aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2021-03-05 13:31:16 -0500
committerStefan Monnier2021-03-05 13:31:16 -0500
commit03ada27cb81dabb87eff38f2d66fe8fc4a02da46 (patch)
treeee81ebdcc796bc856f5abf485f7861e484b80927
parentd582356a7f704f8a209a3ef31d6ea970520c6224 (diff)
downloademacs-03ada27cb81dabb87eff38f2d66fe8fc4a02da46.tar.gz
emacs-03ada27cb81dabb87eff38f2d66fe8fc4a02da46.zip
* lisp/emacs-lisp/bindat.el: Minor refactoring
(bindat--unpack-str, bindat--unpack-strz, bindat--unpack-bits): New functions, extracted from `bindat--unpack-item`. (bindat--unpack-item): Use them. (bindat--align): New function. (bindat--unpack-group, bindat--length-group, bindat--pack-group): Use it. (bindat-get-field): Allow integers to index both lists (as returned by `repeat`) and vectors (as returned by `vec`). (bindat--pack-str, bindat--pack-bits): New functions, extracted from `bindat--pack-item`. (bindat--pack-item): Use them. * test/lisp/emacs-lisp/bindat-tests.el (struct-bindat): Place the fields in the order in which they appear in the structs.
-rw-r--r--lisp/emacs-lisp/bindat.el139
-rw-r--r--test/lisp/emacs-lisp/bindat-tests.el26
2 files changed, 83 insertions, 82 deletions
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index b1b2144e3de..830e61f8516 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -201,7 +201,7 @@
201(defvar bindat-raw) 201(defvar bindat-raw)
202(defvar bindat-idx) 202(defvar bindat-idx)
203 203
204(defun bindat--unpack-u8 () 204(defsubst bindat--unpack-u8 ()
205 (prog1 205 (prog1
206 (aref bindat-raw bindat-idx) 206 (aref bindat-raw bindat-idx)
207 (setq bindat-idx (1+ bindat-idx)))) 207 (setq bindat-idx (1+ bindat-idx))))
@@ -230,47 +230,50 @@
230(defun bindat--unpack-u64r () 230(defun bindat--unpack-u64r ()
231 (logior (bindat--unpack-u32r) (ash (bindat--unpack-u32r) 32))) 231 (logior (bindat--unpack-u32r) (ash (bindat--unpack-u32r) 32)))
232 232
233(defun bindat--unpack-str (len)
234 (let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
235 (setq bindat-idx (+ bindat-idx len))
236 (if (stringp s) s
237 (apply #'unibyte-string s))))
238
239(defun bindat--unpack-strz (len)
240 (let ((i 0) s)
241 (while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
242 (setq i (1+ i)))
243 (setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
244 (setq bindat-idx (+ bindat-idx len))
245 (if (stringp s) s
246 (apply #'unibyte-string s))))
247
248(defun bindat--unpack-bits (len)
249 (let ((bits nil) (bnum (1- (* 8 len))) j m)
250 (while (>= bnum 0)
251 (if (= (setq m (bindat--unpack-u8)) 0)
252 (setq bnum (- bnum 8))
253 (setq j 128)
254 (while (> j 0)
255 (if (/= 0 (logand m j))
256 (setq bits (cons bnum bits)))
257 (setq bnum (1- bnum)
258 j (ash j -1)))))
259 bits))
260
233(defun bindat--unpack-item (type len &optional vectype) 261(defun bindat--unpack-item (type len &optional vectype)
234 (if (eq type 'ip) 262 (if (eq type 'ip)
235 (setq type 'vec len 4)) 263 (setq type 'vec len 4))
236 (pcase type 264 (pcase type
237 ((or 'u8 'byte) 265 ((or 'u8 'byte) (bindat--unpack-u8))
238 (bindat--unpack-u8)) 266 ((or 'u16 'word 'short) (bindat--unpack-u16))
239 ((or 'u16 'word 'short)
240 (bindat--unpack-u16))
241 ('u24 (bindat--unpack-u24)) 267 ('u24 (bindat--unpack-u24))
242 ((or 'u32 'dword 'long) 268 ((or 'u32 'dword 'long) (bindat--unpack-u32))
243 (bindat--unpack-u32))
244 ('u64 (bindat--unpack-u64)) 269 ('u64 (bindat--unpack-u64))
245 ('u16r (bindat--unpack-u16r)) 270 ('u16r (bindat--unpack-u16r))
246 ('u24r (bindat--unpack-u24r)) 271 ('u24r (bindat--unpack-u24r))
247 ('u32r (bindat--unpack-u32r)) 272 ('u32r (bindat--unpack-u32r))
248 ('u64r (bindat--unpack-u64r)) 273 ('u64r (bindat--unpack-u64r))
249 ('bits 274 ('bits (bindat--unpack-bits len))
250 (let ((bits nil) (bnum (1- (* 8 len))) j m) 275 ('str (bindat--unpack-str len))
251 (while (>= bnum 0) 276 ('strz (bindat--unpack-strz len))
252 (if (= (setq m (bindat--unpack-u8)) 0)
253 (setq bnum (- bnum 8))
254 (setq j 128)
255 (while (> j 0)
256 (if (/= 0 (logand m j))
257 (setq bits (cons bnum bits)))
258 (setq bnum (1- bnum)
259 j (ash j -1)))))
260 bits))
261 ('str
262 (let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
263 (setq bindat-idx (+ bindat-idx len))
264 (if (stringp s) s
265 (apply #'unibyte-string s))))
266 ('strz
267 (let ((i 0) s)
268 (while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
269 (setq i (1+ i)))
270 (setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
271 (setq bindat-idx (+ bindat-idx len))
272 (if (stringp s) s
273 (apply #'unibyte-string s))))
274 ('vec 277 ('vec
275 (let ((v (make-vector len 0)) (vlen 1)) 278 (let ((v (make-vector len 0)) (vlen 1))
276 (if (consp vectype) 279 (if (consp vectype)
@@ -283,6 +286,9 @@
283 v)) 286 v))
284 (_ nil))) 287 (_ nil)))
285 288
289(defsubst bindat--align (n len)
290 (* len (/ (+ n (1- len)) len))) ;Isn't there a simpler way?
291
286(defun bindat--unpack-group (spec) 292(defun bindat--unpack-group (spec)
287 (with-suppressed-warnings ((lexical struct last)) 293 (with-suppressed-warnings ((lexical struct last))
288 (defvar struct) (defvar last)) 294 (defvar struct) (defvar last))
@@ -317,8 +323,7 @@
317 ('fill 323 ('fill
318 (setq bindat-idx (+ bindat-idx len))) 324 (setq bindat-idx (+ bindat-idx len)))
319 ('align 325 ('align
320 (while (/= (% bindat-idx len) 0) 326 (setq bindat-idx (bindat--align bindat-idx len)))
321 (setq bindat-idx (1+ bindat-idx))))
322 ('struct 327 ('struct
323 (setq data (bindat--unpack-group (eval len t)))) 328 (setq data (bindat--unpack-group (eval len t))))
324 ('repeat 329 ('repeat
@@ -366,9 +371,8 @@ An integer value in the field list is taken as an array index,
366e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." 371e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
367 (while (and struct field) 372 (while (and struct field)
368 (setq struct (if (integerp (car field)) 373 (setq struct (if (integerp (car field))
369 (nth (car field) struct) 374 (elt struct (car field))
370 (let ((val (assq (car field) struct))) 375 (cdr (assq (car field) struct))))
371 (if (consp val) (cdr val)))))
372 (setq field (cdr field))) 376 (setq field (cdr field)))
373 struct) 377 struct)
374 378
@@ -421,8 +425,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
421 ('fill 425 ('fill
422 (setq bindat-idx (+ bindat-idx len))) 426 (setq bindat-idx (+ bindat-idx len)))
423 ('align 427 ('align
424 (while (/= (% bindat-idx len) 0) 428 (setq bindat-idx (bindat--align bindat-idx len)))
425 (setq bindat-idx (1+ bindat-idx))))
426 ('struct 429 ('struct
427 (bindat--length-group 430 (bindat--length-group
428 (if field (bindat-get-field struct field) struct) (eval len t))) 431 (if field (bindat-get-field struct field) struct) (eval len t)))
@@ -460,7 +463,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
460 463
461;;;; Pack structured data into bindat-raw 464;;;; Pack structured data into bindat-raw
462 465
463(defun bindat--pack-u8 (v) 466(defsubst bindat--pack-u8 (v)
464 (aset bindat-raw bindat-idx (logand v 255)) 467 (aset bindat-raw bindat-idx (logand v 255))
465 (setq bindat-idx (1+ bindat-idx))) 468 (setq bindat-idx (1+ bindat-idx)))
466 469
@@ -498,42 +501,41 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
498 (bindat--pack-u32r v) 501 (bindat--pack-u32r v)
499 (bindat--pack-u32r (ash v -32))) 502 (bindat--pack-u32r (ash v -32)))
500 503
504(defun bindat--pack-str (len v)
505 (dotimes (i (min len (length v)))
506 (aset bindat-raw (+ bindat-idx i) (aref v i)))
507 (setq bindat-idx (+ bindat-idx len)))
508
509(defun bindat--pack-bits (len v)
510 (let ((bnum (1- (* 8 len))) j m)
511 (while (>= bnum 0)
512 (setq m 0)
513 (if (null v)
514 (setq bnum (- bnum 8))
515 (setq j 128)
516 (while (> j 0)
517 (if (memq bnum v)
518 (setq m (logior m j)))
519 (setq bnum (1- bnum)
520 j (ash j -1))))
521 (bindat--pack-u8 m))))
522
501(defun bindat--pack-item (v type len &optional vectype) 523(defun bindat--pack-item (v type len &optional vectype)
502 (if (eq type 'ip) 524 (if (eq type 'ip)
503 (setq type 'vec len 4)) 525 (setq type 'vec len 4))
504 (pcase type 526 (pcase type
505 ((guard (null v)) 527 ((guard (null v)) (setq bindat-idx (+ bindat-idx len)))
506 (setq bindat-idx (+ bindat-idx len))) 528 ((or 'u8 'byte) (bindat--pack-u8 v))
507 ((or 'u8 'byte) 529 ((or 'u16 'word 'short) (bindat--pack-u16 v))
508 (bindat--pack-u8 v)) 530 ('u24 (bindat--pack-u24 v))
509 ((or 'u16 'word 'short) 531 ((or 'u32 'dword 'long) (bindat--pack-u32 v))
510 (bindat--pack-u16 v))
511 ('u24
512 (bindat--pack-u24 v))
513 ((or 'u32 'dword 'long)
514 (bindat--pack-u32 v))
515 ('u64 (bindat--pack-u64 v)) 532 ('u64 (bindat--pack-u64 v))
516 ('u16r (bindat--pack-u16r v)) 533 ('u16r (bindat--pack-u16r v))
517 ('u24r (bindat--pack-u24r v)) 534 ('u24r (bindat--pack-u24r v))
518 ('u32r (bindat--pack-u32r v)) 535 ('u32r (bindat--pack-u32r v))
519 ('u64r (bindat--pack-u64r v)) 536 ('u64r (bindat--pack-u64r v))
520 ('bits 537 ('bits (bindat--pack-bits len v))
521 (let ((bnum (1- (* 8 len))) j m) 538 ((or 'str 'strz) (bindat--pack-str len v))
522 (while (>= bnum 0)
523 (setq m 0)
524 (if (null v)
525 (setq bnum (- bnum 8))
526 (setq j 128)
527 (while (> j 0)
528 (if (memq bnum v)
529 (setq m (logior m j)))
530 (setq bnum (1- bnum)
531 j (ash j -1))))
532 (bindat--pack-u8 m))))
533 ((or 'str 'strz)
534 (dotimes (i (min len (length v)))
535 (aset bindat-raw (+ bindat-idx i) (aref v i)))
536 (setq bindat-idx (+ bindat-idx len)))
537 ('vec 539 ('vec
538 (let ((l (length v)) (vlen 1)) 540 (let ((l (length v)) (vlen 1))
539 (if (consp vectype) 541 (if (consp vectype)
@@ -580,8 +582,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
580 ('fill 582 ('fill
581 (setq bindat-idx (+ bindat-idx len))) 583 (setq bindat-idx (+ bindat-idx len)))
582 ('align 584 ('align
583 (while (/= (% bindat-idx len) 0) 585 (setq bindat-idx (bindat--align bindat-idx len)))
584 (setq bindat-idx (1+ bindat-idx))))
585 ('struct 586 ('struct
586 (bindat--pack-group 587 (bindat--pack-group
587 (if field (bindat-get-field struct field) struct) (eval len t))) 588 (if field (bindat-get-field struct field) struct) (eval len t)))
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 72883fc2ec7..9c417c855c7 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,4 +1,4 @@
1;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t; coding: utf-8; -*- 1;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2019-2021 Free Software Foundation, Inc. 3;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
4 4
@@ -23,14 +23,14 @@
23(require 'bindat) 23(require 'bindat)
24(require 'cl-lib) 24(require 'cl-lib)
25 25
26(defvar header-bindat-spec 26(defconst header-bindat-spec
27 (bindat-spec 27 (bindat-spec
28 (dest-ip ip) 28 (dest-ip ip)
29 (src-ip ip) 29 (src-ip ip)
30 (dest-port u16) 30 (dest-port u16)
31 (src-port u16))) 31 (src-port u16)))
32 32
33(defvar data-bindat-spec 33(defconst data-bindat-spec
34 (bindat-spec 34 (bindat-spec
35 (type u8) 35 (type u8)
36 (opcode u8) 36 (opcode u8)
@@ -39,7 +39,7 @@
39 (data vec (length)) 39 (data vec (length))
40 (align 4))) 40 (align 4)))
41 41
42(defvar packet-bindat-spec 42(defconst packet-bindat-spec
43 (bindat-spec 43 (bindat-spec
44 (header struct header-bindat-spec) 44 (header struct header-bindat-spec)
45 (items u8) 45 (items u8)
@@ -47,23 +47,23 @@
47 (item repeat (items) 47 (item repeat (items)
48 (struct data-bindat-spec)))) 48 (struct data-bindat-spec))))
49 49
50(defvar struct-bindat 50(defconst struct-bindat
51 '((header 51 '((header
52 (dest-ip . [192 168 1 100]) 52 (dest-ip . [192 168 1 100])
53 (src-ip . [192 168 1 101]) 53 (src-ip . [192 168 1 101])
54 (dest-port . 284) 54 (dest-port . 284)
55 (src-port . 5408)) 55 (src-port . 5408))
56 (items . 2) 56 (items . 2)
57 (item ((data . [1 2 3 4 5]) 57 (item ((type . 2)
58 (id . "ABCDEF")
59 (length . 5)
60 (opcode . 3) 58 (opcode . 3)
61 (type . 2)) 59 (length . 5)
62 ((data . [6 7 8 9 10 11 12]) 60 (id . "ABCDEF")
63 (id . "BCDEFG") 61 (data . [1 2 3 4 5]))
64 (length . 7) 62 ((type . 1)
65 (opcode . 4) 63 (opcode . 4)
66 (type . 1))))) 64 (length . 7)
65 (id . "BCDEFG")
66 (data . [6 7 8 9 10 11 12])))))
67 67
68(ert-deftest bindat-test-pack () 68(ert-deftest bindat-test-pack ()
69 (should (equal 69 (should (equal