OpenGATE Contents | GATE development concepts: Streams
Problem description
Unfortunately, the greatest feature of unix is not present in every
C library and also not in the C standard: streams.
C defines FILE
structures, POSIX uses generic int
descriptors and
Windows offers its HANDLE
infrastructure when data is transferred.
And each algorithm and encoding library provides its own API to read and write into their native buffers.
Solution
All generic data driven technologies shall provide one binary interface to read and write data byte blocks, named streams.
A stream interface object shall provide a read()
method to fill an
own buffer with data from the stream implementation, and it shall
provide a write()
method to append data to and internal buffer
implementation.
Also encoders and decoders for different formats shall be covered by a stream interface. And building chains of stream objects will offer a new way of data management
Definition
A gate_stream_t
stream interface inherits from gate_object_t
to support
reference-counting for its lifetime and type-identification. It extends the
object interface with at least 4 methods:
read(char* buffer, gate_size_t buffer_capacity, gate_size_t* ptr_bytes_received)
- Extracts internal data bytes and fills a provided buffer with them.
- In case of an error, a specific NON-OK result code is returned and the stream cannot be used for further operations. It should be closed afterwards.
- A successful
read
operation returns how many bytes could be extracted. This value is always equal or less than the provided buffer capacity. - There is no guarantee how many bytes of the provided buffer can be filled and the stream implemenation shall not make assumptions about specific buffer sizes.
- A
read
invocation must at least extract one byte of data and block until that byte is available. - If no further bytes are available in the stream (and the end of the
stream is reached),
read
returns status OK with zero bytes of buffer usage. - The method shall be designed to be called in a loop to extract all required data until the end of the stream is reached.
write(char const* buffer, gate_size_t buffer_size, gate_size_t* ptr_bytes_written)
- Appends data from the provided buffer to the stream at its current internal position.
- In case of an error, a specific NON-OK result code is returned and the stream cannot be used for further opreations. It should be closed afterwards.
- A successful
write
operation returns how many bytes could be written. The value is between one and the provided buffer_size. - There is no guarantee how many bytes can be written by one invocation and the implementation shall not make assumptions about specific buffer sizes.
- The method shall be designed to be called in a loop to append all required data block by block.
If a stream does only support one of both transfer modes, it should return
GATE_RESULT_NOTSUPPORTED
from the other non-supported method. Input-only
stream will only provide read()
, while output-only stream will only
respond to write()
.
Following auxiliary stream methods are defined too, but may also be implemented
with GATE_RESULT_NOTSUPPORTED
result code:
peek(char* buffer, gate_size_t buffer_capacity, gate_size_t* ptr_bytes_received)
- It is an alternative
read
method that extracts data from a stream but does not remove the extracted data from the streams internal buffer. - Invocation of
peek
in a loop will always return the same bytes.
- It is an alternative
flush()
- Can force the internal stream’s implementation to commit previous
write
operations to the underlaying medium. - It gives a hint that a data transaction sequence has finished and can be marked as completed.
- Can force the internal stream’s implementation to commit previous