74.body.scm 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. ;; Octet-addressed binary objects
  2. ;; Copyright (C) Michael Sperber (2005). All Rights Reserved.
  3. ;;
  4. ;; Copyright (C) Taylan Ulrich Bayırlı/Kammer (2014).
  5. ;;
  6. ;; Permission is hereby granted, free of charge, to any person
  7. ;; obtaining a copy of this software and associated documentation files
  8. ;; (the "Software"), to deal in the Software without restriction,
  9. ;; including without limitation the rights to use, copy, modify, merge,
  10. ;; publish, distribute, sublicense, and/or sell copies of the Software,
  11. ;; and to permit persons to whom the Software is furnished to do so,
  12. ;; subject to the following conditions:
  13. ;;
  14. ;; The above copyright notice and this permission notice shall be
  15. ;; included in all copies or substantial portions of the Software.
  16. ;;
  17. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  21. ;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  22. ;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23. ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. ;; SOFTWARE.
  25. (define endianness-native (native-endianness))
  26. (define (bytevector-s8-ref b k)
  27. (u8->s8 (bytevector-u8-ref b k)))
  28. (define (u8->s8 octet)
  29. (if (> octet 127)
  30. (- octet 256)
  31. octet))
  32. (define (bytevector-s8-set! b k val)
  33. (bytevector-u8-set! b k (s8->u8 val)))
  34. (define (s8->u8 val)
  35. (if (negative? val)
  36. (+ val 256)
  37. val))
  38. (define (index-iterate start count low-first?
  39. unit proc)
  40. (if low-first?
  41. (let loop ((index 0)
  42. (acc unit))
  43. (if (>= index count)
  44. acc
  45. (loop (+ index 1)
  46. (proc (+ start index) acc))))
  47. (let loop ((index (- (+ start count) 1))
  48. (acc unit))
  49. (if (< index start)
  50. acc
  51. (loop (- index 1)
  52. (proc index acc))))))
  53. (define (bytevector-uint-ref size endness bytevector index)
  54. (index-iterate index size
  55. (eq? endianness-big endness)
  56. 0
  57. (lambda (index acc)
  58. (+ (bytevector-u8-ref bytevector index)
  59. (arithmetic-shift acc 8)))))
  60. (define (bytevector-sint-ref size endness bytevector index)
  61. (let ((high-byte (bytevector-u8-ref bytevector
  62. (if (eq? endness endianness-big)
  63. index
  64. (- (+ index size) 1)))))
  65. (if (> high-byte 127)
  66. (- (+ 1
  67. (index-iterate index size
  68. (eq? endianness-big endness)
  69. 0
  70. (lambda (index acc)
  71. (+ (- 255 (bytevector-u8-ref bytevector index))
  72. (arithmetic-shift acc 8))))))
  73. (index-iterate index size
  74. (eq? endianness-big endness)
  75. 0
  76. (lambda (index acc)
  77. (+ (bytevector-u8-ref bytevector index)
  78. (arithmetic-shift acc 8)))))))
  79. (define (make-uint-ref size)
  80. (cut bytevector-uint-ref size <> <> <>))
  81. (define (make-sint-ref size)
  82. (cut bytevector-sint-ref size <> <> <>))
  83. (define (bytevector-uint-set! size endness bytevector index val)
  84. (index-iterate index size (eq? endianness-little endness)
  85. val
  86. (lambda (index acc)
  87. (bytevector-u8-set! bytevector index (remainder acc 256))
  88. (quotient acc 256)))
  89. (values))
  90. (define (bytevector-sint-set! size endness bytevector index val)
  91. (if (negative? val)
  92. (index-iterate index size (eq? endianness-little endness)
  93. (- -1 val)
  94. (lambda (index acc)
  95. (bytevector-u8-set! bytevector index (- 255 (remainder acc 256)))
  96. (quotient acc 256)))
  97. (index-iterate index size (eq? endianness-little endness)
  98. val
  99. (lambda (index acc)
  100. (bytevector-u8-set! bytevector index (remainder acc 256))
  101. (quotient acc 256))))
  102. (values))
  103. (define (make-uint-set! size)
  104. (cut bytevector-uint-set! size <> <> <> <>))
  105. (define (make-sint-set! size)
  106. (cut bytevector-sint-set! size <> <> <> <>))
  107. (define (make-ref/native base base-ref)
  108. (lambda (bytevector index)
  109. (ensure-aligned index base)
  110. (base-ref endianness-native bytevector index)))
  111. (define (make-set!/native base base-set!)
  112. (lambda (bytevector index val)
  113. (ensure-aligned index base)
  114. (base-set! endianness-native bytevector index val)))
  115. (define (ensure-aligned index base)
  116. (if (not (zero? (remainder index base)))
  117. (error "non-aligned bytevector access" index base)))
  118. (define bytevector-u16-ref (make-uint-ref 2))
  119. (define bytevector-u16-set! (make-uint-set! 2))
  120. (define bytevector-s16-ref (make-sint-ref 2))
  121. (define bytevector-s16-set! (make-sint-set! 2))
  122. (define bytevector-u16-native-ref (make-ref/native 2 bytevector-u16-ref))
  123. (define bytevector-u16-native-set! (make-set!/native 2 bytevector-u16-set!))
  124. (define bytevector-s16-native-ref (make-ref/native 2 bytevector-s16-ref))
  125. (define bytevector-s16-native-set! (make-set!/native 2 bytevector-s16-set!))
  126. (define bytevector-u32-ref (make-uint-ref 4))
  127. (define bytevector-u32-set! (make-uint-set! 4))
  128. (define bytevector-s32-ref (make-sint-ref 4))
  129. (define bytevector-s32-set! (make-sint-set! 4))
  130. (define bytevector-u32-native-ref (make-ref/native 4 bytevector-u32-ref))
  131. (define bytevector-u32-native-set! (make-set!/native 4 bytevector-u32-set!))
  132. (define bytevector-s32-native-ref (make-ref/native 4 bytevector-s32-ref))
  133. (define bytevector-s32-native-set! (make-set!/native 4 bytevector-s32-set!))
  134. (define bytevector-u64-ref (make-uint-ref 8))
  135. (define bytevector-u64-set! (make-uint-set! 8))
  136. (define bytevector-s64-ref (make-sint-ref 8))
  137. (define bytevector-s64-set! (make-sint-set! 8))
  138. (define bytevector-u64-native-ref (make-ref/native 8 bytevector-u64-ref))
  139. (define bytevector-u64-native-set! (make-set!/native 8 bytevector-u64-set!))
  140. (define bytevector-s64-native-ref (make-ref/native 8 bytevector-s64-ref))
  141. (define bytevector-s64-native-set! (make-set!/native 8 bytevector-s64-set!))
  142. ;; Auxiliary stuff
  143. (define (bytevector->u8-list b)
  144. (do ((i 0 (+ 1 i))
  145. (list '() (cons (bytevector-u8-ref b i) list)))
  146. ((= i (bytevector-length b))
  147. (reverse list))))
  148. (define (bytevector->s8-list b)
  149. (map u8->s8 (bytevector->u8-list b)))
  150. (define (u8-list->bytevector l)
  151. (apply bytevector l))
  152. (define (s8-list->bytevector l)
  153. (u8-list->bytevector (map s8->u8 l)))
  154. (define (make-bytevector->int-list bytevector-ref)
  155. (lambda (size endness b)
  156. (let ((ref (cut bytevector-ref size endness b <>))
  157. (length (bytevector-length b)))
  158. (let loop ((i 0) (r '()))
  159. (if (>= i length)
  160. (reverse r)
  161. (loop (+ i size)
  162. (cons (ref i) r)))))))
  163. (define bytevector->uint-list (make-bytevector->int-list bytevector-uint-ref))
  164. (define bytevector->sint-list (make-bytevector->int-list bytevector-sint-ref))
  165. (define (make-int-list->bytevector bytevector-set!)
  166. (lambda (size endness l)
  167. (let* ((bytevector (make-bytevector (* size (length l))))
  168. (set! (cut bytevector-set! size endness bytevector <> <>)))
  169. (let loop ((i 0) (l l))
  170. (if (null? l)
  171. bytevector
  172. (begin
  173. (set! i (car l))
  174. (loop (+ i size) (cdr l))))))))
  175. (define uint-list->bytevector (make-int-list->bytevector bytevector-uint-set!))
  176. (define sint-list->bytevector (make-int-list->bytevector bytevector-sint-set!))
  177. ;; Local Variables:
  178. ;; eval: (put 'index-iterate 'scheme-indent-function 4)
  179. ;; End: