srfi-74.scm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber, David van Horn
  3. ; Octet-addressed binary objects
  4. ; The efficiency of this is probably less than optimal.
  5. ; This uses SRFIs 23, 26, 60, and 66
  6. (define *endianness/little* (list 'little))
  7. (define *endianness/big* (list 'big))
  8. (define-syntax endianness
  9. (syntax-rules (little big native)
  10. ((endianness little) *endianness/little*)
  11. ((endianness big) *endianness/big*)
  12. ;; change this to the endianness of your architecture
  13. ((endianness native) *endianness/big*)))
  14. (define blob? u8vector?)
  15. (define (make-blob k)
  16. (make-u8vector k 0))
  17. (define (blob-length b)
  18. (u8vector-length b))
  19. (define (blob-u8-ref b k)
  20. (u8vector-ref b k))
  21. (define (blob-u8-set! b k octet)
  22. (u8vector-set! b k octet))
  23. (define (blob-s8-ref b k)
  24. (u8->s8 (u8vector-ref b k)))
  25. (define (u8->s8 octet)
  26. (if (> octet 127)
  27. (- octet 256)
  28. octet))
  29. (define (blob-s8-set! b k val)
  30. (u8vector-set! b k (s8->u8 val)))
  31. (define (s8->u8 val)
  32. (if (negative? val)
  33. (+ val 256)
  34. val))
  35. (define (index-iterate start count low-first?
  36. unit proc)
  37. (if low-first?
  38. (let loop ((index 0)
  39. (acc unit))
  40. (if (>= index count)
  41. acc
  42. (loop (+ index 1)
  43. (proc (+ start index) acc))))
  44. (let loop ((index (- (+ start count) 1))
  45. (acc unit))
  46. (if (< index start)
  47. acc
  48. (loop (- index 1)
  49. (proc index acc))))))
  50. (define (blob-uint-ref size endness blob index)
  51. (index-iterate index size
  52. (eq? (endianness big) endness)
  53. 0
  54. (lambda (index acc)
  55. (+ (u8vector-ref blob index) (arithmetic-shift acc 8)))))
  56. (define (blob-sint-ref size endness blob index)
  57. (let ((high-byte (u8vector-ref blob
  58. (if (eq? endness (endianness big))
  59. index
  60. (- (+ index size) 1)))))
  61. (if (> high-byte 127)
  62. (- (+ 1
  63. (index-iterate index size
  64. (eq? (endianness big) endness)
  65. 0
  66. (lambda (index acc)
  67. (+ (- 255 (u8vector-ref blob index))
  68. (arithmetic-shift acc 8))))))
  69. (index-iterate index size
  70. (eq? (endianness big) endness)
  71. 0
  72. (lambda (index acc)
  73. (+ (u8vector-ref blob index) (arithmetic-shift acc 8)))))))
  74. (define (make-uint-ref size)
  75. (cut blob-uint-ref size <> <> <>))
  76. (define (make-sint-ref size)
  77. (cut blob-sint-ref size <> <> <>))
  78. (define (blob-uint-set! size endness blob index val)
  79. (index-iterate index size (eq? (endianness little) endness)
  80. val
  81. (lambda (index acc)
  82. (u8vector-set! blob index (remainder acc 256))
  83. (quotient acc 256)))
  84. (values))
  85. (define (blob-sint-set! size endness blob index val)
  86. (if (negative? val)
  87. (index-iterate index size (eq? (endianness little) endness)
  88. (- -1 val)
  89. (lambda (index acc)
  90. (u8vector-set! blob index (- 255 (remainder acc 256)))
  91. (quotient acc 256)))
  92. (index-iterate index size (eq? (endianness little) endness)
  93. val
  94. (lambda (index acc)
  95. (u8vector-set! blob index (remainder acc 256))
  96. (quotient acc 256))))
  97. (values))
  98. (define (make-uint-set! size)
  99. (cut blob-uint-set! size <> <> <> <>))
  100. (define (make-sint-set! size)
  101. (cut blob-sint-set! size <> <> <> <>))
  102. (define (make-ref/native base base-ref)
  103. (lambda (blob index)
  104. (ensure-aligned index base)
  105. (base-ref (endianness native) blob index)))
  106. (define (make-set!/native base base-set!)
  107. (lambda (blob index val)
  108. (ensure-aligned index base)
  109. (base-set! (endianness native) blob index val)))
  110. (define (ensure-aligned index base)
  111. (if (not (zero? (remainder index base)))
  112. (error "non-aligned blob access" index base)))
  113. (define blob-u16-ref (make-uint-ref 2))
  114. (define blob-u16-set! (make-uint-set! 2))
  115. (define blob-s16-ref (make-sint-ref 2))
  116. (define blob-s16-set! (make-sint-set! 2))
  117. (define blob-u16-native-ref (make-ref/native 2 blob-u16-ref))
  118. (define blob-u16-native-set! (make-set!/native 2 blob-u16-set!))
  119. (define blob-s16-native-ref (make-ref/native 2 blob-s16-ref))
  120. (define blob-s16-native-set! (make-set!/native 2 blob-s16-set!))
  121. (define blob-u32-ref (make-uint-ref 4))
  122. (define blob-u32-set! (make-uint-set! 4))
  123. (define blob-s32-ref (make-sint-ref 4))
  124. (define blob-s32-set! (make-sint-set! 4))
  125. (define blob-u32-native-ref (make-ref/native 4 blob-u32-ref))
  126. (define blob-u32-native-set! (make-set!/native 4 blob-u32-set!))
  127. (define blob-s32-native-ref (make-ref/native 4 blob-s32-ref))
  128. (define blob-s32-native-set! (make-set!/native 4 blob-s32-set!))
  129. (define blob-u64-ref (make-uint-ref 8))
  130. (define blob-u64-set! (make-uint-set! 8))
  131. (define blob-s64-ref (make-sint-ref 8))
  132. (define blob-s64-set! (make-sint-set! 8))
  133. (define blob-u64-native-ref (make-ref/native 8 blob-u64-ref))
  134. (define blob-u64-native-set! (make-set!/native 8 blob-u64-set!))
  135. (define blob-s64-native-ref (make-ref/native 8 blob-s64-ref))
  136. (define blob-s64-native-set! (make-set!/native 8 blob-s64-set!))
  137. ; Auxiliary stuff
  138. (define (blob-copy! source source-start target target-start count)
  139. (u8vector-copy! source source-start target target-start count))
  140. (define (blob-copy b)
  141. (u8vector-copy b))
  142. (define (blob=? b1 b2)
  143. (u8vector=? b1 b2))
  144. (define (blob->u8-list b)
  145. (u8vector->list b))
  146. (define (blob->s8-list b)
  147. (map u8->s8 (u8vector->list b)))
  148. (define (u8-list->blob l)
  149. (list->u8vector l))
  150. (define (s8-list->blob l)
  151. (list->u8vector (map s8->u8 l)))
  152. (define (make-blob->int-list blob-ref)
  153. (lambda (size endness b)
  154. (let ((ref (cut blob-ref size endness b <>))
  155. (length (blob-length b)))
  156. (let loop ((i 0) (r '()))
  157. (if (>= i length)
  158. (reverse r)
  159. (loop (+ i size)
  160. (cons (ref i) r)))))))
  161. (define blob->uint-list (make-blob->int-list blob-uint-ref))
  162. (define blob->sint-list (make-blob->int-list blob-sint-ref))
  163. (define (make-int-list->blob blob-set!)
  164. (lambda (size endness l)
  165. (let* ((blob (make-blob (* size (length l))))
  166. (set! (cut blob-set! size endness blob <> <>)))
  167. (let loop ((i 0) (l l))
  168. (if (null? l)
  169. blob
  170. (begin
  171. (set! i (car l))
  172. (loop (+ i size) (cdr l))))))))
  173. (define uint-list->blob (make-int-list->blob blob-uint-set!))
  174. (define sint-list->blob (make-int-list->blob blob-sint-set!))