bindat

Homepage: https://www.gnu.org/software/emacs

Author: Kim F. Storm

Summary

Binary data structure packing and unpacking

Commentary

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".

Dependencies

Reverse dependencies