Roman Klochkov <kalimehtar@mail.ru>
The binary-class combines binary-class/base, binary-class/common and binary-class/string.
This package is based upon idea in Practical Common Lisp.
Binary formats usually are represented as a sequence of fields. So the module allows to define classes with their binary types.
ID3/file identifier"ID3"
ID3 version02γγ« 00
ID3 flags%xx000000
ID3 size4 * %0xxxxxxx
((file-identifier(iso-8859-1-bytes3))(sizeid3-tag-size)(frames(id3-framessize))))
Here iso-8859-1-bytes should be a function of one argument, that returns structure binary . u1 , id3-tag-size are simply such structures.
struct
#:extra-constructor-namemake-binary)
Note, that you may use values of previous fields to calculate the type of the next. In the example the value of field size is used to set the type of field frames.
Another common case is "tagged structures". In that case there is a tag in the beginning of data. The structure of the rest of the data depends upon the value of the tag.
((id(iso-8859-1-bytes3))#:dispatch(find-frame-classid))
Function find-frame-class should return the binary class for given id.
((identifier(iso-8859-1-bytes3))(sizeid3-tag-size))#:dispatch((2)id3v2.2-tag)((3)id3v2.3-tag)))
((frames(id3-framessizeid3v2.2-frame))))
If you use #:dispatch, result class should be either inherited from current class, or at least to have all fields that the current class has. Super class of a binary class may be also not binary class, but then it should have no methods read and write.
syntax
((fieldfield-exprarg...)...)[#:dispatchdispatch-expr]class-body...)field = _| id| (id...)
field may be _. This means, that the field is omitted. In this case no field is created in class, but the data is read and is written from/to the binary port. Value for writing is #f.
field may be list of id’s. In this case binary, returned from field-expr should return the same number of values.
superclass-expr may be either id of a binary class, or any expression, returning non-binary class. If you return binary class from expression, then it is not error, but fields of given class will not be visible inside the current class field-exprs.
If field-expr returns class, implementing binary<%> , then provided arg’s will be used as init arguments to make-object , otherwise they ignored.
If field-expr returns not binary<%> neither binary , then the returned value assigned to field as is.
Binary class implements interface binary<%> :
interface
binary<%> :interface?
in:input-port?Reads the object from in and returns it.out:output-port?Writes the object to out
To make the usage of the module easier there are some shortcuts for reading and writing binary values.
procedure
( read-value typeininit-v...)→any
type:any/cin:input-port?init-v:any/c
procedure
( write-value typeoutvalue)→void?
type:any/cout:output-port?value:any/c
(symbolic-binary (+ 23)(big5)(little4)) will return 'big.
It is written by ceving.
Most common data in binary file is integer numbers in little-endian or big-endian order, or bytestrings. So you may use them from this module.
procedure
( integer-be bytes[bits-per-byte])→binary?
bytes:exact-positive-integer?
procedure
( integer-le bytes[bits-per-byte])→binary?
bytes:exact-positive-integer?
procedure
( signed base-typebytes[bits-per-byte])→binary?
bytes:exact-positive-integer?
value
u1 :binary?
value
u2 :binary?
value
u3 :binary?
value
u4 :binary?
value
l1 :binary?
value
l2 :binary?
value
l3 :binary?
value
l4 :binary?
procedure
( bytestring bytes)→binary?
bytes:exact-positive-integer?
procedure
( discard bytes)→binary?
bytes:exact-positive-integer?
value
current-position :binary?
procedure
( move-position position)→binary?
position:exact-nonnegative-integer?
procedure
( ref positiontypeinit-v...)→binary?
position:exact-nonnegative-integer?type:binary?init-v:any/c
In this module there are several binary types for reading and writing string? .
procedure
( generic-string lengthcharacter-type)→binary?
length:exact-positive-integer?character-type:binary?
procedure
( iso-8859-1-string length)→binary?
length:exact-positive-integer?
procedure
( ucs-2-string length)→binary?
length:exact-positive-integer?
value
iso-8859-1-char :binary?
By default contracts in binary-class/* check only function arguments. If you need more security or more performance, you may use instead their submodules: Submodule safe gives maximum safety and contract checks, submodule unsafe gives maximum performance, but no check at all.
This module introduces useful contracts for use with binary classes.
value-contract:contract?
method-spec = method-id| (method-idmethod-contract-expr)field-spec = field-id| (field-idcontract-expr)absent-spec = method-id
bytes:exact-integer?
bytes:exact-integer?
len:real?
len:real?
terminator:char?
terminator:char?
terminator:char?