bytevector.scm 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; This is taken from the R6RS reference implementation by Mike
  3. ; Sperber, modified by Will Clinger.
  4. (import-dynamic-externals "=scheme48external/r6rs")
  5. (define-enumeration endianness
  6. (little big)
  7. endianness*)
  8. (define bytevector? byte-vector?)
  9. (define make-bytevector
  10. (opt-lambda (size (fill 0))
  11. (if (and (>= fill -128)
  12. (<= fill 255))
  13. (make-byte-vector size fill)
  14. (error #f "wrong value to fill a byte vector must be octet" fill))))
  15. (define bytevector-length byte-vector-length)
  16. (define bytevector=? byte-vector=?)
  17. (define (bytevector-fill! vector fill)
  18. (let loop ((index 0))
  19. (if (< index (bytevector-length vector))
  20. (begin (bytevector-u8-set! vector index fill)
  21. (loop (+ index 1))))))
  22. ;; may be we need a few checks to fit the need -- look carefully
  23. (define (bytevector-copy! source source-start target target-start count)
  24. (copy-bytes! source source-start target target-start count))
  25. (define (bytevector-copy vector)
  26. (let* ((size (byte-vector-length vector))
  27. (copy (make-byte-vector size 0)))
  28. (bytevector-copy! vector 0 copy 0 size)
  29. copy))
  30. ;; now the stuff with the typed bytevectors begins
  31. (define (u8->s8 val)
  32. (if (> val 127)
  33. (- val 256)
  34. val))
  35. (define (s8->u8 val)
  36. (if (negative? val)
  37. (+ val 256)
  38. val))
  39. (define (bytevector-u8-ref vector k)
  40. (check-index vector k)
  41. (byte-vector-ref vector k))
  42. (define (bytevector-u8-set! vector k val)
  43. (check-index vector k)
  44. (check-range val 1 #f)
  45. (byte-vector-set! vector k val))
  46. (define (bytevector-s8-ref vector k)
  47. (check-index vector k)
  48. (u8->s8 (bytevector-u8-ref vector k)))
  49. (define (bytevector-s8-set! vector k val)
  50. (check-index vector k)
  51. (check-range val 1 #t)
  52. ( bytevector-u8-set! vector k (s8->u8 val)))
  53. (define (bytevector->u8-list octets)
  54. (let loop ((n (bytevector-length octets)) (r '()))
  55. (if (zero? n)
  56. r
  57. (loop (- n 1)
  58. (cons (bytevector-u8-ref octets (- n 1)) r)))))
  59. (define (u8-list->bytevector list)
  60. (let ((vect (make-bytevector (length list))))
  61. (let loop ((l list)
  62. (index 0))
  63. (if (not (eq? l '()))
  64. (begin (bytevector-u8-set! vect index (car l))
  65. (loop (cdr l)
  66. (+ index 1)))))
  67. vect))
  68. ;; the integer view (native integers) to a bytevector
  69. (define (bytevector-uint-ref bytevector index endness size)
  70. (case endness
  71. ((big)
  72. (do ((i 0 (+ i 1))
  73. (result 0 (+ (arithmetic-shift result 8)
  74. (bytevector-u8-ref bytevector (+ index i)))))
  75. ((>= i size)
  76. result)))
  77. ((little)
  78. (do ((i (- size 1) (- i 1))
  79. (result 0 (+ (arithmetic-shift result 8)
  80. (bytevector-u8-ref bytevector (+ index i)))))
  81. ((< i 0)
  82. result)))
  83. (else
  84. (error 'bytevector-uint-ref "Invalid endianness: " endness))))
  85. (define (bytevector-sint-ref bytevector index endness size)
  86. (let* ((high-byte (bytevector-u8-ref bytevector
  87. (if (eq? endness (endianness big))
  88. index
  89. (+ index size -1))))
  90. (uresult (bytevector-uint-ref bytevector index endness size)))
  91. (if (> high-byte 127)
  92. (- uresult (expt 256 size))
  93. uresult)))
  94. (define (bytevector-uint-set! bytevector index val endness size)
  95. (check-range val size #f)
  96. (case endness
  97. ((little)
  98. (do ((i 0 (+ i 1))
  99. (val val (quotient val 256)))
  100. ((>= i size))
  101. (bytevector-u8-set! bytevector (+ index i) (remainder val 256))))
  102. ((big)
  103. (do ((i (- size 1) (- i 1))
  104. (val val (quotient val 256)))
  105. ((< i 0))
  106. (bytevector-u8-set! bytevector (+ index i) (remainder val 256))))
  107. (else
  108. (error 'bytevector-uint-set! "Invalid endianness: " endness))))
  109. (define (bytevector-sint-set! bytevector index val endness size)
  110. (check-range val size #t)
  111. (let ((uval (if (< val 0)
  112. (+ val (* 128 (expt 256 (- size 1))))
  113. val)))
  114. (bytevector-uint-set! bytevector index uval endness size)))
  115. (define (bytevector->uint-list vector endness size)
  116. ((make-bytevect->int-list bytevector-uint-ref)
  117. vector endness size))
  118. (define (bytevector->sint-list vector endness size)
  119. ((make-bytevect->int-list bytevector-sint-ref)
  120. vector endness size))
  121. (define (uint-list->bytevector list endness size)
  122. ((make-int-list->bytevect bytevector-uint-set!)
  123. list endness size))
  124. (define (sint-list->bytevector list endness size)
  125. ((make-int-list->bytevect bytevector-sint-set!)
  126. list endness size))
  127. (define (make-uint-ref size)
  128. (lambda (bytevector k endianness)
  129. (bytevector-uint-ref bytevector k endianness size)))
  130. (define (make-sint-ref size)
  131. (lambda (bytevector k endianness)
  132. (bytevector-sint-ref bytevector k endianness size)))
  133. (define (make-uint-set! size)
  134. (lambda (bytevector k n endianness)
  135. (bytevector-uint-set! bytevector k n endianness size)))
  136. (define (make-sint-set! size)
  137. (lambda (bytevector k n endianness)
  138. (bytevector-sint-set! bytevector k n endianness size)))
  139. (define (make-ref/native base base-ref)
  140. (lambda (bytevector index)
  141. (ensure-aligned index base)
  142. (base-ref bytevector index (native-endianness))))
  143. (define (make-set!/native base base-set!)
  144. (lambda (bytevector index val)
  145. (ensure-aligned index base)
  146. (base-set! bytevector index val (native-endianness))))
  147. ;; uint16
  148. (define bytevector-u16-ref (make-uint-ref 2))
  149. (define bytevector-s16-ref (make-sint-ref 2))
  150. (define bytevector-u16-native-ref (make-ref/native 2 bytevector-u16-ref))
  151. (define bytevector-s16-native-ref (make-ref/native 2 bytevector-s16-ref))
  152. (define bytevector-u16-set! (make-uint-set! 2))
  153. (define bytevector-s16-set! (make-sint-set! 2))
  154. (define bytevector-u16-native-set! (make-set!/native 2 bytevector-u16-set!))
  155. (define bytevector-s16-native-set! (make-set!/native 2 bytevector-s16-set!))
  156. ;; uint32
  157. (define bytevector-u32-ref (make-uint-ref 4))
  158. (define bytevector-s32-ref (make-sint-ref 4))
  159. (define bytevector-u32-native-ref (make-ref/native 4 bytevector-u32-ref))
  160. (define bytevector-s32-native-ref (make-ref/native 4 bytevector-s32-ref))
  161. (define bytevector-u32-set! (make-uint-set! 4))
  162. (define bytevector-s32-set! (make-sint-set! 4))
  163. (define bytevector-u32-native-set! (make-set!/native 4 bytevector-u32-set!))
  164. (define bytevector-s32-native-set! (make-set!/native 4 bytevector-s32-set!))
  165. ;; uint64
  166. (define bytevector-u64-ref (make-uint-ref 8))
  167. (define bytevector-s64-ref (make-sint-ref 8))
  168. (define bytevector-u64-native-ref (make-ref/native 8 bytevector-u64-ref))
  169. (define bytevector-s64-native-ref (make-ref/native 8 bytevector-s64-ref))
  170. (define bytevector-u64-set! (make-uint-set! 8))
  171. (define bytevector-s64-set! (make-sint-set! 8))
  172. (define bytevector-u64-native-set! (make-set!/native 8 bytevector-u64-set!))
  173. (define bytevector-s64-native-set! (make-set!/native 8 bytevector-s64-set!))
  174. ;; helper procedures
  175. (define (make-bytevect->int-list bytevect-ref)
  176. (lambda (vect endness size)
  177. (let ((length (bytevector-length vect)))
  178. (let loop ((i 0) (r '()))
  179. (if (>= i length)
  180. (reverse r)
  181. (loop (+ i size)
  182. (cons (bytevect-ref vect i endness size) r)))))))
  183. (define (make-int-list->bytevect bytevect-set!)
  184. (lambda (l endness size)
  185. (let ((bytevect (make-bytevector (* size (length l)))))
  186. (let loop ((i 0) (l l))
  187. (if (null? l)
  188. bytevect
  189. (begin
  190. (bytevect-set! bytevect i (car l) endness size)
  191. (loop (+ i size) (cdr l))))))))
  192. ;; general checks
  193. (define (ensure-aligned index base)
  194. (if (not (zero? (remainder index base)))
  195. (assertion-violation 'ensure-aligned "non-aligned bytevector access" index base)))
  196. (define (check-range value byte-count signed-check?)
  197. (let* ((bits (* byte-count 8))
  198. (unsigned-low 0)
  199. (unsigned-high (- (expt 2 bits) 1))
  200. (signed-low (* -1 (expt 2 (- bits 1))))
  201. (signed-high (- (expt 2 (- bits 1)) 1)))
  202. (if signed-check?
  203. (if (not (and (>= value signed-low) (<= value signed-high)))
  204. (assertion-violation 'check-range
  205. "range check for value failed / signed - value does not fit into "
  206. byte-count 'bytes 'checked-value: value))
  207. (if (not (and (>= value unsigned-low) (<= value unsigned-high)))
  208. (assertion-violation 'check-range
  209. "range check for value failed / unsigned - value does not fit into "
  210. byte-count 'bytes 'checked-value: value)))))
  211. (define (check-index b i)
  212. (if (or (> i (- (bytevector-length b) 1)) (< i 0))
  213. (assertion-violation 'check-index
  214. "invalid index forr vector must be in the range of"
  215. 0 'to (- (bytevector-length b) 1))))
  216. (define (native-endianness)
  217. (if (external-r6rs-big-endian?)
  218. (endianness big)
  219. (endianness little)))
  220. ;; external fun definition
  221. (import-lambda-definition-2 external-r6rs-big-endian?
  222. ()
  223. "r6rs_is_big_endian")