zone.lisp: Some new utilities for handling raw binary strings.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 22 Dec 2014 20:44:10 +0000 (20:44 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 22 Dec 2014 22:23:07 +0000 (22:23 +0000)
zone.lisp

index 5e0b0a9..28ee038 100644 (file)
--- a/zone.lisp
+++ b/zone.lisp
       (when timep
        (format s "~2,'0D:~2,'0D:~2,'0D" hr min sec)))))
 
+(deftype octet () '(unsigned-byte 8))
+(deftype octet-vector (&optional n) `(array octet (,n)))
+
+(defun decode-hex (hex &key (start 0) end)
+  "Decode a hexadecimal-encoded string, returning a vector of octets."
+  (let* ((end (or end (length hex)))
+        (len (- end start))
+        (raw (make-array (floor len 2) :element-type 'octet)))
+    (unless (evenp len)
+      (error "Invalid hex string `~A' (odd length)" hex))
+    (do ((i start (+ i 2)))
+       ((>= i end) raw)
+      (let ((high (digit-char-p (char hex i) 16))
+           (low (digit-char-p (char hex (1+ i)) 16)))
+       (unless (and high low)
+         (error "Invalid hex string `~A' (bad digit)" hex))
+       (setf (aref raw (/ (- i start) 2)) (+ (* 16 high) low))))))
+
+(defun slurp-file (file &optional (element-type 'character))
+  "Read and return the contents of FILE as a vector."
+  (with-open-file (in file :element-type element-type)
+    (let ((buf (make-array 1024 :element-type element-type))
+         (pos 0))
+      (loop
+       (let ((end (read-sequence buf in :start pos)))
+         (when (< end (length buf))
+           (return (adjust-array buf end)))
+         (setf pos end
+               buf (adjust-array buf (* 2 pos))))))))
+
 (defmacro defenum (name (&key export) &body values)
   "Set up symbol properties for manifest constants.
 
                    (do ((new (* 2 have) (* 2 new)))
                        ((<= want new) new))))))
 
+(export 'rec-octet-vector)
+(defun rec-octet-vector (vector &key (start 0) end)
+  "Copy (part of) the VECTOR to the output."
+  (let* ((end (or end (length vector)))
+        (len (- end start)))
+    (rec-ensure len)
+    (do ((i start (1+ i)))
+       ((>= i end))
+      (vector-push (aref vector i) *record-vector*))))
+
 (export 'rec-byte)
 (defun rec-byte (octets value)
   "Append an unsigned byte, OCTETS octets wide, with VALUE, to the record."