From: Mark Wooding Date: Mon, 22 Dec 2014 20:44:10 +0000 (+0000) Subject: zone.lisp: Some new utilities for handling raw binary strings. X-Git-Url: https://git.distorted.org.uk/~mdw/zone/commitdiff_plain/2c446779a47154be4f7431c8a07e3a203f381899 zone.lisp: Some new utilities for handling raw binary strings. --- diff --git a/zone.lisp b/zone.lisp index 5e0b0a9..28ee038 100644 --- a/zone.lisp +++ b/zone.lisp @@ -111,6 +111,36 @@ (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. @@ -690,6 +720,16 @@ (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."