Homepage: https://www.gnu.org/software/emacs
Author: Kim F. Storm
Binary data structure packing and unpacking
Packing and unpacking of (binary) data structures. The data formats used in binary files and network protocols are often structured data which can be described by a C-style structure such as the one shown below. Using the bindat package, decoding and encoding binary data formats like these is made simple using a structure specification which closely resembles the C style structure declarations. Encoded (binary) data is stored in a unibyte string or vector, while the decoded data is stored in an alist with (FIELD . VALUE) pairs. Example: Consider the following C structures: struct header { uint32_t dest_ip; uint32_t src_ip; uint16_t dest_port; uint16_t src_port; }; struct data { uint8_t type; uint8_t opcode; uint32_t length; /* In little endian order */ unsigned char id[8]; /* nul-terminated string */ unsigned char data[/* (length + 3) & ~3 */]; }; struct packet { struct header header; uint8_t items; unsigned char filler[3]; struct data item[/* items */]; }; The corresponding Lisp bindat specification could look like this: (bindat-defmacro ip () '(vec 4 byte)) (setq header-bindat-spec (bindat-type (dest-ip ip) (src-ip ip) (dest-port uint 16) (src-port uint 16))) (setq data-bindat-spec (bindat-type (type u8) (opcode u8) (length uintr 32) ;; little endian order (id strz 8) (data vec length) (_ align 4))) (setq packet-bindat-spec (bindat-type (header type header-bindat-spec) (nitems u8) (_ fill 3) (items repeat nitems type data-bindat-spec))) A binary data representation may look like [ 192 168 1 100 192 168 1 101 01 28 21 32 2 0 0 0 2 3 5 0 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0 1 4 7 0 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ] The corresponding decoded structure returned by `bindat-unpack' (or taken by `bindat-pack') looks like: ((header (dest-ip . [192 168 1 100]) (src-ip . [192 168 1 101]) (dest-port . 284) (src-port . 5408)) (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)))) To access a specific value in this structure, use the function `bindat-get-field' with the structure as first arg followed by a list of field names and array indexes, e.g. using the data above, (bindat-get-field decoded-structure 'item 1 'id) returns "BCDEFG".