You are looking at historical revision 27698 of this page. It may differ significantly from its current revision.

bitstring

Description

Easy binary data manipulation. Support binary encoding-decoding with matching and condition guards. Implements the subset of Erlang bit syntax.

Authors

rivo

Requirements

No requiremtents.

API

Basic syntax description

(bitmatch binary-data
 ((pattern ...) expression)
 ...
 (else expression))

(bitconstruct
 (pattern ...)
 ...
 (else expression))

Patterns description

(NAME)
Read byte from stream and bind to varaible NAME or compare with immidiate value if name not a symbol name. Supported immidiate values types: integer char string
(NAME BITS)
(NAME BITS big)
Read n-BITS big endian integer, bind-or-compare with NAME.
(NAME BITS little)
Read n-BITS little endian integer, bind-or-compare with NAME.
(NAME 16 float)
Read ieee-754 floating point half-precision, bind-or-compare with NAME.
(NAME 32 float)
Read ieee-754 floating point single precision, bind-or-compare with NAME.
(NAME BITS bitstring)
Read raw BITS from stream, bind-or-compare with NAME.
(NAME bitstring)
Greedy read, consume all available bits.
()
Empty bitstring
(PACKET-NAME bitpacket)
Read packet defined with (bitpacket PACKET-NAME ...) declaration. Bind each packet field to current lexical scope. !!! bitpacket is experimental feature !!!
(check EXPRESSION)
user guard EXPRESSION continue matching only when evaluate to #t

<macro>(bitmatch binary-data patterns-list else-guard)<¯o>

[syntax] (bitconstruct pattern-list else-guard)
((EXPRESSION ...) bitstring)
EXPRESSION should evaluate to bitstring during constructing.
[syntax] (bitpacket PACKET-NAME fields ...)

Define well-known set of fields. Fields syntax the same as bitmatch pattern syntax.

[procedure] (bitstring-compare bitstring1 bitstring2)

Compare bitstrings.

[procedure] (bitstring->list bitstring)

Convert bitstring to list.

[procedure] (bitstring? bitstring)

Test variable type.

[procedure] (bitstring-length bitstring)

Return length in bits.

Examples

; Example 1. Tagged data structure.
;
; struct Tagged {
;  enum { IntegerType = 1, FloatType = 2 };
;  unsigned char Tag; // integer type = 1, float type = 2
;  union {
;   unsigned int IValue;
;   float FValue;
;  };
; };
;

(use bitstring)

