Mercurial > emacs
comparison lisp/emacs-lisp/bindat.el @ 75994:1879f509b310
(bindat--unpack-u*): Optimize.
(bindat--unpack-item, bindat--length-group, bindat--pack-item)
(bindat--unpack-group, bindat--pack-group):
Handle vectors with optional element type.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Sat, 17 Feb 2007 22:02:25 +0000 |
parents | 7a3f13e2dd57 |
children | 935157c0b596 dd7c098af727 |
comparison
equal
deleted
inserted
replaced
75993:b980e6c73752 | 75994:1879f509b310 |
---|---|
145 ;; | u24 -- 3-byte value | 145 ;; | u24 -- 3-byte value |
146 ;; | u32 | dword | long -- length 4, network byte order | 146 ;; | u32 | dword | long -- length 4, network byte order |
147 ;; | u16r | u24r | u32r -- little endian byte order. | 147 ;; | u16r | u24r | u32r -- little endian byte order. |
148 ;; | str LEN -- LEN byte string | 148 ;; | str LEN -- LEN byte string |
149 ;; | strz LEN -- LEN byte (zero-terminated) string | 149 ;; | strz LEN -- LEN byte (zero-terminated) string |
150 ;; | vec LEN -- LEN byte vector | 150 ;; | vec LEN [TYPE] -- vector of LEN items of TYPE (default: u8) |
151 ;; | ip -- 4 byte vector | 151 ;; | ip -- 4 byte vector |
152 ;; | bits LEN -- List with bits set in LEN bytes. | 152 ;; | bits LEN -- List with bits set in LEN bytes. |
153 ;; | 153 ;; |
154 ;; -- Note: 32 bit values may be limited by emacs' INTEGER | 154 ;; -- Note: 32 bit values may be limited by emacs' INTEGER |
155 ;; implementation limits. | 155 ;; implementation limits. |
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)))) |
208 | 208 |
209 (defun bindat--unpack-u16 () | 209 (defun bindat--unpack-u16 () |
210 (let* ((a (bindat--unpack-u8)) (b (bindat--unpack-u8))) | 210 (logior (lsh (bindat--unpack-u8) 8) (bindat--unpack-u8))) |
211 (logior (lsh a 8) b))) | |
212 | 211 |
213 (defun bindat--unpack-u24 () | 212 (defun bindat--unpack-u24 () |
214 (let* ((a (bindat--unpack-u16)) (b (bindat--unpack-u8))) | 213 (logior (lsh (bindat--unpack-u16) 8) (bindat--unpack-u8))) |
215 (logior (lsh a 8) b))) | |
216 | 214 |
217 (defun bindat--unpack-u32 () | 215 (defun bindat--unpack-u32 () |
218 (let* ((a (bindat--unpack-u16)) (b (bindat--unpack-u16))) | 216 (logior (lsh (bindat--unpack-u16) 16) (bindat--unpack-u16))) |
219 (logior (lsh a 16) b))) | |
220 | 217 |
221 (defun bindat--unpack-u16r () | 218 (defun bindat--unpack-u16r () |
222 (let* ((a (bindat--unpack-u8)) (b (bindat--unpack-u8))) | 219 (logior (bindat--unpack-u8) (lsh (bindat--unpack-u8) 8))) |
223 (logior a (lsh b 8)))) | |
224 | 220 |
225 (defun bindat--unpack-u24r () | 221 (defun bindat--unpack-u24r () |
226 (let* ((a (bindat--unpack-u16r)) (b (bindat--unpack-u8))) | 222 (logior (bindat--unpack-u16r) (lsh (bindat--unpack-u8) 16))) |
227 (logior a (lsh b 16)))) | |
228 | 223 |
229 (defun bindat--unpack-u32r () | 224 (defun bindat--unpack-u32r () |
230 (let* ((a (bindat--unpack-u16r)) (b (bindat--unpack-u16r))) | 225 (logior (bindat--unpack-u16r) (lsh (bindat--unpack-u16r) 16))) |
231 (logior a (lsh b 16)))) | 226 |
232 | 227 (defun bindat--unpack-item (type len &optional vectype) |
233 (defun bindat--unpack-item (type len) | |
234 (if (eq type 'ip) | 228 (if (eq type 'ip) |
235 (setq type 'vec len 4)) | 229 (setq type 'vec len 4)) |
236 (cond | 230 (cond |
237 ((memq type '(u8 byte)) | 231 ((memq type '(u8 byte)) |
238 (bindat--unpack-u8)) | 232 (bindat--unpack-u8)) |
272 (setq s (substring bindat-raw bindat-idx (+ bindat-idx i))) | 266 (setq s (substring bindat-raw bindat-idx (+ bindat-idx i))) |
273 (setq bindat-idx (+ bindat-idx len)) | 267 (setq bindat-idx (+ bindat-idx len)) |
274 (if (stringp s) s | 268 (if (stringp s) s |
275 (string-make-unibyte (concat s))))) | 269 (string-make-unibyte (concat s))))) |
276 ((eq type 'vec) | 270 ((eq type 'vec) |
277 (let ((v (make-vector len 0)) (i 0)) | 271 (let ((v (make-vector len 0)) (i 0) (vlen 1)) |
272 (if (consp vectype) | |
273 (setq vlen (nth 1 vectype) | |
274 vectype (nth 2 vectype)) | |
275 (setq type (or vectype 'u8) | |
276 vectype nil)) | |
278 (while (< i len) | 277 (while (< i len) |
279 (aset v i (bindat--unpack-u8)) | 278 (aset v i (bindat--unpack-item type vlen vectype)) |
280 (setq i (1+ i))) | 279 (setq i (1+ i))) |
281 v)) | 280 v)) |
282 (t nil))) | 281 (t nil))) |
283 | 282 |
284 (defun bindat--unpack-group (spec) | 283 (defun bindat--unpack-group (spec) |
286 (while spec | 285 (while spec |
287 (let* ((item (car spec)) | 286 (let* ((item (car spec)) |
288 (field (car item)) | 287 (field (car item)) |
289 (type (nth 1 item)) | 288 (type (nth 1 item)) |
290 (len (nth 2 item)) | 289 (len (nth 2 item)) |
290 (vectype (and (eq type 'vec) (nth 3 item))) | |
291 (tail 3) | 291 (tail 3) |
292 data) | 292 data) |
293 (setq spec (cdr spec)) | 293 (setq spec (cdr spec)) |
294 (if (and (consp field) (eq (car field) 'eval)) | 294 (if (and (consp field) (eq (car field) 'eval)) |
295 (setq field (eval (car (cdr field))))) | 295 (setq field (eval (car (cdr field))))) |
333 (if (or (equal cc tag) (equal cc t) | 333 (if (or (equal cc tag) (equal cc t) |
334 (and (consp cc) (eval cc))) | 334 (and (consp cc) (eval cc))) |
335 (setq data (bindat--unpack-group (cdr case)) | 335 (setq data (bindat--unpack-group (cdr case)) |
336 cases nil))))) | 336 cases nil))))) |
337 (t | 337 (t |
338 (setq data (bindat--unpack-item type len) | 338 (setq data (bindat--unpack-item type len vectype) |
339 last data))) | 339 last data))) |
340 (if data | 340 (if data |
341 (if field | 341 (if field |
342 (setq struct (cons (cons field data) struct)) | 342 (setq struct (cons (cons field data) struct)) |
343 (setq struct (append data struct)))))) | 343 (setq struct (append data struct)))))) |
382 (while spec | 382 (while spec |
383 (let* ((item (car spec)) | 383 (let* ((item (car spec)) |
384 (field (car item)) | 384 (field (car item)) |
385 (type (nth 1 item)) | 385 (type (nth 1 item)) |
386 (len (nth 2 item)) | 386 (len (nth 2 item)) |
387 (vectype (and (eq type 'vec) (nth 3 item))) | |
387 (tail 3)) | 388 (tail 3)) |
388 (setq spec (cdr spec)) | 389 (setq spec (cdr spec)) |
389 (if (and (consp field) (eq (car field) 'eval)) | 390 (if (and (consp field) (eq (car field) 'eval)) |
390 (setq field (eval (car (cdr field))))) | 391 (setq field (eval (car (cdr field))))) |
391 (if (and type (consp type) (eq (car type) 'eval)) | 392 (if (and type (consp type) (eq (car type) 'eval)) |
399 field nil)) | 400 field nil)) |
400 (if (and (consp len) (not (eq type 'eval))) | 401 (if (and (consp len) (not (eq type 'eval))) |
401 (setq len (apply 'bindat-get-field struct len))) | 402 (setq len (apply 'bindat-get-field struct len))) |
402 (if (not len) | 403 (if (not len) |
403 (setq len 1)) | 404 (setq len 1)) |
405 (while (eq type 'vec) | |
406 (let ((vlen 1)) | |
407 (if (consp vectype) | |
408 (setq len (* len (nth 1 vectype)) | |
409 type (nth 2 vectype)) | |
410 (setq type (or vectype 'u8) | |
411 vectype nil)))) | |
404 (cond | 412 (cond |
405 ((eq type 'eval) | 413 ((eq type 'eval) |
406 (if field | 414 (if field |
407 (setq struct (cons (cons field (eval len)) struct)) | 415 (setq struct (cons (cons field (eval len)) struct)) |
408 (eval len))) | 416 (eval len))) |
432 (progn | 440 (progn |
433 (bindat--length-group struct (cdr case)) | 441 (bindat--length-group struct (cdr case)) |
434 (setq cases nil)))))) | 442 (setq cases nil)))))) |
435 (t | 443 (t |
436 (if (setq type (assq type bindat--fixed-length-alist)) | 444 (if (setq type (assq type bindat--fixed-length-alist)) |
437 (setq len (cdr type))) | 445 (setq len (* len (cdr type)))) |
438 (if field | 446 (if field |
439 (setq last (bindat-get-field struct field))) | 447 (setq last (bindat-get-field struct field))) |
440 (setq bindat-idx (+ bindat-idx len)))))))) | 448 (setq bindat-idx (+ bindat-idx len)))))))) |
441 | 449 |
442 (defun bindat-length (spec struct) | 450 (defun bindat-length (spec struct) |
476 | 484 |
477 (defun bindat--pack-u32r (v) | 485 (defun bindat--pack-u32r (v) |
478 (bindat--pack-u16r v) | 486 (bindat--pack-u16r v) |
479 (bindat--pack-u16r (lsh v -16))) | 487 (bindat--pack-u16r (lsh v -16))) |
480 | 488 |
481 (defun bindat--pack-item (v type len) | 489 (defun bindat--pack-item (v type len &optional vectype) |
482 (if (eq type 'ip) | 490 (if (eq type 'ip) |
483 (setq type 'vec len 4)) | 491 (setq type 'vec len 4)) |
484 (cond | 492 (cond |
485 ((null v) | 493 ((null v) |
486 (setq bindat-idx (+ bindat-idx len))) | 494 (setq bindat-idx (+ bindat-idx len))) |
509 (if (memq bnum v) | 517 (if (memq bnum v) |
510 (setq m (logior m j))) | 518 (setq m (logior m j))) |
511 (setq bnum (1- bnum) | 519 (setq bnum (1- bnum) |
512 j (lsh j -1)))) | 520 j (lsh j -1)))) |
513 (bindat--pack-u8 m)))) | 521 (bindat--pack-u8 m)))) |
514 ((memq type '(str strz vec)) | 522 ((memq type '(str strz)) |
515 (let ((l (length v)) (i 0)) | 523 (let ((l (length v)) (i 0)) |
516 (if (> l len) (setq l len)) | 524 (if (> l len) (setq l len)) |
517 (while (< i l) | 525 (while (< i l) |
518 (aset bindat-raw (+ bindat-idx i) (aref v i)) | 526 (aset bindat-raw (+ bindat-idx i) (aref v i)) |
519 (setq i (1+ i))) | 527 (setq i (1+ i))) |
520 (setq bindat-idx (+ bindat-idx len)))) | 528 (setq bindat-idx (+ bindat-idx len)))) |
529 ((eq type 'vec) | |
530 (let ((l (length v)) (i 0) (vlen 1)) | |
531 (if (consp vectype) | |
532 (setq vlen (nth 1 vectype) | |
533 vectype (nth 2 vectype)) | |
534 (setq type (or vectype 'u8) | |
535 vectype nil)) | |
536 (if (> l len) (setq l len)) | |
537 (while (< i l) | |
538 (bindat--pack-item (aref v i) type vlen vectype) | |
539 (setq i (1+ i))))) | |
521 (t | 540 (t |
522 (setq bindat-idx (+ bindat-idx len))))) | 541 (setq bindat-idx (+ bindat-idx len))))) |
523 | 542 |
524 (defun bindat--pack-group (struct spec) | 543 (defun bindat--pack-group (struct spec) |
525 (let (last) | 544 (let (last) |
526 (while spec | 545 (while spec |
527 (let* ((item (car spec)) | 546 (let* ((item (car spec)) |
528 (field (car item)) | 547 (field (car item)) |
529 (type (nth 1 item)) | 548 (type (nth 1 item)) |
530 (len (nth 2 item)) | 549 (len (nth 2 item)) |
550 (vectype (and (eq type 'vec) (nth 3 item))) | |
531 (tail 3)) | 551 (tail 3)) |
532 (setq spec (cdr spec)) | 552 (setq spec (cdr spec)) |
533 (if (and (consp field) (eq (car field) 'eval)) | 553 (if (and (consp field) (eq (car field) 'eval)) |
534 (setq field (eval (car (cdr field))))) | 554 (setq field (eval (car (cdr field))))) |
535 (if (and type (consp type) (eq (car type) 'eval)) | 555 (if (and type (consp type) (eq (car type) 'eval)) |
576 (progn | 596 (progn |
577 (bindat--pack-group struct (cdr case)) | 597 (bindat--pack-group struct (cdr case)) |
578 (setq cases nil)))))) | 598 (setq cases nil)))))) |
579 (t | 599 (t |
580 (setq last (bindat-get-field struct field)) | 600 (setq last (bindat-get-field struct field)) |
581 (bindat--pack-item last type len) | 601 (bindat--pack-item last type len vectype) |
582 )))))) | 602 )))))) |
583 | 603 |
584 (defun bindat-pack (spec struct &optional bindat-raw bindat-idx) | 604 (defun bindat-pack (spec struct &optional bindat-raw bindat-idx) |
585 "Return binary data packed according to SPEC for structured data STRUCT. | 605 "Return binary data packed according to SPEC for structured data STRUCT. |
586 Optional third arg BINDAT-RAW is a pre-allocated unibyte string or vector to | 606 Optional third arg BINDAT-RAW is a pre-allocated unibyte string or vector to |