commit 1f47d2a91045607faa7a39c8672a4ce9cdfea3fd
parent 978279cd99ad2531a5e1dcbc371ae76cd10d380b
Author: Tomas Hlavaty <tom@logand.com>
Date:   Sun, 18 Aug 2013 00:10:11 +0200
more readers, better skip, till doesnt eat the last item but peeks
Diffstat:
| M | rw.lisp |  |  | 79 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- | 
1 file changed, 60 insertions(+), 19 deletions(-)
diff --git a/rw.lisp b/rw.lisp
@@ -27,6 +27,9 @@
            :char-reader
            :char-writer
            :copy
+           :fibonacci-reader
+           :filter-reader
+           :line-reader
            :next
            :next-octets
            :next-u16
@@ -66,24 +69,12 @@
                     (incf i))))))))
 
 (defun char-reader (stream)
-  (lambda () (read-char stream nil nil)))
+  (lambda ()
+    (read-char stream nil nil)))
 
 (defun byte-reader (stream)
-  (lambda () (read-byte stream nil nil)))
-
-(defun skip (reader n)
-  (dotimes (i n reader)
-    (next reader)))
-
-(defun till (reader &optional markers)
-  (let (x)
-    (loop
-       until (member (setq x (next reader)) (or markers '(nil)))
-       collect x)))
-
-;;(till (skip (reader '(0 1 2 3 4)) 1) '(3))
-;;(till (skip (reader #(0 1 2 3 4)) 1) '(3))
-;;(with-open-file (s "printers.html") (till (char-reader s) '(#\>)))
+  (lambda ()
+    (read-byte stream nil nil)))
 
 (defun peek-reader (reader)
   (let (x)
@@ -93,6 +84,27 @@
         ((nil) (prog1 (if x x (next reader))
                  (setq x nil)))))))
 
+(defun skip (reader &optional n/items)
+  (etypecase n/items
+    (integer
+     (dotimes (i n/items reader)
+       (next reader)))
+    (list
+     (let ((x (or n/items '(#\space #\tab #\newline))))
+       (loop
+          while (member (peek reader) x)
+          do (next reader)))
+     reader)))
+
+(defun till (reader &optional items)
+  (loop
+     while (let ((x (peek reader))) (and x (not (member x items))))
+     collect (next reader)))
+
+;;(till (skip (peek-reader (reader '(0 1 2 3 4))) 1) '(3))
+;;(till (skip (peek-reader (reader #(0 1 2 3 4))) 1) '(3))
+;;(with-open-file (s "/etc/passwd") (till (peek-reader (char-reader s)) '(#\:)))
+
 (defun search-reader (reader needle)
   (let ((all (till reader)) ;; TODO optimize? use kmp algorithm
         (start 0))
@@ -101,9 +113,7 @@
         (setq start (1+ i))
         (values i all)))))
 
-#+nil
-(with-open-file (s "printers.html")
-  (till (search-reader (char-reader s) '#.(coerce "/printers/" 'list))))
+;;(with-open-file (s "/etc/passwd") (till (peek-reader (search-reader (peek-reader (char-reader s)) '#.(coerce "user" 'list)))))
 
 (defun next-u8 (reader)
   (let? x (next reader)
@@ -169,3 +179,34 @@
 
 ;; TODO write-u64|128
 ;; TODO write-s8|16|32|64|128
+
+(defun line-reader (reader)
+  (lambda ()
+    (let ((x (till reader '(#\newline))))
+      (when (next reader)
+        (or x :empty-line)))))
+
+(defun filter-reader (reader predicate)
+  (lambda ()
+    (block found
+      (loop
+         (let ((x (next reader)))
+           (unless x
+             (return-from found nil))
+           (when (funcall predicate x)
+             (return-from found x)))))))
+
+(defun fibonacci-reader (n)
+  (let ((i -1)
+        (z1 0)
+        (z2 1))
+    (lambda ()
+      (incf i)
+      (cond
+        ((<= n i) nil)
+        ((< i 2) i)
+        (t (let ((z (+ z1 z2)))
+             (setq z1 z2
+                   z2 z)))))))
+
+;;(till (peek-reader (fibonacci-reader 10))) => 0 1 1 2 3 5 8 13 21 34