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



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




No requiremtents.


Basic syntax description

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

 (pattern ...)
 (else expression))

Patterns description

Read byte from stream and bind to varaible NAME or compare with immediate value if name not a symbol name. Supported immediate values types: integer char string
Read n-BITS big endian integer, bind-or-compare to NAME.
(NAME BITS little)
Read n-BITS little endian integer, bind-or-compare to NAME.
(NAME 16 float)
Read ieee-754 floating point half-precision, bind-or-compare to NAME.
(NAME 32 float)
Read ieee-754 floating point single precision, bind-or-compare to NAME.
(NAME BITS bitstring)
Read raw BITS from stream, bind-or-compare to NAME.
(NAME bitstring)
Greedy read, consume all available bits.
Empty bitstring
(PACKET-NAME bitpacket)
Read a packet defined by the (bitpacket PACKET-NAME ...) declaration. Bind each packet field to current lexical scope. !!! bitpacket is an experimental feature !!!
user guard EXPRESSION. Matching will continue only when this evaluates to a true value.
[syntax] (bitmatch binary-data patterns-list else-guard)
[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.


; 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)

; The following will print "integer:3721182122",
; which is the decimal value of #xDDCCBBAA
(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)

; This will print "StringData:(65 66 67 68 69)"
; First it reads the length byte of 5, bind it to Length and
; then it will read a bit string with a length of that many octets.
(bitmatch "\x05\x00ABCDE"
  (((Length 16 little)
    (StringData (* 8 Length) bitstring))
      (print "StringData:" (bitstring->list StringData)))
      (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)))))
    (print "bad datagram")))

; Example 3.1 Using bitconstruct.

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

; The following will print "#t".  First, it reads a 16-bit number length
; and compares it to the immediate value of 7.  Then it will read a
; string and compare it to the immediate value of "qwerty.".  If there
; was any remaining data in the string, it would fail.
(bitmatch (construct-fixed-string "qwerty.")
  (((7 16) ("qwerty."))
    (print #t))
    (print #f)))

; Example 3.2 Concatenating bitstrings.

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

(print (construct-complex-object))

; Basic TGA image parser.
; Support True-Image type format and Run-Length-Encoding compression.
; Full Source:
; 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))
        	  (print "True-Color uncompressed")
        	  (print ImageWidth "x" ImageHeight "x" PixelDepth)
        	    (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))
      		  (print "True-Color compressed")
      		  (print ImageWidth "x" ImageHeight "x" PixelDepth)
        	      (lambda (color)
        	      	(file-write fo (bitstring->blob color)))
        	      PixelDepth Image-data))))))

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

(define (parse-image-compressed func depth image)
  (bitmatch image
    (((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))
      	  (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")




Bitstring is maintained in a hg bitbucket repository.

Version History

0.2 introduce bitconstruct

0.1 first public release