123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- ; Octet-addressed binary objects
- ; Copyright (C) Michael Sperber (2005). All Rights Reserved.
- ;
- ; Permission is hereby granted, free of charge, to any person
- ; obtaining a copy of this software and associated documentation files
- ; (the "Software"), to deal in the Software without restriction,
- ; including without limitation the rights to use, copy, modify, merge,
- ; publish, distribute, sublicense, and/or sell copies of the Software,
- ; and to permit persons to whom the Software is furnished to do so,
- ; subject to the following conditions:
- ;
- ; The above copyright notice and this permission notice shall be
- ; included in all copies or substantial portions of the Software.
- ;
- ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- ; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- ; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- ; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- ; SOFTWARE.
- ; This uses SRFIs 23, 26, 60, and 66
- (define *endianness/little* (list 'little))
- (define *endianness/big* (list 'big))
- (define-syntax endianness
- (syntax-rules (little big native)
- ((endianness little) *endianness/little*)
- ((endianness big) *endianness/big*)
- ;; change this to the endianness of your architecture
- ((endianness native) *endianness/big*)))
- (define blob? u8vector?)
- (define (make-blob k)
- (make-u8vector k 0))
- (define (blob-length b)
- (u8vector-length b))
- (define (blob-u8-ref b k)
- (u8vector-ref b k))
- (define (blob-u8-set! b k octet)
- (u8vector-set! b k octet))
- (define (blob-s8-ref b k)
- (u8->s8 (u8vector-ref b k)))
- (define (u8->s8 octet)
- (if (> octet 127)
- (- octet 256)
- octet))
- (define (blob-s8-set! b k val)
- (u8vector-set! b k (s8->u8 val)))
- (define (s8->u8 val)
- (if (negative? val)
- (+ val 256)
- val))
- (define (index-iterate start count low-first?
- unit proc)
- (if low-first?
- (let loop ((index 0)
- (acc unit))
- (if (>= index count)
- acc
- (loop (+ index 1)
- (proc (+ start index) acc))))
- (let loop ((index (- (+ start count) 1))
- (acc unit))
- (if (< index start)
- acc
- (loop (- index 1)
- (proc index acc))))))
- (define (blob-uint-ref size endness blob index)
- (index-iterate index size
- (eq? (endianness big) endness)
- 0
- (lambda (index acc)
- (+ (u8vector-ref blob index) (arithmetic-shift acc 8)))))
- (define (blob-sint-ref size endness blob index)
- (let ((high-byte (u8vector-ref blob
- (if (eq? endness (endianness big))
- index
- (- (+ index size) 1)))))
- (if (> high-byte 127)
- (- (+ 1
- (index-iterate index size
- (eq? (endianness big) endness)
- 0
- (lambda (index acc)
- (+ (- 255 (u8vector-ref blob index))
- (arithmetic-shift acc 8))))))
- (index-iterate index size
- (eq? (endianness big) endness)
- 0
- (lambda (index acc)
- (+ (u8vector-ref blob index) (arithmetic-shift acc 8)))))))
- (define (make-uint-ref size)
- (cut blob-uint-ref size <> <> <>))
- (define (make-sint-ref size)
- (cut blob-sint-ref size <> <> <>))
- (define (blob-uint-set! size endness blob index val)
- (index-iterate index size (eq? (endianness little) endness)
- val
- (lambda (index acc)
- (u8vector-set! blob index (remainder acc 256))
- (quotient acc 256)))
- (values))
- (define (blob-sint-set! size endness blob index val)
- (if (negative? val)
- (index-iterate index size (eq? (endianness little) endness)
- (- -1 val)
- (lambda (index acc)
- (u8vector-set! blob index (- 255 (remainder acc 256)))
- (quotient acc 256)))
-
- (index-iterate index size (eq? (endianness little) endness)
- val
- (lambda (index acc)
- (u8vector-set! blob index (remainder acc 256))
- (quotient acc 256))))
-
- (values))
-
- (define (make-uint-set! size)
- (cut blob-uint-set! size <> <> <> <>))
- (define (make-sint-set! size)
- (cut blob-sint-set! size <> <> <> <>))
- (define (make-ref/native base base-ref)
- (lambda (blob index)
- (ensure-aligned index base)
- (base-ref (endianness native) blob index)))
- (define (make-set!/native base base-set!)
- (lambda (blob index val)
- (ensure-aligned index base)
- (base-set! (endianness native) blob index val)))
- (define (ensure-aligned index base)
- (if (not (zero? (remainder index base)))
- (error "non-aligned blob access" index base)))
- (define blob-u16-ref (make-uint-ref 2))
- (define blob-u16-set! (make-uint-set! 2))
- (define blob-s16-ref (make-sint-ref 2))
- (define blob-s16-set! (make-sint-set! 2))
- (define blob-u16-native-ref (make-ref/native 2 blob-u16-ref))
- (define blob-u16-native-set! (make-set!/native 2 blob-u16-set!))
- (define blob-s16-native-ref (make-ref/native 2 blob-s16-ref))
- (define blob-s16-native-set! (make-set!/native 2 blob-s16-set!))
- (define blob-u32-ref (make-uint-ref 4))
- (define blob-u32-set! (make-uint-set! 4))
- (define blob-s32-ref (make-sint-ref 4))
- (define blob-s32-set! (make-sint-set! 4))
- (define blob-u32-native-ref (make-ref/native 4 blob-u32-ref))
- (define blob-u32-native-set! (make-set!/native 4 blob-u32-set!))
- (define blob-s32-native-ref (make-ref/native 4 blob-s32-ref))
- (define blob-s32-native-set! (make-set!/native 4 blob-s32-set!))
- (define blob-u64-ref (make-uint-ref 8))
- (define blob-u64-set! (make-uint-set! 8))
- (define blob-s64-ref (make-sint-ref 8))
- (define blob-s64-set! (make-sint-set! 8))
- (define blob-u64-native-ref (make-ref/native 8 blob-u64-ref))
- (define blob-u64-native-set! (make-set!/native 8 blob-u64-set!))
- (define blob-s64-native-ref (make-ref/native 8 blob-s64-ref))
- (define blob-s64-native-set! (make-set!/native 8 blob-s64-set!))
- ; Auxiliary stuff
- (define (blob-copy! source source-start target target-start count)
- (u8vector-copy! source source-start target target-start count))
- (define (blob-copy b)
- (u8vector-copy b))
- (define (blob=? b1 b2)
- (u8vector=? b1 b2))
- (define (blob->u8-list b)
- (u8vector->list b))
- (define (blob->s8-list b)
- (map u8->s8 (u8vector->list b)))
- (define (u8-list->blob l)
- (list->u8vector l))
- (define (s8-list->blob l)
- (list->u8vector (map s8->u8 l)))
- (define (make-blob->int-list blob-ref)
- (lambda (size endness b)
- (let ((ref (cut blob-ref size endness b <>))
- (length (blob-length b)))
- (let loop ((i 0) (r '()))
- (if (>= i length)
- (reverse r)
- (loop (+ i size)
- (cons (ref i) r)))))))
- (define blob->uint-list (make-blob->int-list blob-uint-ref))
- (define blob->sint-list (make-blob->int-list blob-sint-ref))
- (define (make-int-list->blob blob-set!)
- (lambda (size endness l)
- (let* ((blob (make-blob (* size (length l))))
- (set! (cut blob-set! size endness blob <> <>)))
- (let loop ((i 0) (l l))
- (if (null? l)
- blob
- (begin
- (set! i (car l))
- (loop (+ i size) (cdr l))))))))
- (define uint-list->blob (make-int-list->blob blob-uint-set!))
- (define sint-list->blob (make-int-list->blob blob-sint-set!))
|