Google APIs Client Library for C++
|
Interface for reading from an asynchronous binary data stream. More...
#include "client/data/data_reader.h"
Public Member Functions | |
virtual | ~DataReader () |
Standard destructor. | |
virtual bool | seekable () const |
Returns true if the reader is generally seekable. | |
bool | done () const |
Indicates whether unread bytes still remain in the stream or not. | |
bool | error () const |
Determine if we've encountered a hard error or not. | |
bool | ok () const |
Determine if we've encountered a hard error or not. | |
util::Status | status () const |
Returns details for the error on the stream, if any. | |
int64 | offset () const |
Returns the current offset in the byte sequence. | |
int64 | SetOffset (int64 position) |
Set the offset in the byte sequence for the next read. | |
bool | Reset () |
Resets the reader back to the beginning of the byte sequence. | |
int64 | ReadToBuffer (int64 max_bytes, char *storage) |
Keeps reading synchronously until the request is satisfied. | |
int64 | ReadToString (int64 max_bytes, string *append_to) |
Keeps reading synchronously until the request is satisfied. | |
string | RemainderToString () |
Keep reading synchronously until done(). | |
int64 | TotalLengthIfKnown () const |
Returns the total length of the byte sequence if it is known. | |
Protected Member Functions | |
DataReader (Closure *deleter) | |
Standard reader constructor. | |
virtual int64 | DoReadToBuffer (int64 max_bytes, char *storage)=0 |
Implementation hook to read bytes into storage. | |
virtual int64 | DoSetOffset (int64 position) |
Sets the offset into the byte sequence. | |
void | set_status (util::Status status) |
Sets the status as a means to pass error details back to the caller. | |
void | set_done (bool done) |
Indicates whether there is more data to be read. | |
void | set_total_length (int64 length) |
Sets the total number of bytes in the reader. |
Interface for reading from an asynchronous binary data stream.
The DataReader is the base class for reading non-trivial data using a streaming-like interface. It is simpler and potentially more efficient than using standard C++ streams.
The interface primarily consists of 2 methods:
The done() method indicates there is no more data to be read -- until setting the offset back toward (or at) the beginning for the next read. The error() method indicates premature ending. Errors are considered hard-errors. Setting an error implies it is done. error() can be set even if some bytes are read. Soft errors just return fewer bytes than requested, including 0.
Readers can get their data from arbitrary sources, and dont necessarily buffer everything in memory. Therefore you cannot count on being able to read their data over and over again multiple times. Most readers will allow you to but if you have a generic reader then you should not make this assumption.
The reader API supports incremental reading, analogous to reading from a stream or file. When you get data back, the reader advances its offset within the data sequence so that the next read will start reading from another offset; Reading data modifies the reader instance. If you want to get all the data and are not sure where the reader came from, check the offset and reset the reader if it is not at the beginning.
The DataReaer abstraction is used throughout the interfaces within the Google APIs Client Library for C++ where you might otherwise expect to see a string
or even StringPiece. string
and StringPiece are used for efficiency and convienence where small or constant data is expected, or the data is consumed by an external library that uses standard strings. SataReader is used in interfaces where that involve opaque data that can be arbitrarily large or might not naturally reside in memory already.
A DataReader can be used in conjunction with a DataWriter, however this is not necessary. You can use a DataWriter to write bytes then hvee that writer create a reader to read those bytes back. This is useful if you dont know what that byte stream is, such as an HTTP payload you are receiving from a server. However if you already have access to the bytes then it is easier and more efficeint to create a reader directly from those bytes.
It may also be that the writer serves no purpose other than to create a reader, in which case you may as well just create a reader. This is why some objects provide factory methods that return readers rather than define serialization methods that take writers.
DataReaders are not thread-safe.
virtual ~DataReader | ( | ) | [virtual] |
Standard destructor.
DataReader | ( | Closure * | deleter | ) | [explicit, protected] |
Standard reader constructor.
The deleter determines whether the reader will be characterized as begin "managed" or "unmanaged". A NULL reader indicates it is "unmanaged".
Managed readers call a closure when they are destroyed. Often this closure is used to free up resources consumed by the byte sequence the reader is reading from. However the closure may do anything.
[in] | deleter | If non-NULL then the caller retains ownership. Typically this will be a self-managed deleter that self-destructs once run. |
bool done | ( | ) | const [inline] |
virtual int64 DoReadToBuffer | ( | int64 | max_bytes, |
char * | storage | ||
) | [protected, pure virtual] |
Implementation hook to read bytes into storage.
This method is called by the public Read* methods to perform the actual data reading. The base class will do the adminstrative stuff, including updating the offset. However marking done and error status are left to this method.
[in] | max_bytes | Read at most max_bytes into storage. |
[in] | storage | At least max_bytes of allocated storage. |
This method is resopnsible for explicitly marking the reader done() when there is no more data to be returned by future calls. It should set the status if a hard error is encountered.
This method is required of all concrete readers as the sole point of access.
Implemented in CodecReader.
virtual int64 DoSetOffset | ( | int64 | position | ) | [protected, virtual] |
Sets the offset into the byte sequence.
This method is called by the public SetOffset() method. The public method will do the administrative stuff including resetting the offset and updating the status based on the status returned by this method.
This method will return the actual offset that the sequence is at after attempting to set. The intent is that if offset is too big then the reader will seek to the end and return the offset of the end. This isnt an ideal definition but is compatible with being able to seek into readers of unknown size.
In a complete failure the offset will be -1 (invalid) and require a successful SetOffset to restore.
Reimplemented in CodecReader.
bool error | ( | ) | const [inline] |
int64 offset | ( | ) | const [inline] |
Returns the current offset in the byte sequence.
bool ok | ( | ) | const [inline] |
Determine if we've encountered a hard error or not.
This is equivalent to !error().
int64 ReadToBuffer | ( | int64 | max_bytes, |
char * | storage | ||
) |
Keeps reading synchronously until the request is satisfied.
If the stream is done before the requested bytes are read, then this will return a partial read to the point where the stream was done. You will need to check ok() or error() if you want to distinguish the partial read being due to the end of the sequence or a hard error.
Reading will advance the offset by the number of bytes actually read.
[in] | max_bytes | The most bytes to read. |
[in] | storage | The storage to read into must have at least max_bytes of capacity allocated. |
int64 ReadToString | ( | int64 | max_bytes, |
string * | append_to | ||
) |
Keeps reading synchronously until the request is satisfied.
If the stream is done before the requested bytes are read, then this will return a partial read to the point where the stream was done. You will need to check ok() or error() if you want to distinguish the partial read being due to the end of the sequence or a hard error.
Reading will advance the offset by the number of bytes actually read.
[in] | max_bytes | The most bytes to read. |
[in,out] | append_to | The string to append the data into. If you need to look at the raw memory, use string::data() rather than string::c_str() since the byte sequence you've read from may contain binary data. |
string RemainderToString | ( | ) | [inline] |
Keep reading synchronously until done().
You should check either done() or error() to determine whether you are done() because of a hard error or because you read all remaining bytes.
bool Reset | ( | ) | [inline] |
virtual bool seekable | ( | ) | const [virtual] |
Returns true if the reader is generally seekable.
This does not guarantee that SetOffset will always work, but indicates whether it is expected to in general. As a rule of thumb this would be true if the backing store is reliable and false if it is transient.
This value is meant as a hint for consumers and not as a constraint to attempting to SetOffset.
void set_done | ( | bool | done | ) | [inline, protected] |
Indicates whether there is more data to be read.
[in] | done | true if there si no more data, false if there is. |
void set_status | ( | util::Status | status | ) | [protected] |
Sets the status as a means to pass error details back to the caller.
Setting an error implies setting done as well. However clearing an error by setting an ok status will not clear done. To clear the done state you must explicitly call set_done.
[in] | status | An error implies a hard failure and will mark the reader done. |
void set_total_length | ( | int64 | length | ) | [protected] |
Sets the total number of bytes in the reader.
If calling this method, you should call it from within your constructor if possible.
[in] | length | The number of bytes is returned by TotalLengthIfKnown. -1 indicates unknown. 0 Indicates none. The default is -1 (unknown). |
int64 SetOffset | ( | int64 | position | ) |
Set the offset in the byte sequence for the next read.
[in] | position | The new offset. 0 is the beginning. There is no means to specify the end other than by absolute position. |
util::Status status | ( | ) | const [inline] |
Returns details for the error on the stream, if any.
int64 TotalLengthIfKnown | ( | ) | const [inline] |
Returns the total length of the byte sequence if it is known.