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. For a version of this page that may be more recent, see BytevectorsCowan in WG2's repo for R7RS-large.

Bytevectors­Cowan

cowan
2015-09-07 07:22:55
8history
source

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.

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 SRFI 43 and VectorsCowan, with the exceptions of the ones defined here.

Structured representation types

For mapping C structs onto bytevectors, see StructuresCowan or 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

This syntax-rules macro by Ian Price will be helpful in implementing lots of similar but not identical procedures for the 32 types.