This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home.
Source for wiki BytevectorsCowan version 8
author
cowan
comment
ipnr
127.11.51.1
name
BytevectorsCowan
readonly
0
text
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 [http://srfi.schemers.org/srfi-63/srfi-63.html SRFI 63], [http://srfi.schemers.org/srfi-66/srfi-66.html SRFI 66], and [http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-3.html 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.
== Representation types ==
A [type] consists of a [principal type] followed by an [endianism].
The [principal type] values are:
`u8`::
unsigned 8-bit integer
`s8`::
signed 8-bit integer
`u16`::
unsigned 16-bit integer
`s16`::
signed 16-bit integer
`u32`::
unsigned 32-bit integer
`s32`::
signed 32-bit integer
`u64`::
unsigned 64-bit integer
`s64`::
signed 64-bit integer
`f32`::
32-bit float
`f64`::
64-bit float
`c64`::
64-bit complex number (two 32-bit floats, real followed by imaginary)
`c128`::
128-bit complex number (two 64-bit floats, real followed by imaginary)
The [endianism] values are:
(empty)::
Native representations (system-dependent)
`le`::
Little-endian (for float and complex, IEEE format)
`be`::
Big-endian (for float and complex, IEEE format)
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.
== Constructors ==
`(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].
== Selectors ==
`([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.
== Mutators ==
`([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.
== Conversions to bytevectors ==
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''.
== Conversions from bytevectors ==
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''.
== The whole bytevector ==
`([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].
== Mapping ==
`([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.
== Input and output ==
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.
=== Extended bytevector API ===
See the procedures of [http://srfi.schemers.org/srfi-43/srfi-43.html SRFI 43] and VectorsCowan, with the exceptions of the ones defined here.
== Structured representation types ==
For mapping C structs onto bytevectors, see StructuresCowan or [https://github.com/TaylanUB/scheme-bytestructures ByteStructuresTaylanub].
== Packaging ==
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.
== Implementation ==
[https://gist.github.com/ijp/1e0e67ff93c486f66fc8 This syntax-rules macro by Ian Price] will be helpful in implementing lots of similar but not identical procedures for the 32 types.
time
2015-09-07 07:22:55
version
8