This repository has been archived on 2022-08-10. You can view files and clone it, but cannot push or open issues or pull requests.
chez-openbsd/ta6ob/s/bytevector.ss
2022-08-09 23:28:25 +02:00

1517 lines
62 KiB
Scheme

;;; bytevector.ss
;;; Copyright 1984-2017 Cisco Systems, Inc.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;; http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.
(let ()
(define-syntax signed-value-pred
(lambda (x)
(syntax-case x ()
[(_ ?bits)
(let ([bits (syntax->datum #'?bits)])
(unless (and (fixnum? bits)
(fx> bits 0)
(fx= (* (fxquotient bits 8) 8) bits))
(syntax-error #'?bits "invalid bits"))
(cond
[(fx<= bits (constant fixnum-bits))
(with-syntax ([limit- (- (expt 2 (- bits 1)))]
[limit+ (- (expt 2 (- bits 1)) 1)])
#'(lambda (k) (and (fixnum? k) (fx<= limit- k limit+))))]
[(fx= bits (constant fixnum-bits)) #'fixnum?]
[else
(with-syntax ([limit- (- (expt 2 (- bits 1)))]
[limit+ (- (expt 2 (- bits 1)) 1)])
#'(lambda (k)
(or (fixnum? k)
(and (bignum? k) (<= limit- k limit+)))))]))])))
(define-syntax unsigned-value-pred
(lambda (x)
(syntax-case x ()
[(_ ?bits)
(let ([bits (syntax->datum #'?bits)])
(unless (and (fixnum? bits)
(fx> bits 0)
(fx= (* (fxquotient bits 8) 8) bits))
(syntax-error #'?bits "invalid bits"))
(cond
[(fx< bits (constant fixnum-bits))
(with-syntax ([limit+ (expt 2 bits)])
#'(lambda (k) (and (fixnum? k) ($fxu< k limit+))))]
[(fx= bits (constant fixnum-bits))
#'(lambda (k) (and (fixnum? k) (fx>= k 0)))]
[else
(with-syntax ([limit+ (- (expt 2 bits) 1)])
#'(lambda (k)
(if (fixnum? k)
(fx>= k 0)
(and (bignum? k) (<= 0 k limit+)))))]))])))
(define (not-a-bytevector who v)
($oops who "~s is not a bytevector" v))
(define (not-a-mutable-bytevector who v)
($oops who "~s is not a mutable bytevector" v))
(define (invalid-index who v i)
($oops who "invalid index ~s for bytevector ~s" i v))
(define (invalid-fill-value who fill)
($oops who "~s is not a valid fill value" fill))
(define (invalid-value who x)
($oops who "invalid value ~s" x))
(define (size-multiple-error who n size)
($oops who "bytevector length ~s is not a multiple of size ~s"
n size))
(define (unrecognized-endianness who eness)
($oops who "unrecognized endianness ~s" eness))
(define (invalid-size who size)
($oops who "invalid size ~s" size))
(define (invalid-size-or-index who size v i)
(if (and (fixnum? i) ($fxu< i (bytevector-length v)))
(if ($fxu< size (bytevector-length v))
($oops who "invalid index ~s for ~s-byte field of bytevector ~s" i size v)
($oops who "invalid size ~s for bytevector ~s" size v))
(invalid-index who v i)))
(define (fill? x) (and (fixnum? x) (fx<= -128 x 255)))
(define-syntax unaligned-ref-check
(syntax-rules ()
[(_ who ?size v i)
(let ([size ?size])
(unless (and (fixnum? i)
(fx>= i 0)
(fx< i (fx- (bytevector-length v) (fx- size 1))))
(invalid-size-or-index who size v i)))]))
(module ($bytevector-sint-little-ref $bytevector-uint-little-ref)
(define (load-little v i size a)
(cond
[(fx>= size 3)
(load-little v (fx- i 3) (fx- size 3)
(logor (ash a 24)
(fxlogor
(fxsll (bytevector-u8-ref v i) 16)
(fxsll (bytevector-u8-ref v (fx- i 1)) 8)
(bytevector-u8-ref v (fx- i 2)))))]
[(fx= size 0) a]
[(fx= size 1) (logor (ash a 8) (bytevector-u8-ref v i))]
[else (logor (ash a 16)
(fxlogor
(fxsll (bytevector-u8-ref v i) 8)
(bytevector-u8-ref v (fx- i 1))))]))
(define ($bytevector-sint-little-ref v i size)
(let ([i (fx+ i size -1)])
(load-little v (fx- i 1) (fx- size 1) (bytevector-s8-ref v i))))
(define ($bytevector-uint-little-ref v i size)
(let ([i (fx+ i size -1)])
(load-little v (fx- i 1) (fx- size 1) (bytevector-u8-ref v i)))))
(module ($bytevector-sint-big-ref $bytevector-uint-big-ref)
(define (load-big v i size a)
(cond
[(fx>= size 3)
(load-big v (fx+ i 3) (fx- size 3)
(logor (ash a 24)
(fxlogor
(fxsll (bytevector-u8-ref v i) 16)
(fxsll (bytevector-u8-ref v (fx+ i 1)) 8)
(bytevector-u8-ref v (fx+ i 2)))))]
[(fx= size 0) a]
[(fx= size 1) (logor (ash a 8) (bytevector-u8-ref v i))]
[else (logor (ash a 16)
(fxlogor
(fxsll (bytevector-u8-ref v i) 8)
(bytevector-u8-ref v (fx+ i 1))))]))
(define ($bytevector-sint-big-ref v i size)
(load-big v (fx+ i 1) (fx- size 1) (bytevector-s8-ref v i)))
(define ($bytevector-uint-big-ref v i size)
(load-big v (fx+ i 1) (fx- size 1) (bytevector-u8-ref v i))))
(define ($bytevector-int-little-set! v i k size)
(let store-little! ([i i] [k k] [size size])
(cond
[(fx>= size 4)
(let ([k (logand k #xffffff)])
(bytevector-u8-set! v i (fxlogand k #xff))
(bytevector-u8-set! v (fx+ i 1) (fxlogand (fxsra k 8) #xff))
(bytevector-u8-set! v (fx+ i 2) (fxsra k 16)))
(store-little! (fx+ i 3) (ash k -24) (fx- size 3))]
[(fx= size 1) ($bytevector-set! v i k)]
[(fx= size 2)
(bytevector-u8-set! v i (fxlogand k #xff))
($bytevector-set! v (fx+ i 1) (fxsra k 8))]
[else
(bytevector-u8-set! v i (fxlogand k #xff))
(bytevector-u8-set! v (fx+ i 1) (fxlogand (fxsra k 8) #xff))
($bytevector-set! v (fx+ i 2) (fxsra k 16))])))
(define ($bytevector-int-big-set! v i k size)
(let store-big! ([i (fx+ i size -1)] [k k] [size size])
(cond
[(fx>= size 4)
(let ([k (logand k #xffffff)])
(bytevector-u8-set! v (fx- i 2) (fxsra k 16))
(bytevector-u8-set! v (fx- i 1) (fxlogand (fxsra k 8) #xff))
(bytevector-u8-set! v i (fxlogand k #xff)))
(store-big! (fx- i 3) (ash k -24) (fx- size 3))]
[(fx= size 1) ($bytevector-set! v i k)]
[(fx= size 2)
($bytevector-set! v (fx- i 1) (fxsra k 8))
(bytevector-u8-set! v i (fxlogand k #xff))]
[else
($bytevector-set! v (fx- i 2) (fxsra k 16))
(bytevector-u8-set! v (fx- i 1) (fxlogand (fxsra k 8) #xff))
(bytevector-u8-set! v i (fxlogand k #xff))])))
(module ($bytevector-s16-ref $bytevector-u16-ref
$bytevector-s24-ref $bytevector-u24-ref
$bytevector-s32-ref $bytevector-u32-ref
$bytevector-s40-ref $bytevector-u40-ref
$bytevector-s48-ref $bytevector-u48-ref
$bytevector-s56-ref $bytevector-u56-ref
$bytevector-s64-ref $bytevector-u64-ref)
(meta-cond
[(fx> (constant fixnum-bits) 56)
(define logor56 fxlogor)
(define sll56 fxsll)]
[else
(define logor56 logor)
(define sll56 ash)])
(define (little-ref-s16 v i)
(fxlogor (fxsll (#3%bytevector-s8-ref v (fx+ i 1)) 8)
(#3%bytevector-u8-ref v i)))
(define (big-ref-s16 v i)
(fxlogor (fxsll (#3%bytevector-s8-ref v i) 8)
(#3%bytevector-u8-ref v (fx+ i 1))))
(define (little-ref-u16 v i)
(fxlogor (fxsll (#3%bytevector-u8-ref v (fx+ i 1)) 8)
(#3%bytevector-u8-ref v i)))
(define (big-ref-u16 v i)
(fxlogor (fxsll (#3%bytevector-u8-ref v i) 8)
(#3%bytevector-u8-ref v (fx+ i 1))))
(define (little-ref-s24 v i)
(fxlogor (fxsll (#3%bytevector-s8-ref v (fx+ i 2)) 16)
(little-ref-u16 v i)))
(define (big-ref-s24 v i)
(fxlogor (fxsll (#3%bytevector-s8-ref v i) 16)
(big-ref-u16 v (fx+ i 1))))
(define (little-ref-u24 v i)
(fxlogor (fxsll (#3%bytevector-u8-ref v (fx+ i 2)) 16)
(little-ref-u16 v i)))
(define (big-ref-u24 v i)
(fxlogor (fxsll (#3%bytevector-u8-ref v i) 16)
(big-ref-u16 v (fx+ i 1))))
(define (little-ref-s32 v i)
(logor56 (sll56 (little-ref-s16 v (fx+ i 2)) 16)
(little-ref-u16 v i)))
(define (big-ref-s32 v i)
(logor56 (sll56 (big-ref-s16 v i) 16)
(big-ref-u16 v (fx+ i 2))))
(define (little-ref-u32 v i)
(logor56 (sll56 (little-ref-u16 v (fx+ i 2)) 16)
(little-ref-u16 v i)))
(define (big-ref-u32 v i)
(logor56 (sll56 (big-ref-u16 v i) 16)
(big-ref-u16 v (fx+ i 2))))
(define (little-ref-s40 v i)
(logor56 (sll56(#3%bytevector-s8-ref v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-s40 v i)
(logor56 (sll56(#3%bytevector-s8-ref v i) 32)
(big-ref-u32 v (fx+ i 1))))
(define (little-ref-u40 v i)
(logor56 (sll56(#3%bytevector-u8-ref v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-u40 v i)
(logor56 (sll56(#3%bytevector-u8-ref v i) 32)
(big-ref-u32 v (fx+ i 1))))
(define (little-ref-s48 v i)
(logor56 (sll56(little-ref-s16 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-s48 v i)
(logor56 (sll56(big-ref-s16 v i) 32)
(big-ref-u32 v (fx+ i 2))))
(define (little-ref-u48 v i)
(logor56 (sll56(little-ref-u16 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-u48 v i)
(logor56 (sll56(big-ref-u16 v i) 32)
(big-ref-u32 v (fx+ i 2))))
(define (little-ref-s56 v i)
(logor56 (sll56(little-ref-s24 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-s56 v i)
(logor56 (sll56(big-ref-s24 v i) 32)
(big-ref-u32 v (fx+ i 3))))
(define (little-ref-u56 v i)
(logor56 (sll56(little-ref-u24 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-u56 v i)
(logor56 (sll56(big-ref-u24 v i) 32)
(big-ref-u32 v (fx+ i 3))))
(define (little-ref-s64 v i)
(logor (ash (little-ref-s32 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-s64 v i)
(logor (ash (big-ref-s32 v i) 32)
(big-ref-u32 v (fx+ i 4))))
(define (little-ref-u64 v i)
(logor (ash (little-ref-u32 v (fx+ i 4)) 32)
(little-ref-u32 v i)))
(define (big-ref-u64 v i)
(logor (ash (big-ref-u32 v i) 32)
(big-ref-u32 v (fx+ i 4))))
(define-syntax bytevector-*-ref
(lambda (x)
(define p2?
(lambda (n)
(let f ([i 1])
(or (fx= i n)
(and (not (fx> i n)) (f (fxsll i 1)))))))
(syntax-case x ()
[(kwd s/u bits)
(with-syntax ([prim-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-ref")]
[native-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-native-ref")]
[little-ref (construct-name #'kwd "little-ref-" #'s/u #'bits)]
[big-ref (construct-name #'kwd "big-ref-" #'s/u #'bits)])
#`(lambda (v i eness who)
(unless (bytevector? v) (not-a-bytevector who v))
(unaligned-ref-check who (fxquotient bits 8) v i)
(case eness
[(big)
#,(cond
[(constant unaligned-integers) #`(#3%prim-name v i 'big)]
[(and (eq? (constant native-endianness) 'big) (p2? (datum bits)))
#`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0)
(#3%native-name v i)
(big-ref v i))]
[else #`(big-ref v i)])]
[(little)
#,(cond
[(constant unaligned-integers) #`(#3%prim-name v i 'little)]
[(and (eq? (constant native-endianness) 'little) (p2? (datum bits)))
#`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0)
(#3%native-name v i)
(little-ref v i))]
[else #`(little-ref v i)])]
[else (unrecognized-endianness who eness)])))])))
(define $bytevector-s16-ref (bytevector-*-ref s 16))
(define $bytevector-u16-ref (bytevector-*-ref u 16))
(define $bytevector-s24-ref (bytevector-*-ref s 24))
(define $bytevector-u24-ref (bytevector-*-ref u 24))
(define $bytevector-s32-ref (bytevector-*-ref s 32))
(define $bytevector-u32-ref (bytevector-*-ref u 32))
(define $bytevector-s40-ref (bytevector-*-ref s 40))
(define $bytevector-u40-ref (bytevector-*-ref u 40))
(define $bytevector-s48-ref (bytevector-*-ref s 48))
(define $bytevector-u48-ref (bytevector-*-ref u 48))
(define $bytevector-s56-ref (bytevector-*-ref s 56))
(define $bytevector-u56-ref (bytevector-*-ref u 56))
(define $bytevector-s64-ref (bytevector-*-ref s 64))
(define $bytevector-u64-ref (bytevector-*-ref u 64))
)
(module ($bytevector-s16-set! $bytevector-u16-set!
$bytevector-s24-set! $bytevector-u24-set!
$bytevector-s32-set! $bytevector-u32-set!
$bytevector-s40-set! $bytevector-u40-set!
$bytevector-s48-set! $bytevector-u48-set!
$bytevector-s56-set! $bytevector-u56-set!
$bytevector-s64-set! $bytevector-u64-set!)
(meta-cond
[(fx> (constant fixnum-bits) 56)
(define logand56 fxlogand)
(define sra56 fxsra)]
[else
(define logand56 logand)
(define sra56 (lambda (x y) (ash x (fx- y))))])
(define (little-set-s16! v i k)
(#3%bytevector-u8-set! v i (fxlogand k #xff))
(#3%bytevector-s8-set! v (fx+ i 1) (fxsra k 8)))
(define (big-set-s16! v i k)
(#3%bytevector-s8-set! v i (fxsra k 8))
(#3%bytevector-u8-set! v (fx+ i 1) (fxlogand k #xff)))
(define (little-set-u16! v i k)
(#3%bytevector-u8-set! v i (fxlogand k #xff))
(#3%bytevector-u8-set! v (fx+ i 1) (fxsra k 8)))
(define (big-set-u16! v i k)
(#3%bytevector-u8-set! v i (fxsra k 8))
(#3%bytevector-u8-set! v (fx+ i 1) (fxlogand k #xff)))
(define (little-set-s24! v i k)
(little-set-u16! v i (fxlogand k #xffff))
(#3%bytevector-s8-set! v (fx+ i 2) (fxsra k 16)))
(define (big-set-s24! v i k)
(#3%bytevector-s8-set! v i (fxsra k 16))
(big-set-u16! v (fx+ i 1) (fxlogand k #xffff)))
(define (little-set-u24! v i k)
(little-set-u16! v i (fxlogand k #xffff))
(#3%bytevector-u8-set! v (fx+ i 2) (fxsra k 16)))
(define (big-set-u24! v i k)
(#3%bytevector-u8-set! v i (fxsra k 16))
(big-set-u16! v (fx+ i 1) (fxlogand k #xffff)))
(define (little-set-s32! v i k)
(little-set-u16! v i (logand56 k #xffff))
(little-set-s16! v (fx+ i 2) (sra56 k 16)))
(define (big-set-s32! v i k)
(big-set-s16! v i (sra56 k 16))
(big-set-u16! v (fx+ i 2) (logand56 k #xffff)))
(define (little-set-u32! v i k)
(little-set-u16! v i (logand56 k #xffff))
(little-set-u16! v (fx+ i 2) (sra56 k 16)))
(define (big-set-u32! v i k)
(big-set-u16! v i (sra56 k 16))
(big-set-u16! v (fx+ i 2) (logand56 k #xffff)))
(define (little-set-s40! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(#3%bytevector-s8-set! v (fx+ i 4) (sra56 k 32)))
(define (big-set-s40! v i k)
(#3%bytevector-s8-set! v i (sra56 k 32))
(big-set-u32! v (fx+ i 1) (logand56 k #xffffffff)))
(define (little-set-u40! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(#3%bytevector-u8-set! v (fx+ i 4) (sra56 k 32)))
(define (big-set-u40! v i k)
(#3%bytevector-u8-set! v i (sra56 k 32))
(big-set-u32! v (fx+ i 1) (logand56 k #xffffffff)))
(define (little-set-s48! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(little-set-s16! v (fx+ i 4) (sra56 k 32)))
(define (big-set-s48! v i k)
(big-set-s16! v i (sra56 k 32))
(big-set-u32! v (fx+ i 2) (logand56 k #xffffffff)))
(define (little-set-u48! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(little-set-u16! v (fx+ i 4) (sra56 k 32)))
(define (big-set-u48! v i k)
(big-set-u16! v i (sra56 k 32))
(big-set-u32! v (fx+ i 2) (logand56 k #xffffffff)))
(define (little-set-s56! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(little-set-s24! v (fx+ i 4) (sra56 k 32)))
(define (big-set-s56! v i k)
(big-set-s24! v i (sra56 k 32))
(big-set-u32! v (fx+ i 3) (logand56 k #xffffffff)))
(define (little-set-u56! v i k)
(little-set-u32! v i (logand56 k #xffffffff))
(little-set-u24! v (fx+ i 4) (sra56 k 32)))
(define (big-set-u56! v i k)
(big-set-u24! v i (sra56 k 32))
(big-set-u32! v (fx+ i 3) (logand56 k #xffffffff)))
(define (little-set-s64! v i k)
(little-set-u32! v i (logand k #xffffffff))
(little-set-s32! v (fx+ i 4) (ash k -32)))
(define (big-set-s64! v i k)
(big-set-s32! v i (ash k -32))
(big-set-u32! v (fx+ i 4) (logand k #xffffffff)))
(define (little-set-u64! v i k)
(little-set-u32! v i (logand k #xffffffff))
(little-set-u32! v (fx+ i 4) (ash k -32)))
(define (big-set-u64! v i k)
(big-set-u32! v i (ash k -32))
(big-set-u32! v (fx+ i 4) (logand k #xffffffff)))
(define-syntax bytevector-*-set!
(lambda (x)
(define p2?
(lambda (n)
(let f ([i 1])
(or (fx= i n)
(and (not (fx> i n)) (f (fxsll i 1)))))))
(syntax-case x ()
[(kwd s/u bits)
(with-syntax ([prim-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-set!")]
[native-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-native-set!")]
[little-set! (construct-name #'kwd "little-set-" #'s/u #'bits "!")]
[big-set! (construct-name #'kwd "big-set-" #'s/u #'bits "!")]
[value-pred (if (free-identifier=? #'s/u #'s)
#'signed-value-pred
#'unsigned-value-pred)])
#`(let ([value-okay? (value-pred bits)])
(lambda (v i k eness who)
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unaligned-ref-check who (fxquotient bits 8) v i)
(unless (value-okay? k) (invalid-value who k))
(case eness
[(big)
#,(cond
[(and (constant unaligned-integers) (>= (constant ptr-bits) (datum bits)))
#`(#3%prim-name v i k 'big)]
[(and (eq? (constant native-endianness) 'big) (fx>= (constant ptr-bits) (datum bits)) (p2? (datum bits)))
#`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0)
(#3%native-name v i k)
(big-set! v i k))]
[else #`(big-set! v i k)])]
[(little)
#,(cond
[(and (constant unaligned-integers) (>= (constant ptr-bits) (datum bits)))
#`(#3%prim-name v i k 'little)]
[(and (eq? (constant native-endianness) 'little) (fx>= (constant ptr-bits) (datum bits)) (p2? (datum bits)))
#`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0)
(#3%native-name v i k)
(little-set! v i k))]
[else #`(little-set! v i k)])]
[else (unrecognized-endianness who eness)]))))])))
(define $bytevector-s16-set! (bytevector-*-set! s 16))
(define $bytevector-u16-set! (bytevector-*-set! u 16))
(define $bytevector-s24-set! (bytevector-*-set! s 24))
(define $bytevector-u24-set! (bytevector-*-set! u 24))
(define $bytevector-s32-set! (bytevector-*-set! s 32))
(define $bytevector-u32-set! (bytevector-*-set! u 32))
(define $bytevector-s40-set! (bytevector-*-set! s 40))
(define $bytevector-u40-set! (bytevector-*-set! u 40))
(define $bytevector-s48-set! (bytevector-*-set! s 48))
(define $bytevector-u48-set! (bytevector-*-set! u 48))
(define $bytevector-s56-set! (bytevector-*-set! s 56))
(define $bytevector-u56-set! (bytevector-*-set! u 56))
(define $bytevector-s64-set! (bytevector-*-set! s 64))
(define $bytevector-u64-set! (bytevector-*-set! u 64))
)
(set! native-endianness
(lambda ()
(#2%native-endianness)))
(set-who! make-bytevector
(case-lambda
[(n fill)
(unless (and (fixnum? n) (not ($fxu< (constant maximum-bytevector-length) n)))
($oops who "~s is not a valid bytevector length" n))
(unless (fill? fill) (invalid-fill-value who fill))
(#3%make-bytevector n fill)]
[(n)
(unless (and (fixnum? n) (not ($fxu< (constant maximum-bytevector-length) n)))
($oops who "~s is not a valid bytevector length" n))
(#3%make-bytevector n)]))
(set! bytevector? (lambda (x) (#2%bytevector? x)))
(set! bytevector-length
(lambda (v)
(#2%bytevector-length v)))
(set-who! $bytevector-set-immutable!
(lambda (v)
(unless (bytevector? v)
($oops who "~s is not a bytevector" v))
(#3%$bytevector-set-immutable! v)))
(set-who! mutable-bytevector?
(lambda (v)
(#3%mutable-bytevector? v)))
(set-who! immutable-bytevector?
(lambda (v)
(#3%immutable-bytevector? v)))
(set! bytevector-s8-ref
(lambda (v i)
(#2%bytevector-s8-ref v i)))
(set! bytevector-u8-ref
(lambda (v i)
(#2%bytevector-u8-ref v i)))
(set! bytevector-s8-set!
(lambda (v i byte)
(#2%bytevector-s8-set! v i byte)))
(set! bytevector-u8-set!
(lambda (v i octet)
(#2%bytevector-u8-set! v i octet)))
(set-who! $bytevector-set!
(lambda (v i fill)
(if ($bytevector-set!-check? 8 v i)
(begin
(unless (fill? fill) (invalid-value who fill))
(#3%$bytevector-set! v i fill))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v)))))
(set-who! bytevector-s16-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 16 v i)
(#3%bytevector-s16-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-u16-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 16 v i)
(#3%bytevector-u16-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-s16-native-set!
(let ([value-okay? (signed-value-pred 16)])
(lambda (v i k)
(if ($bytevector-set!-check? 16 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(#3%bytevector-s16-native-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-u16-native-set!
(let ([value-okay? (unsigned-value-pred 16)])
(lambda (v i k)
(if ($bytevector-set!-check? 16 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(#3%bytevector-u16-native-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-s32-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 32 v i)
(#3%bytevector-s32-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-u32-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 32 v i)
(#3%bytevector-u32-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-s32-native-set!
(let ([value-okay? (signed-value-pred 32)])
(lambda (v i k)
(if ($bytevector-set!-check? 32 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(#3%bytevector-s32-native-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-u32-native-set!
(let ([value-okay? (unsigned-value-pred 32)])
(lambda (v i k)
(if ($bytevector-set!-check? 32 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(#3%bytevector-u32-native-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-s64-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 64 v i)
(constant-case ptr-bits
[(64) (#3%bytevector-s64-native-ref v i)]
[(32)
(constant-case native-endianness
[(big)
(logor (ash (#3%bytevector-s32-native-ref v i) 32)
(#3%bytevector-u32-native-ref v (fx+ i 4)))]
[(little)
(logor (ash (#3%bytevector-s32-native-ref v (fx+ i 4)) 32)
(#3%bytevector-u32-native-ref v i))])])
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-u64-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 64 v i)
(constant-case ptr-bits
[(64) (#3%bytevector-u64-native-ref v i)]
[(32)
(constant-case native-endianness
[(big)
(logor (ash (#3%bytevector-u32-native-ref v i) 32)
(#3%bytevector-u32-native-ref v (fx+ i 4)))]
[(little)
(logor (ash (#3%bytevector-u32-native-ref v (fx+ i 4)) 32)
(#3%bytevector-u32-native-ref v i))])])
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-s64-native-set!
(let ([value-okay? (signed-value-pred 64)])
(lambda (v i k)
(if ($bytevector-set!-check? 64 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(constant-case ptr-bits
[(64) (#3%bytevector-s64-native-set! v i k)]
[(32)
(constant-case native-endianness
[(big)
(#3%bytevector-s32-native-set! v i (ash k -32))
(#3%bytevector-u32-native-set! v (fx+ i 4) (logand k (- (expt 2 32) 1)))]
[(little)
(#3%bytevector-s32-native-set! v (fx+ i 4) (ash k -32))
(#3%bytevector-u32-native-set! v i (logand k (- (expt 2 32) 1)))])]))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-u64-native-set!
(let ([value-okay? (unsigned-value-pred 64)])
(lambda (v i k)
(if ($bytevector-set!-check? 64 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(constant-case ptr-bits
[(64) (#3%bytevector-u64-native-set! v i k)]
[(32)
(constant-case native-endianness
[(big)
(#3%bytevector-u32-native-set! v i (ash k -32))
(#3%bytevector-u32-native-set! v (fx+ i 4) (logand k (- (expt 2 32) 1)))]
[(little)
(#3%bytevector-u32-native-set! v (fx+ i 4) (ash k -32))
(#3%bytevector-u32-native-set! v i (logand k (- (expt 2 32) 1)))])]))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-ieee-single-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 32 v i)
(#3%bytevector-ieee-single-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-ieee-double-native-ref
(lambda (v i)
(if ($bytevector-ref-check? 64 v i)
(#3%bytevector-ieee-double-native-ref v i)
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v)))))
(set-who! bytevector-ieee-single-native-set!
(lambda (v i x)
(if ($bytevector-set!-check? 32 v i)
; inline routine checks to make sure x is a real number
(#3%bytevector-ieee-single-native-set! v i x)
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v)))))
(set-who! bytevector-ieee-double-native-set!
(lambda (v i x)
(if ($bytevector-set!-check? 64 v i)
; inline routine checks to make sure x is a real number
(#3%bytevector-ieee-double-native-set! v i x)
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v)))))
(set-who! bytevector-copy
(lambda (v)
(unless (bytevector? v) (not-a-bytevector who v))
(let* ([n (bytevector-length v)] [v2 (make-bytevector n)])
($ptr-copy! v (constant bytevector-data-disp) v2
(constant bytevector-data-disp)
(fxsrl
(fx+ n (fx- (constant ptr-bytes) 1))
(constant log2-ptr-bytes)))
v2)))
(set-who! bytevector-copy!
(lambda (v1 i1 v2 i2 k)
(unless (bytevector? v1) (not-a-bytevector who v1))
(unless (mutable-bytevector? v2) (not-a-mutable-bytevector who v2))
(let ([n1 (bytevector-length v1)] [n2 (bytevector-length v2)])
(unless (and (fixnum? i1) (fx>= i1 0))
($oops who "invalid start value ~s" i1))
(unless (and (fixnum? i2) (fx>= i2 0))
($oops who "invalid start value ~s" i2))
(unless (and (fixnum? k) (fx>= k 0))
($oops who "invalid count ~s" k))
(unless (fx<= k (fx- n1 i1)) ; avoid overflow
($oops who "index ~s + count ~s is beyond the end of ~s" i1 k v1))
(unless (fx<= k (fx- n2 i2)) ; avoid overflow
($oops who "index ~s + count ~s is beyond the end of ~s" i2 k v2))
; whew!
(#3%bytevector-copy! v1 i1 v2 i2 k))))
(set-who! bytevector->immutable-bytevector
(lambda (v)
(cond
[(immutable-bytevector? v) v]
[(eqv? v '#vu8()) ($tc-field 'null-immutable-bytevector ($tc))]
[else
(unless (bytevector? v) ($oops who "~s is not a bytevector" v))
(let ([v2 (bytevector-copy v)])
($bytevector-set-immutable! v2)
v2)])))
(set-who! bytevector-fill!
(lambda (v fill)
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unless (fill? fill) (invalid-fill-value who fill))
(#3%bytevector-fill! v fill)))
(set-who! bytevector=?
(lambda (v1 v2)
(unless (bytevector? v1) (not-a-bytevector who v1))
(unless (bytevector? v2) (not-a-bytevector who v2))
(#3%bytevector=? v1 v2)))
(set-who! $bytevector-ref-check?
(lambda (bits v i)
; inlined handles only constant bits argument
(case bits
[(8) (#2%$bytevector-ref-check? 8 v i)]
[(16) (#2%$bytevector-ref-check? 16 v i)]
[(32) (#2%$bytevector-ref-check? 32 v i)]
[(64) (#2%$bytevector-ref-check? 64 v i)]
[else ($oops who "invalid bits argument ~s" bits)])))
(set-who! $bytevector-set!-check?
(lambda (bits v i)
; inlined handles only constant bits argument
(case bits
[(8) (#2%$bytevector-set!-check? 8 v i)]
[(16) (#2%$bytevector-set!-check? 16 v i)]
[(32) (#2%$bytevector-set!-check? 32 v i)]
[(64) (#2%$bytevector-set!-check? 64 v i)]
[else ($oops who "invalid bits argument ~s" bits)])))
(set-who! bytevector-s16-ref
(lambda (v i eness)
($bytevector-s16-ref v i eness who)))
(set-who! bytevector-u16-ref
(lambda (v i eness)
($bytevector-u16-ref v i eness who)))
(set-who! bytevector-s24-ref
(lambda (v i eness)
($bytevector-s24-ref v i eness who)))
(set-who! bytevector-u24-ref
(lambda (v i eness)
($bytevector-u24-ref v i eness who)))
(set-who! bytevector-s32-ref
(lambda (v i eness)
($bytevector-s32-ref v i eness who)))
(set-who! bytevector-u32-ref
(lambda (v i eness)
($bytevector-u32-ref v i eness who)))
(set-who! bytevector-s40-ref
(lambda (v i eness)
($bytevector-s40-ref v i eness who)))
(set-who! bytevector-u40-ref
(lambda (v i eness)
($bytevector-u40-ref v i eness who)))
(set-who! bytevector-s48-ref
(lambda (v i eness)
($bytevector-s48-ref v i eness who)))
(set-who! bytevector-u48-ref
(lambda (v i eness)
($bytevector-u48-ref v i eness who)))
(set-who! bytevector-s56-ref
(lambda (v i eness)
($bytevector-s56-ref v i eness who)))
(set-who! bytevector-u56-ref
(lambda (v i eness)
($bytevector-u56-ref v i eness who)))
(set-who! bytevector-s64-ref
(lambda (v i eness)
($bytevector-s64-ref v i eness who)))
(set-who! bytevector-u64-ref
(lambda (v i eness)
($bytevector-u64-ref v i eness who)))
(set-who! bytevector-s16-set!
(lambda (v i k eness)
($bytevector-s16-set! v i k eness who)))
(set-who! bytevector-u16-set!
(lambda (v i k eness)
($bytevector-u16-set! v i k eness who)))
(set-who! bytevector-s24-set!
(lambda (v i k eness)
($bytevector-s24-set! v i k eness who)))
(set-who! bytevector-u24-set!
(lambda (v i k eness)
($bytevector-u24-set! v i k eness who)))
(set-who! bytevector-s32-set!
(lambda (v i k eness)
($bytevector-s32-set! v i k eness who)))
(set-who! bytevector-u32-set!
(lambda (v i k eness)
($bytevector-u32-set! v i k eness who)))
(set-who! bytevector-s40-set!
(lambda (v i k eness)
($bytevector-s40-set! v i k eness who)))
(set-who! bytevector-u40-set!
(lambda (v i k eness)
($bytevector-u40-set! v i k eness who)))
(set-who! bytevector-s48-set!
(lambda (v i k eness)
($bytevector-s48-set! v i k eness who)))
(set-who! bytevector-u48-set!
(lambda (v i k eness)
($bytevector-u48-set! v i k eness who)))
(set-who! bytevector-s56-set!
(lambda (v i k eness)
($bytevector-s56-set! v i k eness who)))
(set-who! bytevector-u56-set!
(lambda (v i k eness)
($bytevector-u56-set! v i k eness who)))
(set-who! bytevector-s64-set!
(lambda (v i k eness)
($bytevector-s64-set! v i k eness who)))
(set-who! bytevector-u64-set!
(lambda (v i k eness)
($bytevector-u64-set! v i k eness who)))
(set-who! bytevector-ieee-single-ref
(lambda (v i eness)
(define (swap-ref v i)
(bytevector-ieee-single-native-ref
(bytevector
(bytevector-u8-ref v (fx+ i 3))
(bytevector-u8-ref v (fx+ i 2))
(bytevector-u8-ref v (fx+ i 1))
(bytevector-u8-ref v i))
0))
(define (noswap-ref v i)
(bytevector-ieee-single-native-ref
(bytevector
(bytevector-u8-ref v i)
(bytevector-u8-ref v (fx+ i 1))
(bytevector-u8-ref v (fx+ i 2))
(bytevector-u8-ref v (fx+ i 3)))
0))
(unless (bytevector? v) (not-a-bytevector who v))
(unaligned-ref-check who 4 v i)
(if (or (constant unaligned-floats) (fx= (fxlogand i 3) 0))
(if (eq? eness (native-endianness))
(#3%bytevector-ieee-single-native-ref v i)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-ref v i)
(unrecognized-endianness who eness)))
(if (eq? eness (native-endianness))
(noswap-ref v i)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-ref v i)
(unrecognized-endianness who eness))))))
(set-who! bytevector-ieee-double-ref
(lambda (v i eness)
(define (swap-ref v i)
(bytevector-ieee-double-native-ref
(bytevector
(bytevector-u8-ref v (fx+ i 7))
(bytevector-u8-ref v (fx+ i 6))
(bytevector-u8-ref v (fx+ i 5))
(bytevector-u8-ref v (fx+ i 4))
(bytevector-u8-ref v (fx+ i 3))
(bytevector-u8-ref v (fx+ i 2))
(bytevector-u8-ref v (fx+ i 1))
(bytevector-u8-ref v i))
0))
(define (noswap-ref v i)
(bytevector-ieee-double-native-ref
(bytevector
(bytevector-u8-ref v i)
(bytevector-u8-ref v (fx+ i 1))
(bytevector-u8-ref v (fx+ i 2))
(bytevector-u8-ref v (fx+ i 3))
(bytevector-u8-ref v (fx+ i 4))
(bytevector-u8-ref v (fx+ i 5))
(bytevector-u8-ref v (fx+ i 6))
(bytevector-u8-ref v (fx+ i 7)))
0))
(unless (bytevector? v) (not-a-bytevector who v))
(unaligned-ref-check who 8 v i)
(if (or (constant unaligned-floats) (fx= (fxlogand i 7) 0))
(if (eq? eness (native-endianness))
(#3%bytevector-ieee-double-native-ref v i)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-ref v i)
(unrecognized-endianness who eness)))
(if (eq? eness (native-endianness))
(noswap-ref v i)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-ref v i)
(unrecognized-endianness who eness))))))
(set-who! bytevector-ieee-single-set!
(lambda (v i x eness)
(define (swap-set! v i x)
(let ([v2 (make-bytevector 4)])
(bytevector-ieee-single-native-set! v2 0 x)
(bytevector-u8-set! v i (bytevector-u8-ref v2 3))
(bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 2))
(bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 1))
(bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 0))))
(define (noswap-set! v i x)
(let ([v2 (make-bytevector 4)])
(bytevector-ieee-single-native-set! v2 0 x)
(bytevector-u8-set! v i (bytevector-u8-ref v2 0))
(bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 1))
(bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 2))
(bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 3))))
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unaligned-ref-check who 4 v i)
(let ([x ($real->flonum x who)])
(if (or (constant unaligned-floats) (fx= (fxlogand i 3) 0))
(if (eq? eness (native-endianness))
(#3%bytevector-ieee-single-native-set! v i x)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-set! v i x)
(unrecognized-endianness who eness)))
(if (eq? eness (native-endianness))
(noswap-set! v i x)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-set! v i x)
(unrecognized-endianness who eness)))))))
(set-who! bytevector-ieee-double-set!
(lambda (v i x eness)
(define (swap-set! v i x)
(let ([v2 (make-bytevector 8)])
(bytevector-ieee-double-native-set! v2 0 x)
(bytevector-u8-set! v i (bytevector-u8-ref v2 7))
(bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 6))
(bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 5))
(bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 4))
(bytevector-u8-set! v (fx+ i 4) (bytevector-u8-ref v2 3))
(bytevector-u8-set! v (fx+ i 5) (bytevector-u8-ref v2 2))
(bytevector-u8-set! v (fx+ i 6) (bytevector-u8-ref v2 1))
(bytevector-u8-set! v (fx+ i 7) (bytevector-u8-ref v2 0))))
(define (noswap-set! v i x)
(let ([v2 (make-bytevector 8)])
(bytevector-ieee-double-native-set! v2 0 x)
(bytevector-u8-set! v i (bytevector-u8-ref v2 0))
(bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 1))
(bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 2))
(bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 3))
(bytevector-u8-set! v (fx+ i 4) (bytevector-u8-ref v2 4))
(bytevector-u8-set! v (fx+ i 5) (bytevector-u8-ref v2 5))
(bytevector-u8-set! v (fx+ i 6) (bytevector-u8-ref v2 6))
(bytevector-u8-set! v (fx+ i 7) (bytevector-u8-ref v2 7))))
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unaligned-ref-check who 8 v i)
(let ([x ($real->flonum x who)])
(if (or (constant unaligned-floats) (fx= (fxlogand i 7) 0))
(if (eq? eness (native-endianness))
(#3%bytevector-ieee-double-native-set! v i x)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-set! v i x)
(unrecognized-endianness who eness)))
(if (eq? eness (native-endianness))
(noswap-set! v i x)
(if (constant-case native-endianness
[(little) (eq? eness 'big)]
[(big) (eq? eness 'little)])
(swap-set! v i x)
(unrecognized-endianness who eness)))))))
(let ()
(define ($bytevector-s8-ref v i eness who)
(if ($bytevector-ref-check? 8 v i)
(begin
(unless (memq eness '(little big)) (unrecognized-endianness who eness))
(#3%bytevector-s8-ref v i))
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v))))
(define ($bytevector-u8-ref v i eness who)
(if ($bytevector-ref-check? 8 v i)
(begin
(unless (memq eness '(little big)) (unrecognized-endianness who eness))
(#3%bytevector-u8-ref v i))
(if (bytevector? v)
(invalid-index who v i)
(not-a-bytevector who v))))
(set-who! bytevector-sint-ref
(lambda (v i eness size)
(case size
[(1) ($bytevector-s8-ref v i eness who)]
[(2) ($bytevector-s16-ref v i eness who)]
[(4) ($bytevector-s32-ref v i eness who)]
[(8) ($bytevector-s64-ref v i eness who)]
[else
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(unaligned-ref-check who size v i)
(case eness
[(big) ($bytevector-sint-big-ref v i size)]
[(little) ($bytevector-sint-little-ref v i size)]
[else (unrecognized-endianness who eness)])])))
(set-who! bytevector-uint-ref
(lambda (v i eness size)
(case size
[(1) ($bytevector-u8-ref v i eness who)]
[(2) ($bytevector-u16-ref v i eness who)]
[(4) ($bytevector-u32-ref v i eness who)]
[(8) ($bytevector-u64-ref v i eness who)]
[else
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(unaligned-ref-check who size v i)
(case eness
[(big) ($bytevector-uint-big-ref v i size)]
[(little) ($bytevector-uint-little-ref v i size)]
[else (unrecognized-endianness who eness)])]))))
(let ()
(define $bytevector-s8-set!
(let ([value-okay? (signed-value-pred 8)])
(lambda (v i k eness who)
(if ($bytevector-set!-check? 8 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(unless (memq eness '(little big)) (unrecognized-endianness who eness))
(#3%bytevector-s8-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(define $bytevector-u8-set!
(let ([value-okay? (unsigned-value-pred 8)])
(lambda (v i k eness who)
(if ($bytevector-set!-check? 8 v i)
(begin
(unless (value-okay? k) (invalid-value who k))
(unless (memq eness '(little big)) (unrecognized-endianness who eness))
(#3%bytevector-u8-set! v i k))
(if (mutable-bytevector? v)
(invalid-index who v i)
(not-a-mutable-bytevector who v))))))
(set-who! bytevector-sint-set!
(lambda (v i k eness size)
(case size
[(1) ($bytevector-s8-set! v i k eness who)]
[(2) ($bytevector-s16-set! v i k eness who)]
[(4) ($bytevector-s32-set! v i k eness who)]
[(8) ($bytevector-s64-set! v i k eness who)]
[else
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(unaligned-ref-check who size v i)
(unless (and (or (fixnum? k) (bignum? k))
(let ([k (ash k (fx- 1 (fx* size 8)))])
(or (fx= k 0) (fx= k -1))))
(invalid-value who k))
(case eness
[(big) ($bytevector-int-big-set! v i k size)]
[(little) ($bytevector-int-little-set! v i k size)]
[else (unrecognized-endianness who eness)])])))
(set-who! bytevector-uint-set!
(lambda (v i k eness size)
(case size
[(1) ($bytevector-u8-set! v i k eness who)]
[(2) ($bytevector-u16-set! v i k eness who)]
[(4) ($bytevector-u32-set! v i k eness who)]
[(8) ($bytevector-u64-set! v i k eness who)]
[else
(unless (mutable-bytevector? v) (not-a-mutable-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(unaligned-ref-check who size v i)
(unless (and (or (fixnum? k) (bignum? k))
(fx= (ash k (fx- (fx* size 8))) 0))
(invalid-value who k))
(case eness
[(big) ($bytevector-int-big-set! v i k size)]
[(little) ($bytevector-int-little-set! v i k size)]
[else (unrecognized-endianness who eness)])]))))
(let ()
(define-syntax bv->list
(syntax-rules ()
[(_ bytes ref)
(lambda (v who)
(unless (bytevector? v) (not-a-bytevector who v))
(let ([n (bytevector-length v)])
(unless (fx= (fxlogand n (fx- bytes 1)) 0)
(size-multiple-error who n bytes))
(let loop ([i (fx- n bytes)] [ls '()])
(if (fx> i 0)
(loop
(fx- i (fx* bytes 2))
(list* (ref v (fx- i bytes)) (ref v i) ls))
(if (fx= i 0) (cons (ref v 0) ls) ls)))))]))
(define $bytevector->s8-list (bv->list 1 bytevector-s8-ref))
(define $bytevector->u8-list (bv->list 1 bytevector-u8-ref))
(define $bytevector->s16-native-list (bv->list 2 bytevector-s16-native-ref))
(define $bytevector->u16-native-list (bv->list 2 bytevector-u16-native-ref))
(define $bytevector->s32-native-list (bv->list 4 bytevector-s32-native-ref))
(define $bytevector->u32-native-list (bv->list 4 bytevector-u32-native-ref))
(define $bytevector->s64-native-list (bv->list 8 bytevector-s64-native-ref))
(define $bytevector->u64-native-list (bv->list 8 bytevector-u64-native-ref))
(set-who! bytevector->s8-list
(lambda (v)
($bytevector->s8-list v who)))
(set-who! bytevector->u8-list
(lambda (v)
($bytevector->u8-list v who)))
(set-who! bytevector->sint-list
(lambda (v eness size)
(define (big->list v size)
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([n (bytevector-length v)])
(unless (fx= (fxremainder n size) 0) (size-multiple-error who n size))
(let f ([i 0])
(if (fx= i n)
'()
(cons ($bytevector-sint-big-ref v i size)
(f (fx+ i size)))))))
(define (little->list v size)
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([n (bytevector-length v)])
(unless (fx= (fxremainder n size) 0) (size-multiple-error who n size))
(let f ([i 0])
(if (fx= i n)
'()
(cons ($bytevector-sint-little-ref v i size)
(f (fx+ i size)))))))
(if (eq? eness (native-endianness))
(case size
[(1) ($bytevector->s8-list v who)]
[(2) ($bytevector->s16-native-list v who)]
[(4) ($bytevector->s32-native-list v who)]
[(8) ($bytevector->s64-native-list v who)]
[else
(constant-case native-endianness
[(little) (little->list v size)]
[(big) (big->list v size)])])
(constant-case native-endianness
[(little)
(if (eq? eness 'big)
(big->list v size)
(unrecognized-endianness who eness))]
[(big)
(if (eq? eness 'little)
(little->list v size)
(unrecognized-endianness who eness))]))))
(set-who! bytevector->uint-list
(lambda (v eness size)
(define (big->list v size)
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([n (bytevector-length v)])
(unless (fx= (fxremainder n size) 0) (size-multiple-error who n size))
(let f ([i 0])
(if (fx= i n)
'()
(cons ($bytevector-uint-big-ref v i size)
(f (fx+ i size)))))))
(define (little->list v size)
(unless (bytevector? v) (not-a-bytevector who v))
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([n (bytevector-length v)])
(unless (fx= (fxremainder n size) 0) (size-multiple-error who n size))
(let f ([i 0])
(if (fx= i n)
'()
(cons ($bytevector-uint-little-ref v i size)
(f (fx+ i size)))))))
(if (eq? eness (native-endianness))
(case size
[(1) ($bytevector->u8-list v who)]
[(2) ($bytevector->u16-native-list v who)]
[(4) ($bytevector->u32-native-list v who)]
[(8) ($bytevector->u64-native-list v who)]
[else
(constant-case native-endianness
[(little) (little->list v size)]
[(big) (big->list v size)])])
(constant-case native-endianness
[(little)
(if (eq? eness 'big)
(big->list v size)
(unrecognized-endianness who eness))]
[(big)
(if (eq? eness 'little)
(little->list v size)
(unrecognized-endianness who eness))]))))
)
(let ()
(define-syntax list->bv
(syntax-rules ()
[(_ bytes set! vokay?)
(let ([value-okay? vokay?])
(lambda (ls who)
(let* ([n ($list-length ls who)]
[v (make-bytevector (fx* n bytes))])
(let loop ([ls ls] [i 0])
(unless (null? ls)
(let ([k (car ls)])
(unless (value-okay? k) (invalid-value who k))
(set! v i k))
(let ([ls (cdr ls)])
(unless (null? ls)
(let ([k (car ls)])
(unless (value-okay? k) (invalid-value who k))
(set! v (fx+ i bytes) k))
(loop (cdr ls) (fx+ i (fx* bytes 2)))))))
v)))]))
(define $s8-list->bytevector (list->bv 1 bytevector-s8-set! (signed-value-pred 8)))
(define $u8-list->bytevector (list->bv 1 bytevector-u8-set! (unsigned-value-pred 8)))
(define $s16-native-list->bytevector (list->bv 2 bytevector-s16-native-set! (signed-value-pred 16)))
(define $u16-native-list->bytevector (list->bv 2 bytevector-u16-native-set! (unsigned-value-pred 16)))
(define $s32-native-list->bytevector (list->bv 4 bytevector-s32-native-set! (signed-value-pred 32)))
(define $u32-native-list->bytevector (list->bv 4 bytevector-u32-native-set! (unsigned-value-pred 32)))
(define $s64-native-list->bytevector (list->bv 8 bytevector-s64-native-set! (signed-value-pred 64)))
(define $u64-native-list->bytevector (list->bv 8 bytevector-u64-native-set! (unsigned-value-pred 64)))
(set-who! s8-list->bytevector
(lambda (ls)
($s8-list->bytevector ls who)))
(set-who! u8-list->bytevector
(lambda (ls)
($u8-list->bytevector ls who)))
(set-who! sint-list->bytevector
(lambda (ls eness size)
(define (list->big v size)
(let ([n ($list-length ls who)])
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([v (make-bytevector (fx* n size))])
(let f ([ls ls] [i 0])
(unless (null? ls)
(let ([k (car ls)])
(unless (and (or (fixnum? k) (bignum? k))
(let ([k (ash k (fx- 1 (fx* size 8)))])
(or (fx= k 0) (fx= k -1))))
(invalid-value who k))
($bytevector-int-big-set! v i k size))
(f (cdr ls) (fx+ i size))))
v)))
(define (list->little v size)
(let ([n ($list-length ls who)])
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([v (make-bytevector (fx* n size))])
(let f ([ls ls] [i 0])
(unless (null? ls)
(let ([k (car ls)])
(unless (and (or (fixnum? k) (bignum? k))
(let ([k (ash k (fx- 1 (fx* size 8)))])
(or (fx= k 0) (fx= k -1))))
(invalid-value who k))
($bytevector-int-little-set! v i k size))
(f (cdr ls) (fx+ i size))))
v)))
(if (eq? eness (native-endianness))
(case size
[(1) ($s8-list->bytevector ls who)]
[(2) ($s16-native-list->bytevector ls who)]
[(4) ($s32-native-list->bytevector ls who)]
[(8) ($s64-native-list->bytevector ls who)]
[else
(constant-case native-endianness
[(little) (list->little ls size)]
[(big) (list->big ls size)])])
(constant-case native-endianness
[(little)
(if (eq? eness 'big)
(list->big ls size)
(unrecognized-endianness who eness))]
[(big)
(if (eq? eness 'little)
(list->little ls size)
(unrecognized-endianness who eness))]))))
(set-who! uint-list->bytevector
(lambda (ls eness size)
(define (list->big v size)
(let ([n ($list-length ls who)])
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([v (make-bytevector (fx* n size))])
(let f ([ls ls] [i 0])
(unless (null? ls)
(let ([k (car ls)])
(unless (and (or (fixnum? k) (bignum? k))
(fx= (ash k (fx- (fx* size 8))) 0))
(invalid-value who k))
($bytevector-int-big-set! v i k size))
(f (cdr ls) (fx+ i size))))
v)))
(define (list->little v size)
(let ([n ($list-length ls who)])
(unless (and (fixnum? size) (fx> size 0)) (invalid-size who size))
(let ([v (make-bytevector (fx* n size))])
(let f ([ls ls] [i 0])
(unless (null? ls)
(let ([k (car ls)])
(unless (and (or (fixnum? k) (bignum? k))
(fx= (ash k (fx- (fx* size 8))) 0))
(invalid-value who k))
($bytevector-int-little-set! v i k size))
(f (cdr ls) (fx+ i size))))
v)))
(if (eq? eness (native-endianness))
(case size
[(1) ($u8-list->bytevector ls who)]
[(2) ($u16-native-list->bytevector ls who)]
[(4) ($u32-native-list->bytevector ls who)]
[(8) ($u64-native-list->bytevector ls who)]
[else
(constant-case native-endianness
[(little) (list->little ls size)]
[(big) (list->big ls size)])])
(constant-case native-endianness
[(little)
(if (eq? eness 'big)
(list->big ls size)
(unrecognized-endianness who eness))]
[(big)
(if (eq? eness 'little)
(list->little ls size)
(unrecognized-endianness who eness))]))))
)
(let ()
;; Store uncompressed size as u64, using low bits to indicate compression format:
(define uncompressed-length-length (ftype-sizeof integer-64))
;; Always big-endian, so that compressed data is portable.
(define uncompressed-length-endianness (endianness big))
(define fp-bytevector-compress-size
(foreign-procedure "(cs)bytevector_compress_size" (iptr int) uptr))
(define fp-bytevector-compress
(foreign-procedure "(cs)bytevector_compress" (scheme-object iptr iptr scheme-object iptr iptr int) scheme-object))
(define fp-bytevector-uncompress
(foreign-procedure "(cs)bytevector_uncompress" (scheme-object iptr iptr scheme-object iptr iptr int) scheme-object))
(let ()
(define (compress who bv fmt offset)
(let* ([dest-max-len (fp-bytevector-compress-size (bytevector-length bv) fmt)]
[dest-alloc-len (min (+ dest-max-len offset) (constant maximum-bytevector-length))]
[dest-bv (make-bytevector dest-alloc-len)])
(let ([r (fp-bytevector-compress dest-bv offset (fx- dest-alloc-len offset) bv 0 (bytevector-length bv) fmt)])
(if (string? r)
($oops who r bv)
(bytevector-truncate! dest-bv (fx+ r offset))))))
(set-who! $bytevector-compress
(lambda (bv fmt)
(compress who bv fmt 0)))
(set-who! bytevector-compress
(lambda (bv)
(unless (bytevector? bv) (not-a-bytevector who bv))
(let* ([fmt ($tc-field 'compress-format ($tc))]
[dest-bv (compress who bv fmt uncompressed-length-length)])
(let ([tag (bitwise-ior
(bitwise-arithmetic-shift-left (bytevector-length bv) (constant COMPRESS-FORMAT-BITS))
fmt)])
($bytevector-u64-set! dest-bv 0 tag uncompressed-length-endianness who)
dest-bv)))))
(let ()
(define (uncompress who bv dest-length fmt offset)
(unless (and (fixnum? dest-length) ($fxu< dest-length (constant maximum-bytevector-length)))
($oops who "bytevector ~s claims invalid uncompressed size ~s" bv dest-length))
(let ([dest-bv (make-bytevector dest-length)])
(let ([r (fp-bytevector-uncompress dest-bv 0 dest-length bv offset (fx- (bytevector-length bv) offset) fmt)])
(cond
[(string? r) ($oops who r bv)]
[(fx= r dest-length) dest-bv]
[else ($oops who "uncompressed size ~s for ~s is smaller than expected size ~s" r bv dest-length)]))))
(set-who! $bytevector-uncompress
(lambda (bv dest-length fmt)
(uncompress who bv dest-length fmt 0)))
(set-who! bytevector-uncompress
(lambda (bv)
(unless (bytevector? bv) (not-a-bytevector who bv))
(unless (>= (bytevector-length bv) uncompressed-length-length) ($oops who "invalid data in source bytevector ~s" bv))
(let* ([tag ($bytevector-u64-ref bv 0 uncompressed-length-endianness who)]
[fmt (logand tag (fx- (fxsll 1 (constant COMPRESS-FORMAT-BITS)) 1))]
[dest-length (bitwise-arithmetic-shift-right tag (constant COMPRESS-FORMAT-BITS))])
(uncompress who bv dest-length fmt uncompressed-length-length))))))
)