#include <CRingBlockReader> class CRingBlockReader { public: typedef struct _DataDescriptor { std::uint32_t s_nBytes; std::uint32_t s_nItems; void* s_pData; } DataDescriptor, *pDataDescriptor; public: CRingBlockReader(); virtual DataDescriptor read(size_t nBytes); protected: virtual ssize_t readBlock(void* pBuffer, size_t maxBytes) = 0; };
This is an abstract base class that uses a strategy pattern to read large blocks of data from some source and pass back to the user a description of the items in the block. The items are only assumed to begin with a uint32_t size in bytes.
Actual data transfer is done via the protected, pure virtual,
method readBlock
. The base class
properly handles items which span block boundaries transparently
with respect concrete derive classes.
Full customizability of the internals is also provided
by making the public read
method
virtual as well.
CRingBlockReader();
Constructs the object.
virtual DataDescriptor read(size_t nBytes);
Obtains at most nBytes
of
data from the source. The return value is a
CRingBlockReader
::DataDescriptor
.
See DataTypes.
It is important to know that the
s_pData
field of the
returned structure points to data allocated dynamically
via malloc
(3). When the
caller is done using it that data must be released
via free
(3).
It is an error if nBytes
cannot accommodate at least one complete item. In that
case an std::logic_error
is thrown.
protected virtual =0 ssize_t readBlock(void* pBuffer, size_t maxBytes);
Concrete sub-classes must implement this method.
The method must obtain at most
maxBytes
from the data source
storing them in pBuffer
.
The actual number of bytes returned is
the return value.
A return value of 0 represents an end to the data source.
A return value less than zero indicates an error
whose reason is in the errno
variable. The caller will transform errors like this
into throw std::system_error
exceptions.
The class defines a nested struct:
CRingBlockReader
::DataDescriptor
and an associated pointer type
CRingBlockReader
::pDataDescriptor
which is a pointer to that struct. The struct has the following
fields:
s_nBytes
<Number of bytes in this chunk of data. This may be less than the number of bytes requested of the read but it will never be more than that.
s_nItems
The number of items in the block read. Each item is assumed to have a leading std::uint32_t that contains the size of the item in bytes. Note that this is also how NSCLDAQ ring items are formatted.
s_pData
Pointer to the data. The data pointed to is
allocated dynamically by malloc
(3)
and must be deallocated by the client code when
appropriate via free
(3).