emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 0c3ce42: * lisp/emacs-lisp/bindat.el: Allow non-fixed size of `st


From: Stefan Monnier
Subject: master 0c3ce42: * lisp/emacs-lisp/bindat.el: Allow non-fixed size of `strz`
Date: Thu, 15 Apr 2021 11:28:10 -0400 (EDT)

branch: master
commit 0c3ce42c8f12f1865a3327448bc58f472f153bf9
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    * lisp/emacs-lisp/bindat.el: Allow non-fixed size of `strz`
    
    (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 |  5 +++--
 lisp/emacs-lisp/bindat.el  | 33 ++++++++++++++++++++++++---------
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 6786ac2..0dfdac7 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -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
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 9899496..247fb91 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -167,7 +167,7 @@
 
 (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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]