(bitmatch "\x01\xAA\xBB\xCC\xDD"
  (((#x01) (IValue 32 little))
      (print "integer:" IValue))
  (((#x02) (FValue 32 float))
      (print "float:" FValue)))

; Example 2. Fixed length string. 
;
; struct FixedString {
;  short Length; // length of StringData array
;  char StringData[0];
; };
;

(use bitstring)

(bitmatch "\x05\x00ABCDE"
  (((Length 16 little)
    (StringData (* 8 Length) bitstring))
      (print "StringData:" (bitstring->list StringData)))
  (else
      (print "invalid string")))

; Example 3. IP packet parsing. 
;

(use bitstring srfi-4)

(define IPRaw `#u8( #x45 #x00 #x00 #x6c
		    #x92 #xcc #x00 #x00
		    #x38 #x06 #x00 #x00
		    #x92 #x95 #xba #x14
		    #xa9 #x7c #x15 #x95 ))

(bitmatch IPRaw
  (((Version 4)
    (IHL 4)
    (TOS 8)
    (TL 16)
    (Identification 16)
    (Reserved 1) (DF 1) (MF 1)
    (FramgentOffset 13)
    (TTL 8)
    (Protocol 8) (check (or (= Protocol 1)
    	                    (= Protocol 2)
    	                    (= Protocol 6)
    	                    (= Protocol 17))) 
    (CheckSum 16)
    (SourceAddr 32 bitstring)
    (DestinationAddr 32 bitstring)
    (Optional bitstring))
    	; print packet filds
    	(print "\n Version: " Version
    	       "\n IHL: " IHL
    	       "\n TOS: " TOS
    	       "\n TL:  " TL
    	       "\n Identification: " Identification
    	       "\n DF: " DF
    	       "\n MF: " MF
    	       "\n FramgentOffset: " FramgentOffset
    	       "\n Protocol: " Protocol
    	       "\n CheckSum: " CheckSum
    	       "\n SourceAddr: " 
    	           (bitmatch SourceAddr (((A)(B)(C)(D)) (list A B C D)))
               "\n DestinationAddr: " 
                   (bitmatch DestinationAddr (((A)(B)(C)(D)) (list A B C D)))))
  (else
    (print "bad datagram")))

; Example 3.1 Using bitconstruct.

(define (construct-fixed-string str)
  (bitconstruct
    (( (string-length str) 16) (str bitstring) )))

(bitmatch (construct-fixed-string "qwerty.")
  (((7 16) ("qwerty."))
    (print #t))
  (else 
    (print #f)))

; Example 3.2 Concatenating bitstrings.

(define (construct-complex-object)
  (bitconstruct
    ( ((construct-fixed-string "A") bitstring)
      (#xAABB 16)
      ((construct-fixed-string "RRR") bitstring))
      (#\X)))

(print (construct-complex-object))

; Basic TGA image parser.
; Support True-Image type format and Run-Length-Encoding compression.
; SPEC: http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf
; Full Source: https://bitbucket.org/rivo/bitstring/src/tip/tests?at=default
;
; WARNING!!! bitpacket feature is experimental !!!

(use bitstring posix srfi-4)

(bitpacket TGA-Header
  (ID-length 8)
  (ColorMapType 8)
  (ImageType 8)
  (TGA-ColorMapSpec bitpacket)
  (TGA-ImageSpec bitpacket))

(bitpacket TGA-ColorMapSpec
  (FirstEntryIndex 16 little)
  (ColorMapLength 16 little)
  (ColorMapEntrySize 8))

(bitpacket TGA-ImageSpec
  (X-Origin 16 little)
  (Y-Origin 16 little)
  (ImageWidth 16 little)
  (ImageHeight 16 little)
  (PixelDepth 8)
  (ImageTransferOrder 2)
  (#x00 2) ; reserved
  (AttributesBitsPerPixel 4))

(define (bitstring->blob bs)
  (u8vector->blob (list->u8vector (bitstring->list bs))))

(define (parse-tga file file-out)
  (let* ((fi (file-open file (+ open/rdonly open/binary)))
         (fo (file-open file-out (+ open/write open/creat open/trunc open/binary)))
         (size (file-size fi))
         (res (file-read fi size))
         (data (car res)))
    (bitmatch data
      ; True-Color uncompressed
      (((TGA-Header bitpacket)
      	(check (and (= 0 ColorMapType) (= 2 ImageType)))
      	(ID-data ID-length bitstring)
        (Image-data (* ImageWidth ImageHeight PixelDepth) bitstring)
        (Rest-data bitstring))
        	(begin
        	  (print "True-Color uncompressed")
        	  (print ImageWidth "x" ImageHeight "x" PixelDepth)
        	  (parse-image-uncompressed
        	    (lambda (color)
        	      (file-write fo (bitstring->blob color)))
        	    PixelDepth Image-data)))
      ; True-Color compressed
      (((TGA-Header bitpacket)
      	(check (and (= 0 ColorMapType) (= 10 ImageType)))
      	(ID-data ID-length bitstring)
      	(Image-data bitstring))
      		(begin
      		  (print "True-Color compressed")
      		  (print ImageWidth "x" ImageHeight "x" PixelDepth)
      		  (parse-image-compressed
        	      (lambda (color)
        	      	(file-write fo (bitstring->blob color)))
        	      PixelDepth Image-data))))))

(define (parse-image-uncompressed func depth image)
  (bitmatch image
    ((())
      	'ok)
    (((Color depth bitstring) (Rest bitstring))
      (begin
      	(func Color)
      	(parse-image-uncompressed func depth Rest)))))

(define (parse-image-compressed func depth image)
  (bitmatch image
    ((())
      	'ok)
    (((1 1) (Count 7) (Color depth bitstring) (Rest bitstring))
      	(let loop ((i 0))
	  (func Color)
	  (if (< i Count)
	    (loop (+ i 1))
	    (parse-image-compressed func depth Rest))))
    (((0 1) (Count 7) (RAW-data (* depth (+ Count 1)) bitstring) (Rest bitstring))
      	(begin
      	  (parse-image-uncompressed func depth RAW-data)
      	  (parse-image-compressed func depth Rest)))))

; Convert images to raw pixels 
;(parse-tga "tests/24compressed.tga" "tests/24c.raw")
;(parse-tga "tests/24uncompressed.tga" "tests/24u.raw")

License

BSD

Version History

0.2 introduce bitconstruct

0.1 first public release