diff options
| author | Stefan Monnier | 2021-03-05 13:31:16 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2021-03-05 13:31:16 -0500 |
| commit | 03ada27cb81dabb87eff38f2d66fe8fc4a02da46 (patch) | |
| tree | ee81ebdcc796bc856f5abf485f7861e484b80927 | |
| parent | d582356a7f704f8a209a3ef31d6ea970520c6224 (diff) | |
| download | emacs-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.el | 139 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/bindat-tests.el | 26 |
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, | |||
| 366 | e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." | 371 | e.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 |