Quirrel4.41.0

iostream

Binary streams and blobs.

from "iostream" import ...

Streams and the cursor

A stream is a cursor over a run of bytes. readn and writen act at the cursor and move it forward by as many bytes as they touched, tell reports where it is, and seek puts it somewhere else. Nothing here reads or writes at an address; every operation is relative to where the cursor is.

Two things are streams, and they share the same method set, listed on the stream page: a blob, whose bytes are in memory, and a file from the io module. Code written against the stream methods works with either, which is the usual reason to parse a downloaded buffer and a file on disk with the same function.

What a blob is

A blob is a resizable block of memory with a cursor on it. blob(n) gives n zero bytes with the cursor at the start; blob(0) is empty.

Length and cursor are independent, and mixing them up is the common bug:

Indexing bytes directly

A blob is also indexable, which the stream methods are not. b[i] reads the byte at position i as an integer from 0 to 255, and b[i] = v writes one. Neither moves the cursor, so byte access and stream access can be mixed freely.

let b = blob(3)
b[0] = 72; b[1] = 105; b[2] = 33
b.as_string()   // "Hi!", and the cursor is still at 0

foreach over a blob yields the position and the byte, in order.

There are two edge cases. An index outside the blob throws Error in '_get' metamethod: index out of range, since indexing is implemented as a metamethod. A value outside 0 to 255 does not throw: only the low byte is stored, so b[0] = 300 stores 44. Mask or range-check the value yourself when it comes from arithmetic.

Text and bytes

as_string is the conversion to text: it returns the bytes as a string. tostring is the ordinary object printer and gives an address, so it does not show the contents in a log.

Functions

castf2ipure fastcall castf2i(f: number): intReinterprets the bits of a float as an integer
casti2fpure fastcall casti2f(i: int): floatReinterprets the bits of an integer as a float
swap2pure fastcall swap2(val: number): intByte-swaps a 16-bit value
swap4pure fastcall swap4(val: number): intByte-swaps a 32-bit value
swapfloatpure fastcall swapfloat(val: number): floatByte-swaps the bits of a float

blob class

A resizable block of memory read and written as a stream.

Functions

as_stringinstance.as_string(): stringReturns the blob contents as a string
constructorconstructor([size: int]): instanceCreates a blob of the given size (default 0)
eosinstance.eos(): int|nullReturns non-null if the stream is at end-of-stream
flushinstance.flush(): int|nullFlushes the stream and returns non-null on success
leninstance.len(): intReturns the stream length
readblobinstance.readblob(size: int): instanceReads up to size bytes and returns them as a blob
readninstance.readn(format: int): numberReads a value of the given numeric format and returns it
readobjectinstance.readobject([classes: table|null]): anyDeserializes an object from the stream
resizeinstance.resize(size: int)Resizes the blob to the given size
seekinstance.seek(offset: int, [origin: int]): intSeeks to the given offset; origin is 'b' (begin), 'c' (current) or 'e' (end)
swap2instance.swap2()Byte-swaps the blob contents as an array of 16-bit values
swap4instance.swap4()Byte-swaps the blob contents as an array of 32-bit values
tellinstance.tell(): intReturns the current stream position
tostringinstance.tostring(): stringAllows calling .tostring() on blob instances (bypassing _get)
writeblobinstance.writeblob(blob: instance): intWrites the given blob and returns the number of bytes written
writeninstance.writen(value: number, format: int)Writes a numeric value in the given format
writeobjectinstance.writeobject(obj, [classes: table|null])Serializes the object to the stream
writestringinstance.writestring(str: string): intWrites the string and returns the number of characters written

stream class

The stream methods shared by blob and file.

Functions

eosinstance.eos(): int|nullReturns non-null if the stream is at end-of-stream
flushinstance.flush(): int|nullFlushes the stream and returns non-null on success
leninstance.len(): intReturns the stream length
readblobinstance.readblob(size: int): instanceReads up to size bytes and returns them as a blob
readninstance.readn(format: int): numberReads a value of the given numeric format and returns it
readobjectinstance.readobject([classes: table|null]): anyDeserializes an object from the stream
seekinstance.seek(offset: int, [origin: int]): intSeeks to the given offset; origin is 'b' (begin), 'c' (current) or 'e' (end)
tellinstance.tell(): intReturns the current stream position
writeblobinstance.writeblob(blob: instance): intWrites the given blob and returns the number of bytes written
writeninstance.writen(value: number, format: int)Writes a numeric value in the given format
writeobjectinstance.writeobject(obj, [classes: table|null])Serializes the object to the stream
writestringinstance.writestring(str: string): intWrites the string and returns the number of characters written