@head
@module pack
@title pack: Binary encoding and decoding
This module provides low-level facilities for converting Alore objects to
and from packed binary representations (this is called packing and
unpacking, respectively). The packed representations are
narrow strings that can written to files, sockets and other narrow
streams. Strings containing character codes larger than 255 (wide strings) must
be encoded before passing them to the
packing methods (using the @ref{encodings} module, for example).
This module is typically used for accessing and generating binary data
using standard binary formats, for implementing binary network
protocols and interoperating with lower-level languages such as C.
Pack formats
Binary data can be packed in several different formats. Some formats can
only pack integer data, others floating point numbers, and finally there
is a format for string data. There are no separate formats for different
endiannesses — instead there are separate classes for packing and
unpacking big endian and little endian data.
The table below contains descriptions of the supported formats, including
sizes of the packed representations and the corresponding Alore types that
can be packed into and unpacked from using each format (note that N in a format
name must be replaced by a valid integer):
Notes:
1
| The Byte format is thus named for convenience; for consistency's
sake it could equivalently have been named Word8.
|
2
| Signed
integer formats (Int8 to Int64) are encoded using the
standard 2's complement encoding.
|
3
| The Float32 and Float64 formats correspond to single
and double precision IEEE floating point numbers, respectively.
|
4
| The width of a Str format is always specified with an additional
integer argument specifying the length of the packed string in bytes.
When packing, input strings may be smaller than the length; they will be
padded with spaces so that the desired length is reached.
|
Packer classes
There are two concrete packer classes, one for the big-endian (network)
byte order and other for the little-endian byte order. They both support the
same methods; the common abstract superclass PackerBase defines these.
Class Packer
@inherits PackerBase
@supertypes
@class Packer()
@desc Construct a packer that packs and unpacks data in the big-endian
(network) byte order.
@end
Class LittleEndianPacker
@inherits PackerBase
@supertypes
@class LittleEndianPacker()
@desc Construct a packer that packs and unpacks data in the little-endian byte
order.
@end
@class-hidden PackerBase
Class PackerBase
This is an abstract base class of the packer classes.
Methods
@note Instances of N in method names below must be replaced with an integer
valid
for the format. See the above table for details. For example, the actual
methods for packing words are packWord16, packWord32 and
packWord64.
@end
@fun packByte(int as Int) as Str
@fun packWordN(int as Int) as Str
@fun packIntN(int as Int) as Str
@fun packFloatN(float as Float) as Str
@fun packStr(str as Str, len as Int) as Str
@desc Pack a value in a specific format. The argument must have a compatible
Alore type for the format (integers are also valid when floats are
expected). The result is a narrow string.
@end
@fun packBytes(array as Array) as Str
@fun packWordsN(array as Array) as Str
@fun packIntsN(array as Array) as Str
@fun packFloatsN(array as Array) as Str
@fun packStrs(array as Array, len as Int) as Str
@desc Pack an array of values in a specific format. The argument must be an
array, and each array item must have a compatible Alore type for the
format. The result is a narrow string that is the concatenation of the
packed items.
@end
@fun unpackByte(str as Str) as Int
@fun unpackWordN(str as Str) as Int
@fun unpackIntN(str as Str) as Int
@fun unpackFloatN(str as Str) as Float
@fun unpackStr(str as Str) as Str
@desc Unpack a narrow string encoded in the format specified by the method
name. The
argument must have the correct length for the format. The Alore type of
the result value is specified by the format.
@end
@fun unpackBytes(str as Str) as Array
@fun unpackWordsN(str as Str) as Array
@fun unpackIntsN(str as Str) as Array
@fun unpackFloatsN(str as Str) as Array
@fun unpackStrs(str as Str, len as Int) as Array
@desc Unpack a narrow string that contains any number of values encoded in the
format specified by the method name. The argument must have a valid
length for the format (any multiple of the single item length). The
result is an array of values whose type is specified by the format.
@end
Examples
@example
var p = Packer()
p.packWord16(7) -- Result: "\u0000\u0007"
p.packBytes([16, 128]) -- Result: "\u0010\u0080"
p.unpackBytes("\u0010\u0080") -- Result: [16, 128]
var pl = LittleEndianPacker()
pl.packWord16(7) -- Result: "\u0007\u0000"
@end
Class PackStream
@inherits Stream
@supertypes
@class PackStream(stream as Stream[, packer as PackerBase][, bufMode as Constant])
@desc Construct a PackStream instance that uses another stream for
input/output. The packer argument,
if present, must be a packer object. If omitted, the big endian packer
will be used. The bufMode argument may be @ref{Buffered},
@ref{LineBuffered} or @ref{Unbuffered}. If omitted, full buffering will
be used.
@end
PackStream methods
@note Instances of N in method names below must be replaced with an integer
valid
for the format. See the above table for details. For example, the actual
methods for writing words are writeWord16, writeWord32
and writeWord64.
@end
@fun writeByte(int as Int)
@fun writeWordN(int as Int)
@fun writeIntN(int as Int)
@fun writeFloatN(float as Float)
@fun writeStr(str as Str, int as Int)
@desc Pack data and write to the stream. The arguments are similar to the
corresponding pack* methods (see above).
@end
@fun writeBytes(array as Array)
@fun writeWordsN(array as Array)
@fun writeIntsN(array as Array)
@fun writeFloatsN(array as Array)
@fun writeStrs(array as Array, int as Str)
@desc Pack an array and write to the stream. The arguments are similar to the
corresponding pack* methods (see above).
@end
@fun readByte() as Int
@fun readWordN() as Int
@fun readIntN() as Int
@fun readFloatN() as Int
@desc Read and unpack data from the stream. The format specifies the number of
characters (bytes) to read and the type of the return value.
@end
@fun readBytes(n as Int) as Array
@fun readWordsN(n as Int) as Array
@fun readIntsN(n as Int) as Array
@fun readFloatsN(n as Int) as Array
@fun readStrs(n as Int, len as Int) as Array
@desc Read and unpack multiple data items from the stream. The format and the
length argument
specify the number of characters (bytes) to read and the length of the
@ref{Array} return value and the type of its items.
@end
@fun eof() as Boolean
@fun seek(n as Int)
@fun close()
@desc Call the corresponding method of the underlying stream (if it is
supported).
@end
The inherited writing and reading methods (write,
readLn, etc.) behave normally and can be used in addition to the
PackStream specific input/output methods.
Class PackFile
@inherits PackStream
@supertypes
@class PackFile(path as Str[, packer as PackerBase], ... as Constant)
@desc Open a binary file for reading and/or writing. The supported additional
arguments are the same as for @ref{io::File}. The packer
argument, if present, must be a packer object (see above). If omitted,
the big endian packer will be used.
Example:
@example
var f = PackFile("file.bin", Output)
f.writeWord32(1234)
f.writeBytes([1, 2, 3, 4])
f.close()
@end
@end
@end-class
Constants
@var HostByteOrderPacker as def () as PackerBase
@desc This constant refers to either @ref{Packer} or @ref{LittleEndianPacker}
depending on the native byte order of the host system.
@end
Exceptions
@class PackError
@desc Raised when a packer class gets invalid input and cannot perform
packing or unpacking. Inherits from @ref{std::ValueError}.
@end