commit b637f2779d1bf89abf77307df38f431e8b9f33c2
parent a2dd25809c045da65c80ff9678d642e882126a6b
Author: Tomas Hlavaty <tom@logand.com>
Date: Sat, 10 Aug 2013 22:25:59 +0200
read|write-value introduced
Diffstat:
M | ipp.lisp | | | 185 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
1 file changed, 127 insertions(+), 58 deletions(-)
diff --git a/ipp.lisp b/ipp.lisp
@@ -66,53 +66,87 @@
;;(tag #x45)
;;(tag :uri)
-(defun attribute-tag (attribute)
- (cdr (assoc attribute '((:attributes-charset . :charset)
- (:attributes-natural-language . :naturalLanguage)
- (:printer-uri . :uri)
- (:requesting-user-name . :nameWithoutLanguage)
- (:job-name . :nameWithoutLanguage)
- (:ipp-attribute-fidelity . :boolean)
- (:document-name . nil)
- (:document-format . nil)
- (:document-natural-language . :naturalLanguage)
- (:compression . nil)
- (:job-k-octets . nil)
- (:job-impressions . nil)
- (:job-media-sheets . nil)))))
+(let ((attributes '((:attributes-charset . :charset)
+ (:attributes-natural-language . :naturalLanguage)
+ (:printer-uri . :uri)
+ (:requesting-user-name . :nameWithoutLanguage)
+ (:job-name . :nameWithoutLanguage)
+ (:ipp-attribute-fidelity . :boolean)
+ (:document-name . nil)
+ (:document-format . nil)
+ (:document-natural-language . :naturalLanguage)
+ (:compression . nil)
+ (:job-k-octets . nil)
+ (:job-impressions . nil)
+ (:job-media-sheets . nil)
+ (:copies . :integer)
+ (:sides . :keyword)
+ (:job-uri . nil)
+ (:job-id . nil)
+ (:job-state . nil)
+ (:job-state-reasons . nil))))
+
+ (defun attribute-tag (attribute)
+ (cdr (assoc attribute attributes)))
+
+ (let ((x (loop
+ for (k) in attributes
+ collect (cons (string-downcase (symbol-name k)) k))))
+ (defun attribute-keyword (string)
+ (or (cdr (assoc string x :test #'equal))
+ (error "unknown attribute ~s" string)))))
;;(attribute-tag :printer-uri)
+;;(attribute-keyword "printer-uri")
(defun attribute-name (attribute)
(format nil "~(~a~)" attribute))
;;(attribute-name :attributes-charset)
+(defun read-text (reader)
+ (octets-to-string (rw:next-octets reader (rw:next-u16 reader))))
+
+(defun read-value (reader tag)
+ (ecase tag
+ ;; :no-value
+ ((:integer :enum)
+ (assert (= 4 (rw:next-u16 reader)))
+ (rw:next-u32 reader))
+ (:boolean
+ (assert (= 1 (rw:next-u16 reader)))
+ (not (zerop (rw:next-u32 reader))))
+ ;; :octetString
+ ;; :dateTime
+ ;; :resolution
+ ;; :rangeOfInteger
+ ((:textWithLanguage
+ :nameWithLanguage
+ :textWithoutLanguage
+ :nameWithoutLanguage
+ :keyword
+ :uri
+ :uriScheme
+ :charset
+ :naturalLanguage
+ :mimeMediaType)
+ (read-text reader))))
+
(defun read-attribute (reader)
- (let ((tag (rw:next-u8 reader)))
- (if (member tag (mapcar 'tag ;; TODO optimize
- '(:operation-attributes-tag
- :job-attributes-tag
- :end-of-attributes-tag
- :printer-attributes-tag
- :unsupported-attributes-tag)))
+ (let ((tag (tag (rw:next-u8 reader))))
+ (if (member tag '(:operation-attributes-tag
+ :job-attributes-tag
+ :end-of-attributes-tag
+ :printer-attributes-tag
+ :unsupported-attributes-tag))
tag
- (flet ((text ()
- (octets-to-string
- (rw:next-octets reader (rw:next-u16 reader)))))
- `(,tag ;;(tag (attribute-tag k))
- ,(text)
- , (case tag ;; TODO handle more cases
- ((33 35)
- (assert (= 4 (rw:next-u16 reader)))
- (rw:next-u32 reader))
- (t (text))))))))
+ (list (attribute-keyword (read-text reader))
+ (read-value reader tag)))))
(defun read-groups (reader)
- (let ((sentinel (tag :end-of-attributes-tag)) ;; TODO optimize
- (x (rw:next-u8 reader)))
+ (let ((x (tag (rw:next-u8 reader))))
(loop
- until (= sentinel x)
+ until (eq :end-of-attributes-tag x)
collect `(,x
,@(loop
while (consp (setq x (read-attribute reader)))
@@ -122,24 +156,51 @@
(with-open-file (s "response.dat" :element-type '(unsigned-byte 8))
(read-ipp (rw:byte-reader s) 314))
+(defun write-text (writer x)
+ (let ((y (string-to-octets x)))
+ (rw:write-u16 writer (length y))
+ (rw:write-octets writer y)))
+
+(defun write-value (writer tag x)
+ (ecase tag
+ ;; :no-value
+ ((:integer :enum)
+ (rw:write-u16 writer 4)
+ (rw:write-u32 writer x))
+ (:boolean
+ (rw:write-u16 writer 1)
+ (rw:write-u8 writer (if x 1 0)))
+ ;; :octetString
+ ;; :dateTime
+ ;; :resolution
+ ;; :rangeOfInteger
+ ((:textWithLanguage
+ :nameWithLanguage
+ :textWithoutLanguage
+ :nameWithoutLanguage
+ :keyword
+ :uri
+ :uriScheme
+ :charset
+ :naturalLanguage
+ :mimeMediaType)
+ (write-text writer x))))
+
(defun write-group (writer group)
(destructuring-bind (group-id &rest plist) group
(when (loop
- for (k v) on plist by #'cddr
+ for (v) on (cdr plist) by #'cddr
when v
do (return t))
(rw:write-u8 writer group-id)
(loop
for (k v) on plist by #'cddr
when v
- do (let ((%k (string-to-octets (attribute-name k)))
- (%v (string-to-octets v)))
+ do (let ((tag (attribute-tag k)))
;; TODO additional value (when v is list)
- (rw:write-u8 writer (tag (attribute-tag k)))
- (rw:write-u16 writer (length %k))
- (rw:write-octets writer %k)
- (rw:write-u16 writer (length %v))
- (rw:write-octets writer %v))))))
+ (rw:write-u8 writer (tag tag))
+ (write-text writer (attribute-name k))
+ (write-value writer tag v))))))
(defun operation-code (operation)
(cdr (assoc operation '((:print-job 1 0 #x0002)
@@ -238,14 +299,16 @@
(attributes-natural-language "en")
(requesting-user-name (user-name))
job-name
- ipp-attribute-fidelity
- document-name
- document-format
- document-natural-language
- compression
- job-k-octets
- job-impressions
- job-media-sheets)
+ (ipp-attribute-fidelity t)
+ ;; document-name
+ ;; document-format
+ ;; document-natural-language
+ ;; compression
+ ;; job-k-octets
+ ;; job-impressions
+ ;; job-media-sheets
+ copies
+ sides)
(ipp ipp-client
printer-uri
request-file
@@ -261,13 +324,15 @@
:requesting-user-name ,requesting-user-name
:job-name ,job-name
:ipp-attribute-fidelity ,ipp-attribute-fidelity
- :document-name ,document-name
- :document-format ,document-format
- :document-natural-language ,document-natural-language
- :compression ,compression
- :job-k-octets ,job-k-octets
- :job-impressions ,job-impressions
- :job-media-sheets ,job-media-sheets))))
+ ;; :document-name ,document-name
+ ;; :document-format ,document-format
+ ;; :document-natural-language ,document-natural-language
+ ;; :compression ,compression
+ ;; :job-k-octets ,job-k-octets
+ ;; :job-impressions ,job-impressions
+ ;; :job-media-sheets ,job-media-sheets
+ :copies ,copies
+ :sides ,sides))))
(defun printer-search-reader (reader)
(let* ((k '#.(coerce "\"/printers/" 'list)) ;; TODO #\' as attribute quote
@@ -379,7 +444,11 @@
"request2.dat"
"response2.dat"
"test.txt"
- 314)
+ 314
+ :ipp-attribute-fidelity nil
+ :copies 2
+ :sides "two-sided-long-edge"
+ )
#+nil
(ipp:list-printers 'ipp-client