[cl-utilities-cvs] CVS update: cl-utilities/read-delimited.lisp
Peter Scott
pscott at common-lisp.net
Thu May 26 19:46:47 UTC 2005
Update of /project/cl-utilities/cvsroot/cl-utilities
In directory common-lisp.net:/tmp/cvs-serv5758
Modified Files:
read-delimited.lisp
Log Message:
Major refactoring. It now does exactly the same thing as it used to,
but now it does it in such a way that I'm not afraid of its source
code.
Date: Thu May 26 21:46:46 2005
Author: pscott
Index: cl-utilities/read-delimited.lisp
diff -u cl-utilities/read-delimited.lisp:1.1.1.1 cl-utilities/read-delimited.lisp:1.2
--- cl-utilities/read-delimited.lisp:1.1.1.1 Mon May 9 23:26:29 2005
+++ cl-utilities/read-delimited.lisp Thu May 26 21:46:46 2005
@@ -1,5 +1,25 @@
(in-package :cl-utilities)
+(defun read-delimited (sequence stream &key (start 0) end
+ (delimiter #\Newline) (test #'eql) (key #'identity))
+ ;; Check bounds on SEQUENCE
+ (multiple-value-setq (start end)
+ (%read-delimited-bounds-check sequence start end))
+ ;; Loop until we run out of input characters or places to put them,
+ ;; or until we encounter the delimiter.
+ (loop for index from start
+ for char = (read-char stream nil nil)
+ for test-result = (funcall test (funcall key char) delimiter)
+ while (and char
+ (< index end)
+ (not test-result))
+ do (setf (elt sequence index) char)
+ finally (return-from read-delimited
+ (values index test-result))))
+
+;; Conditions
+;;;;;;;;;;;;;
+
(define-condition read-delimited-bounds-error (error)
((start :initarg :start :reader read-delimited-bounds-error-start)
(end :initarg :end :reader read-delimited-bounds-error-end)
@@ -11,41 +31,48 @@
(:documentation "There's a problem with the indices START and END
for SEQUENCE. See CLHS SUBSEQ-OUT-OF-BOUNDS:IS-AN-ERROR issue."))
-(defun read-delimited (sequence stream &key (start 0) end
- (delimiter #\Newline) (test #'eql) key)
- ;; Check to make sure END is in bounds
- (when (and end (> end (length sequence)))
+;; Error checking for bounds
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun %read-delimited-bounds-check (sequence start end)
+ "Check to make sure START and END are in bounds when calling
+READ-DELIMITED with SEQUENCE"
+ (check-type start (or integer null))
+ (check-type end (or integer null))
+ (let ((start (%read-delimited-bounds-check-start sequence start end))
+ (end (%read-delimited-bounds-check-end sequence start end)))
+ ;; Returns (values start end)
+ (%read-delimited-bounds-check-order sequence start end)))
+
+(defun %read-delimited-bounds-check-order (sequence start end)
+ "Check the order of START and END bounds, and return them in the
+correct order."
+ (when (< end start)
(restart-case (error 'read-delimited-bounds-error
:start start :end end :sequence sequence)
(continue ()
- :report "Use default instead"
- (setf end nil))))
- ;; Check to make sure START is in bounds
+ :report "Switch start and end"
+ (rotatef start end))))
+ (values start end))
+
+(defun %read-delimited-bounds-check-start (sequence start end)
+ "Check to make sure START is in bounds when calling READ-DELIMITED
+with SEQUENCE"
(when (and start (< start 0))
(restart-case (error 'read-delimited-bounds-error
:start start :end end :sequence sequence)
(continue ()
- :report "Use default instead"
+ :report "Use default for START instead"
(setf start 0))))
- (let ((key (or key #'identity))
- (end (or end (length sequence))))
- ;; START and END should be positive integers by now
- (check-type start unsigned-byte)
- (check-type end unsigned-byte)
- ;; Check to make sure that START < END
- (when (< end start)
- (restart-case (error 'read-delimited-bounds-error
- :start start :end end :sequence sequence)
- (continue ()
- :report "Switch start and end"
- (rotatef start end))))
- ;; Actually do the looping
- (loop for index from start
- for char = (read-char stream nil nil)
- for test-result = (funcall test (funcall key char) delimiter)
- while (and char
- (< index end)
- (not test-result))
- do (setf (elt sequence index) char)
- finally (return-from read-delimited
- (values index test-result)))))
\ No newline at end of file
+ start)
+
+(defun %read-delimited-bounds-check-end (sequence start end)
+ "Check to make sure END is in bounds when calling READ-DELIMITED
+with SEQUENCE"
+ (when (and end (> end (length sequence)))
+ (restart-case (error 'read-delimited-bounds-error
+ :start start :end end :sequence sequence)
+ (continue ()
+ :report "Use default for END instead"
+ (setf end nil))))
+ (or end (length sequence)))
\ No newline at end of file
More information about the Cl-utilities-cvs
mailing list