]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/emacs-lisp/bindat.el: Allow non-fixed size of `strz`
authorStefan Monnier <monnier@iro.umontreal.ca>
Thu, 15 Apr 2021 15:27:52 +0000 (11:27 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Thu, 15 Apr 2021 15:28:06 +0000 (11:28 -0400)
(bindat--unpack-strz): Allow `len` to be nil.
(bindat--pack-strz): New function.
(bindat--type) <strz>: Make `len` arg optional.
(bindat-type): Adjust debug spec and docstring accordingly.

* doc/lispref/processes.texi (Bindat Types): Adjust accordingly.

doc/lispref/processes.texi
lisp/emacs-lisp/bindat.el

index 6786ac28f9026a8399d41bdfad94fe1850053c54..0dfdac71479e6d727af7040a5a29ec2afbadb32a 100644 (file)
@@ -3410,8 +3410,9 @@ Unsigned integer in little endian order, with @var{bitlen} bits.
 @item str @var{len}
 String of bytes of length @var{len}.
 
-@item strz @var{len}
-Zero-terminated string of bytes, in a fixed-size field with length @var{len}.
+@item strz &optional @var{len}
+Zero-terminated string of bytes, can be of arbitrary length or in a fixed-size
+field with length @var{len}.
 
 @item vec @var{len} [@var{type}]
 Vector of @var{len} elements.  The type of the elements is given by
index 98994963e3e82ea9bf04fc3d425c4bb452c75d3e..247fb91379e56cd8b819a49ae8957f59c573400c 100644 (file)
 
 (defun bindat--unpack-strz (len)
   (let ((i 0) s)
-    (while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
+    (while (and (if len (< i len) t) (/= (aref bindat-raw (+ bindat-idx i)) 0))
       (setq i (1+ i)))
     (setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
     (setq bindat-idx (+ bindat-idx len))
@@ -439,6 +439,12 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
     (aset bindat-raw (+ bindat-idx i) (aref v i)))
   (setq bindat-idx (+ bindat-idx len)))
 
+(defun bindat--pack-strz (v)
+  (let ((len (length v)))
+    (dotimes (i len)
+      (aset bindat-raw (+ bindat-idx i) (aref v i)))
+    (setq bindat-idx (+ bindat-idx len 1))))
+
 (defun bindat--pack-bits (len v)
   (let ((bnum (1- (* 8 len))) j m)
     (while (>= bnum 0)
@@ -677,14 +683,23 @@ is the name of a variable that will hold the value we need to pack.")
     (`(length . ,_) `(cl-incf bindat-idx ,len))
     (`(pack . ,args) `(bindat--pack-str ,len . ,args))))
 
-(cl-defmethod bindat--type (op (_ (eql strz))  len)
+(cl-defmethod bindat--type (op (_ (eql strz))  &optional len)
   (bindat--pcase op
     ('unpack `(bindat--unpack-strz ,len))
-    (`(length . ,_) `(cl-incf bindat-idx ,len))
-    ;; Here we don't add the terminating zero because we rely
-    ;; on the fact that `bindat-raw' was presumably initialized with
-    ;; all-zeroes before we started.
-    (`(pack . ,args) `(bindat--pack-str ,len . ,args))))
+    (`(length ,val)
+     `(cl-incf bindat-idx ,(cond
+                            ((null len) `(length ,val))
+                            ((numberp len) len)
+                            (t `(or ,len (length ,val))))))
+    (`(pack . ,args)
+     (macroexp-let2 nil len len
+       `(if ,len
+            ;; Same as non-zero terminated strings since we don't actually add
+            ;; the terminating zero anyway (because we rely on the fact that
+            ;; `bindat-raw' was presumably initialized with all-zeroes before
+            ;; we started).
+            (bindat--pack-str ,len . ,args)
+          (bindat--pack-strz . ,args))))))
 
 (cl-defmethod bindat--type (op (_ (eql bits))  len)
   (bindat--pcase op
@@ -812,7 +827,7 @@ is the name of a variable that will hold the value we need to pack.")
   '(&or ["uint" def-form]
         ["uintr" def-form]
         ["str" def-form]
-        ["strz" def-form]
+        ["strz" &optional def-form]
         ["bits" def-form]
         ["fill" def-form]
         ["align" def-form]
@@ -832,7 +847,7 @@ TYPE is a Bindat type expression.  It can take the following forms:
   uint BITLEN          - Big-endian unsigned integer
   uintr BITLEN         - Little-endian unsigned integer
   str LEN              - Byte string
-  strz LEN             - Zero-terminated byte-string
+  strz [LEN]           - Zero-terminated byte-string
   bits LEN             - Bit vector (LEN is counted in bytes)
   fill LEN             - Just a filler
   align LEN            - Fill up to the next multiple of LEN bytes