Welcome to the CHICKEN Scheme pasting service

bitstring draft added by klgg213498 on Tue Oct 9 17:23:40 2012

(define-record bitstring
  offset  ; offset in bits
  numbits ; length of the bitstring in bits
  buffer) ; vector

(define-record-printer (bitstring x out)
  (fprintf out "bitstring ~A" (bitstring-buffer x)))

(define (bitstring-reserve numbits)
  (let* ((n (quotient numbits 8))
      	 (rem (remainder numbits 8))
    	 (aligned-size (if (zero? rem) n (+ 1 n))))
    (make-bitstring 0 numbits (make-vector aligned-size 0))))

(define (bitstring-of-vector v)
  (let* ((size (vector-length v))
         (numbits (* 8 size)))
    (make-bitstring 0 numbits v)))
    
(define (bitstring-load-byte bs index)
  (vector-ref (bitstring-buffer bs) index))
 
(define (bitstring-store-byte bs index value)
  (vector-set! (bitstring-buffer bs) index (bitwise-and #xFF value)))
  
(define (integer->bitstring endian value count)
  (cond
    ((eq? endian 'big)
      (integer->bitstring-big (bitstring-reserve count) 0 value count))
    ((eq? endian 'little)
      (integer->bitstring-little (bitstring-reserve count) #f value count))))

(define (integer->bitstring-big bs index value count)
  (let ((n (min 8 count)))
    (cond
      ((< n 8)
      	(bitstring-store-byte bs index (arithmetic-shift value (- 8 n)))
      	bs);return bitstring
      (else
      	(bitstring-store-byte bs index (arithmetic-shift value (- n count)))
      	(integer->bitstring-big bs (+ index 1) value (- count n))))))

(define (integer->bitstring-little bs index value count)
  (cond
    ((zero? count)
      bs)
    ((eq? index #f)
      (let* ((r (remainder count 8))
      	     (n (- 8 r))
             (index (quotient count 8)))
      	(bitstring-store-byte bs index (arithmetic-shift value n))
      	;(print " index=" index " count=" count " n=" n " value=" (bitmask8 value 8) " store=" (bitstring-load-byte bs index))
      	(integer->bitstring-little bs (- index 1)
      	  (arithmetic-shift value (- r)) (- count r)))) 
    (else
      (let ((n 8))
      	(bitstring-store-byte bs index value)
      	;(print " index=" index " count=" count " n=" n " store=" (bitstring-load-byte bs index))
      	(integer->bitstring-little bs (- index 1)
      	  (arithmetic-shift value (- n)) (- count n))))))

(define (bitstring->integer bs endian)
  (cond 
    ((eq? endian 'big)
      (bitstring->integer-big bs (bitstring-numbits bs) 0 0))
    ((eq? endian 'little)
      (bitstring->integer-little bs (bitstring-numbits bs) 0 0))))

(define (bitstring->integer-big bs count index acc)
  (print "big count=" count " index=" index)
  (let* ((n (min 8 count))
         (shift (- n 8)))
    (cond
      ((zero? count)
      	acc)
      ((< n 8)
      	(bitwise-ior
      	  (arithmetic-shift (bitstring-load-byte bs index) shift)
      	  (arithmetic-shift acc n)))
      (else
      	(bitstring->integer-big bs (- count n) (+ 1 index)
      	  (bitwise-ior
      	    (arithmetic-shift (bitstring-load-byte bs index) (- n 8))
      	    (arithmetic-shift acc n)))))))
  
(define (bitstring->integer-little bs count index acc)
  (let* ((n (min 8 count)))
    (print "count=" count " n=" n)
    (if (zero? n)
      acc
      (bitstring->integer-little bs (- count n) (+ 1 index)
      	(bitwise-ior
      	  (arithmetic-shift (bitstring-load-byte bs index) (- n))
      	  (arithmetic-shift acc (- n)))))))
      	  
(define (bitstring-append-safe bs value count)
  (if (zero? count)
    bs
    (let* ((offset (bitstring-offset bs))
    	   (index (quotient offset 8))
           (drift (remainder offset 8))
           (space (- 8 drift))
           (nbits (min count space))
           (byte1 (bitstring-load-byte bs index))
           (byte2 (bitmask8 (arithmetic-shift value (- count nbits)) nbits)))
      (bitstring-store-byte bs index ; blend bits
      	(bitwise-ior byte1 (arithmetic-shift byte2 (- space nbits))))
      ;(print "store offset=" offset " value=" (bitstring-load-byte bs index) 
      ;	" space=" space " shift=" (- count nbits) " bits=" nbits)
      (bitstring-offset-set! bs (+ offset nbits))
      (bitstring-append-safe bs value (- count nbits)))))

(define (bitstring-read-bits bs count)
  (assert (>= count 0))
  (let ((offset (bitstring-offset bs))
	(limit (bitstring-numbits bs)))
    (if (<= (+ offset count) limit)
      (let ((acc (bitstring-reserve count)))
      	(bitstring-read-bits-safe bs offset count acc)
      	(bitstring-offset-set! bs (+ offset count))
      	acc)
      #f)))

(define (bitstring-read-bits-safe bs offset count acc)
  (if (= count 0)
    acc
    (let* ((index (quotient offset 8))
    	   (drift (remainder offset 8))
    	   (nbits (min 8 count (- 8 drift)))
    	   (shift (- offset (* 8 index)))
    	   (byte (bitstring-load-byte bs index))
    	   (value (extract-bits byte nbits shift)))
      ;(print "offs=" offset " nbits=" nbits " byte=" byte " value=" value)
      (bitstring-read-bits-safe bs (+ offset nbits) (- count nbits)
      	(bitstring-append-safe acc value nbits)))))

(define (bitmask8 value nbits)
  (case nbits
    ((0) 0)
    ((1) (bitwise-and value #b00000001))
    ((2) (bitwise-and value #b00000011))
    ((3) (bitwise-and value #b00000111))
    ((4) (bitwise-and value #b00001111))
    ((5) (bitwise-and value #b00011111))
    ((6) (bitwise-and value #b00111111))
    ((7) (bitwise-and value #b01111111))
    ((8) (bitwise-and value #b11111111))))

(define (extract-bits byte nbits shift)
  (let* ((n (- (+ nbits shift) 8))
         (value (arithmetic-shift byte n)))
    (bitmask8 value nbits)))


(define (bitmatch-open v)
  (print "bitmatch-open " v)
  (bitstring-of-vector v))

(define (bitmatch-reset stream)
  (print "bitmatch-reset ")
  (bitstring-offset-set! stream 0))

(define (bitmatch-read stream num-bits)
  (let ((bs (bitstring-read-bits stream num-bits)))
    (print " read " num-bits " " bs) 
    (and
      bs
      (bitstring->integer bs 'big))))  

(define (bitmatch-compare a b)
  (print "compare " a " = " b)
  (equal? a b))

(define-syntax bitmatch
  (syntax-rules ()
    ((_ value patterns ...)
      (let ((stream (bitmatch-open value)))
      	(call-with-current-continuation
      	  (lambda (k)
      	    (or (bitmatch2 ('secret-params stream k) patterns ...))))))))

(define-syntax bitmatch2
  (syntax-rules (else)
    ((_ ('secret-params stream k))
      (print "error: nothing match"))
    ((_ ('secret-params stream k) (else expression))
      (print "else condition"))    	
    ((_ ('secret-params stream k) (pattern ...) rest ...)
      (or
      	(begin
      	  (print "group: " `(pattern ...))
      	  (bitmatch-reset stream)
      	  #f)
	(and
	  (bitmatch1 ('secret-params stream k) pattern ...))
	(bitmatch2 ('secret-params stream k) rest ...)))
    ((_ err)
      (print "bad pattern: " `err))))


(define-syntax bitmatch1
  (syntax-rules (let : ->) ; CAUTION: use let* during macro expansion !!!
    ((_ ('secret-params stream k)
    	(let name : num-bits) rest ...)
      (and
      	(let* ((name (bitmatch-read stream num-bits)))
      	  (print "bind variable " name)
      	  (and
      	    (not (eq? #f name))
      	    (bitmatch1 ('secret-params stream k) rest ...)))))

    ((_ ('secret-params stream k)
    	(let name : num-bits : signed) rest ...)
      (and
      	(bitmatch1 ('secret-params stream k) rest ...)))

    ((_ ('secret-params stream k) (var name : num-bits : unsigned) rest ...)
      (and
      	(bitmatch1 ('secret-params stream k) rest ...)))

    ((_ ('secret-params stream k)
    	(value : num-bits) rest ...)
      (and
      	(begin (print "value=?") #t)
      	(bitmatch1 ('secret-params stream k) rest ...)))

    ((_ ('secret-params stream k)
    	(value) rest ...)
      (and
      	(let* ((bits (bitmatch-read stream 8)))
      	  (print "value=" bits)
      	  (and
      	    (bitmatch-compare value bits)
      	    (bitmatch1 ('secret-params stream k) rest ...)))))

    ((_ ('secret-params stream k)
    	-> expression)
      (begin
      	(print "match! " `expression)
      	(k expression)))
     ((_ ('secret-params stream k))
      (print "empty expression"))
    
    ((_ ('secret-params stream k) err1)
      (print "malformed pattern1 " `err1))
    
    ((_ ('secret-params stream k) err2 rest ...)
      (print "malformed pattern2 " `err2))))

(print "-\n")

(bitmatch '#(130 50)
  ((let a : 1) (let b : 7) (50 : 18) ->
    (print " a=" a " b=" b)))

Your annotation:

Enter a new annotation:

Your nick:
The title of your paste:
Your paste (mandatory) :
Which relatively recent Scheme report version does CHICKEN _not_ implement?
Visually impaired? Let me spell it for you (wav file) download WAV