This is a proposal for a bytevector API whose procedures allow a bytevector to be viewed as one of several kinds of numeric vectors. It differs from related designs such as SRFI 63, SRFI 66, and R6RS in that each procedure listed below actually represents many procedures, one for each defined representation type. This makes for a lot of procedures, but many of them can be easily inlined by even a very dumb compiler, providing high efficiency. The procedures provided in the present proposal are the analogues of the R7RS-small vector API with a few additions.
A [type] consists of a [principal type] followed by an [endianism].
The [principal type] values are:
The [endianism] values are:
Endianism is not applicable to the u8 and s8 types. Thus there are 3 * 12 - 4, or 32, representation types altogether.
The s and u types correspond to limited ranges of exact integers, the f types to limited ranges of inexact real numbers, and the c types to limited ranges of inexact complex numbers.
The number of bytes occupied by a representation type is the number of bits expressed in its name divided by 8. This value is designated by b in the descriptions of procedures.
(make-[type]-bytevector k [ fill ])
Returns a newly allocated bytevector of length k * b.Fill is converted to a binary value according to `[type] and used to fill the bytevector; if fill is not specified, the values of the elements are unspecified. It is an error if fill cannot be converted to [type].
([type]-bytevector v ... )
Returns a newly allocated bytevector of length k * b, where k is the number of arguments to the procedure. It is filled with the binary values resulting from encoding the v arguments according to [type]. It is an error if an argument cannot be converted to [type].
([type]-bytevector-ref bytevector k)
Returns a Scheme number corresponding to the binary value encoded according to [type] beginning at offset k * b in bytevector. This procedure treats bytevector as a uniformly typed vector.
(bytevector-[type]-ref bytevector k)
Returns a Scheme number corresponding to the binary value encoded according to [type] beginning at offset k in bytevector. This procedure treats bytevector as potentially containing more than one type.
Note that bytevector-u8-ref is defined in the small language.
([type]-bytevector-set! bytevector k v)
Converts v to a binary value encoded according to [type] and places it into bytevector beginning at offset k * b. This procedure treats bytevector as a uniformly typed vector. It is an error if v cannot be converted to [type].
(bytevector-[type]-set! bytevector k v)
Converts v to a binary value encoded according to [type] and places it into bytevector beginning at offset k. This procedure treats bytevector as potentially containing more than one type. It is an error if v cannot be converted to [type].
Note that bytevector-u8-set! is defined in the small language.
It is an error if a value being used to fill an element of a [type]vector cannot be converted to [type], or if start (inclusive), end (inclusive), or at are out of range, or if an existing bytevector is being overflowed.
(vector->[type]-bytevector vector [start [ end ] ])
Returns a newly allocated bytevector of length end * b - start * b, filled with the corresponding elements of vector.
(list->[type]-bytevector list)
Returns a newly allocated bytevector whose length is the length of list times b, filled with the elements of list.
(vector->[type]-bytevector! bytevector at vector [start [ end ] ])
Writes the elements of vector from start to end into bytevector starting at at * b.
(list->[type]-bytevector! list bytevector at)
Writes the elements of list into bytevector starting at at * b.
It is an error if start (inclusive), end (inclusive), or at are out of range, or if an existing vector is being overflowed.
([type]-bytevector->vector bytevector [ start [ end ] ])
([type]-bytevector->list bytevector [ start [ end ] ])
Returns a newly allocated vector or list of length end - start with the elements of bytevector from start * b to end * b.
([type]-bytevector->vector! vector at bytevector [start [ end ] ])
Writes the elements of bytevector from start * b to end * b into vector starting at at.
([type]-bytevector-length bytevector)
Returns the length of bytevector / b, rounded toward zero.
([type]-bytevector-fill! bytevector fill [ [ start ] end ] )
Stores fill in the elements of bytevector viewed as a [type]vector from start * b to end * b. An error is signaled if fill cannot be converted to [type].
([type]-bytevector-map proc bytevector ...)
Returns a newly allocated bytevector which contains the results of applying proc to the elements of the bytevectors, considered as typed vectors, in an unspecified order.
([type]-bytevector-map! proc output-bytevector bytevector ...)
Writes the results of applying proc to the elements of the bytevectors, considered as typed vectors, into the corresponding elements of output-bytevector in an unspecified order. It is not an error for output-bytevector to be the same as one of the bytevectors. Returns an unspecified value.
([type]-bytevector-for-each proc bytevector ...)
Applies proc to the elements of the bytevectors, considered as typed vectors, in order from first to last and discards the results. Returns an unspecified value.
These are trivial variants of read-bytevector, read-bytevector!, and write-bytevector provided for uniformity.
(read-bytevector-[type] k [ port ])
Read k * b bytes from port into a newly allocated [type]vector and returns it.
(read-bytevector-[type]! bytevector [ port [ start [ end ] ] ])
Read end * b - start * b bytes from port into [type]vector starting at start. Returns the number of bytes read divided by b, or an eof object if no bytes are available. If the number of bytes available is not a multiple of b, the value of the element of [type]vector for which b bytes are not available is unspecified.
(write-bytevector-[type] bytevector [ port [ start [ end'' ] ] ])
Write end * b - start * b bytes to port from [type]vector starting at start. Returns an unspecified value.
See the procedures of SRFI 43 and VectorsCowan, with the exceptions of the ones defined here.
For mapping C structs onto bytevectors, see StructuresCowan or ByteStructuresTaylanub.
Since there are a great many procedures, it makes sense to factor this into separate libraries. Most programs won't require all the representation types, so factoring horizontally into 38 libraries based on that is a simple approach. If the result is still too large, then we can factor vertically based on expected uses for the function.
This syntax-rules macro by Ian Price will be helpful in implementing lots of similar but not identical procedures for the 32 types.