Previous: Bindat Functions, Up: Byte Packing
Here are two complete examples that use bindat.el. The first shows simple byte packing:
(require 'bindat) (defun rfc868-payload () (bindat-pack '((now-hi u16) (now-lo u16)) ;; Emacs uses Unix epoch, while RFC868 epoch ;; is 1900-01-01 00:00:00, which is 2208988800 ;; (or #x83aa7e80) seconds more. (let ((now (time-add nil '(#x83aa #x7e80)))) `((now-hi . ,(car now)) (now-lo . ,(cadr now)))))) (let ((s (rfc868-payload))) (list (multibyte-string-p s) (mapconcat (lambda (byte) (format "%02x" byte)) s " ") (current-time-string))) ⇒ (nil "dc 6d 17 01" "Fri Mar 10 13:13:53 2017")
The following is an example of defining and unpacking a complex structure. Consider the following C structures:
struct header { unsigned long dest_ip; unsigned long src_ip; unsigned short dest_port; unsigned short src_port; }; struct data { unsigned char type; unsigned char opcode; unsigned short length; /* in network byte order */ unsigned char id[8]; /* null-terminated string */ unsigned char data[/* (length + 3) & ~3 */]; }; struct packet { struct header header; unsigned long counters[2]; /* in little endian order */ unsigned char items; unsigned char filler[3]; struct data item[/* items */]; };
The corresponding data layout specification is:
(setq header-spec '((dest-ip ip) (src-ip ip) (dest-port u16) (src-port u16))) (setq data-spec '((type u8) (opcode u8) (length u16) ; network byte order (id strz 8) (data vec (length)) (align 4))) (setq packet-spec '((header struct header-spec) (counters vec 2 u32r) ; little endian order (items u8) (fill 3) (item repeat (items) (struct data-spec))))
A binary data representation is:
(setq binary-data [ 192 168 1 100 192 168 1 101 01 28 21 32 160 134 1 0 5 1 0 0 2 0 0 0 2 3 0 5 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0 1 4 0 7 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ])
The corresponding decoded structure is:
(setq decoded (bindat-unpack packet-spec binary-data)) ⇒ ((header (dest-ip . [192 168 1 100]) (src-ip . [192 168 1 101]) (dest-port . 284) (src-port . 5408)) (counters . [100000 261]) (items . 2) (item ((data . [1 2 3 4 5]) (id . "ABCDEF") (length . 5) (opcode . 3) (type . 2)) ((data . [6 7 8 9 10 11 12]) (id . "BCDEFG") (length . 7) (opcode . 4) (type . 1))))
An example of fetching data from this structure:
(bindat-get-field decoded 'item 1 'id) ⇒ "BCDEFG"