commit f1a790c2efb29a7e1a29c04330c52d8e8883f3f0
parent 4ce4694e85f1d0bf4cd3f96da39a2b2555e3e996
Author: Tomas Hlavaty <tom@logand.com>
Date:   Sat, 10 Aug 2013 16:29:47 +0200
list-printers implemented
Diffstat:
| M | ipp.lisp |  |  | 112 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- | 
1 file changed, 105 insertions(+), 7 deletions(-)
diff --git a/ipp.lisp b/ipp.lisp
@@ -22,7 +22,8 @@
 
 (defpackage :ipp
   (:use :cl)
-  (:export :print-job))
+  (:export :print-job
+           :list-printers))
 
 (in-package :ipp)
 
@@ -266,7 +267,7 @@
                                    :if-exists :supersede
                                    :if-does-not-exist :create)
     (write-ipp data-file request-id operation groups))
-  (funcall ipp-client printer-uri request-file response-file)
+  (funcall ipp-client "application/ipp" printer-uri request-file response-file)
   (with-open-file (*input-stream* response-file :element-type '(unsigned-byte 8))
     (read-ipp request-id)))
 
@@ -312,6 +313,93 @@
            :job-impressions ,job-impressions
            :job-media-sheets ,job-media-sheets))))
 
+(defun stream (x &optional (start 0))
+  (etypecase x
+    (list
+     (dotimes (i start)
+       (pop x))
+     (lambda ()
+       (pop x)))
+    (vector
+     (let ((i start)
+           (n (length x)))
+       (lambda ()
+         (when (< i n)
+           (prog1 (aref x i)
+             (incf i))))))))
+
+(defun char-stream (x &optional (start 0))
+  (dotimes (i start)
+    (read-char x nil nil))
+  (lambda ()
+    (read-char x nil nil)))
+
+(defun byte-stream (x &optional (start 0))
+  (dotimes (i start)
+    (read-byte x nil nil))
+  (lambda ()
+    (read-byte x nil nil)))
+
+(defun next (stream)
+  (funcall stream))
+
+(defun peek (stream)
+  (funcall stream 'peek))
+
+(defun peek-stream (stream)
+  (let (x)
+    (lambda (&optional msg)
+      (ecase msg
+        (peek (or x (setq x (next stream))))
+        ((nil) (prog1 (if x x (next stream))
+                 (setq x nil)))))))
+
+(defun till (stream &optional markers)
+  (let (x)
+    (loop
+       until (member (setq x (next stream)) (or markers '(nil)))
+       collect x)))
+
+;;(till (stream '(0 1 2 3 4) 1) '(3))
+;;(till (stream #(0 1 2 3 4) 1) '(3))
+;;(with-open-file (s "printers.html") (till (char-stream s) '(#\>)))
+
+(defun search-stream (stream needle)
+  (let ((all (till stream)) ;; TODO optimize? use kmp algorithm
+        (start 0))
+    (lambda ()
+      (let ((i (search needle all :start2 start)))
+        (when i
+          (setq start (1+ i))
+          (values i all))))))
+
+#+nil
+(with-open-file (s "printers.html")
+  (till (search-stream (char-stream s) '#.(coerce "/printers/" 'list))))
+
+(defun printer-search-stream (stream)
+  (let* ((k '#.(coerce "\"/printers/" 'list)) ;; TODO #\' as attribute quote
+         (n (length k))
+         (s (search-stream stream k)))
+    (lambda ()
+      (block found
+        (loop
+           (multiple-value-bind (i all) (funcall s)
+             (unless i
+               (return-from found))
+             (let ((z (till (stream all (+ i n)) '(#\"))))
+               (when (and z (char/= #\? (car z)))
+                 (return-from found (coerce z 'string))))))))))
+
+#+nil
+(with-open-file (s "printers.html")
+  (till (printer-search-stream (char-stream s))))
+
+(defun list-printers (ipp-client printer-uri response-file)
+  (funcall ipp-client nil printer-uri nil response-file)
+  (with-open-file (s response-file)
+    (till (printer-search-stream (char-stream s)))))
+
 (defpackage :ipp.wget
   (:use :cl)
   (:export :ipp-client))
@@ -332,11 +420,11 @@
 
 ;;(wget "http://localhost:631/printers/" :response-file "/tmp/a.html")
 
-(defun ipp-client (printer-uri request-file response-file)
+(defun ipp-client (content-type printer-uri request-file response-file)
   (wget printer-uri
         :request-file request-file
         :response-file response-file
-        :content-type "application/ipp"))
+        :content-type content-type))
 
 #+nil
 (ipp:print-job 'ipp-client
@@ -347,6 +435,11 @@
                314
                :requesting-user-name "tomas")
 
+#+nil
+(ipp:list-printers 'ipp-client
+                   "http://localhost:631/printers/"
+                   "printers.html")
+
 (defpackage :ipp.curl
   (:use :cl)
   (:export :ipp-client))
@@ -365,13 +458,13 @@
           `("-H" ,(format nil "Content-Type:~a" content-type)))
      ,url)))
 
-;;(curl "http://localhost:631/printers/" :response-file "/tmp/a.html")
+;;(curl "http://localhost:631/printers/" :response-file "printers.html")
 
-(defun ipp-client (printer-uri request-file response-file)
+(defun ipp-client (content-type printer-uri request-file response-file)
   (curl printer-uri
         :request-file request-file
         :response-file response-file
-        :content-type "application/ipp"))
+        :content-type content-type))
 
 #+nil
 (ipp:print-job 'ipp-client
@@ -381,3 +474,8 @@
                "test.txt"
                314
                :requesting-user-name "tomas")
+
+#+nil
+(ipp:list-printers 'ipp-client
+                   "http://localhost:631/printers/"
+                   "printers.html")