Google APIs Client Library for C++
DataReader Class Reference

Interface for reading from an asynchronous binary data stream. More...

#include "client/data/data_reader.h"

+ Inheritance diagram for DataReader:

List of all members.

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.

Detailed Description

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:

  • Read data from the reader in whole or part.
  • Set the offset into the byte sequence for the next read.

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.

See also:
DataWriter
NewManagedInMemoryDataReader
NewManageFileDataReader
NewManageCompositeiDataReader

Constructor & Destructor Documentation

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.

Warning:
The reader instance will not be valid when teh deleter is called
Parameters:
[in]deleterIf non-NULL then the caller retains ownership. Typically this will be a self-managed deleter that self-destructs once run.
See also:
NewCallback

Member Function Documentation

bool done ( ) const [inline]

Indicates whether unread bytes still remain in the stream or not.

Returns:
true if there will never be more bytes to be read ahead of the current offset. To distinguish between a successful read and an error, you must check either error() or ok() since hard errors imply done() as well.
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.

Parameters:
[in]max_bytesRead at most max_bytes into storage.
[in]storageAt least max_bytes of allocated storage.
Returns:
Number of bytes actually written into storage. 0 has no special meaning beyond no byets were written for whatever reason. 0 does not indicate any kind of failure. This method should never return a negative number.

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.

See also:
set_done
set_etatus

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.

Returns:
the offset that was seeked to or -1 on complete failure. The seek should not exceed the length of the bytestream.

Reimplemented in CodecReader.

bool error ( ) const [inline]

Determine if we've encountered a hard error or not.

Hard errors are sticky and can only be cleared with Reset(), if at all. This is equivalent to !ok().

Returns:
true if a hard error was set, false otherwise.
See also:
ok
Status
int64 offset ( ) const [inline]

Returns the current offset in the byte sequence.

Returns:
The number of bytes read so far. 0 is the beginning.
bool ok ( ) const [inline]

Determine if we've encountered a hard error or not.

This is equivalent to !error().

Returns:
true if no hard error has been set, false if an error.
See also:
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.

Parameters:
[in]max_bytesThe most bytes to read.
[in]storageThe storage to read into must have at least max_bytes of capacity allocated.
Returns:
the number of bytes actually read might be 0 and the reader may still not be done(). Negative values are never returned.
See also:
ReadToString
RemainderToString
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.

Parameters:
[in]max_bytesThe most bytes to read.
[in,out]append_toThe 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.
Returns:
the number of bytes actually read might be 0 and the reader may still not be done(). Negative values are never returned.
See also:
ReadToBuffer
RemainderToString
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.

Returns:
the remaining string from the offset.
See also:
ReadToBuffer
ReadToString
bool Reset ( ) [inline]

Resets the reader back to the beginning of the byte sequence.

If the reset succeeds, the offset will be 0. If the reset fails then the reader will be in an error() state preventing any future reads.

Returns:
false on failure. See status() for details.
See also:
SetOffset
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.

Returns:
The base class assumes false to be conservative.
void set_done ( bool  done) [inline, protected]

Indicates whether there is more data to be read.

Parameters:
[in]donetrue 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.

Parameters:
[in]statusAn 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.

Parameters:
[in]lengthThe 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.

Parameters:
[in]positionThe new offset. 0 is the beginning. There is no means to specify the end other than by absolute position.
Returns:
offset that was set. -1 indicates complete failure. if the result was < offset then the reader will be positioned at the end of the sequence.
util::Status status ( ) const [inline]

Returns details for the error on the stream, if any.

Returns:
a successful status if the stream is ok, otherwise the error encounteredd.
int64 TotalLengthIfKnown ( ) const [inline]

Returns the total length of the byte sequence if it is known.

Returns:
-1 if the length is not known. Otherwise the total length from the beginning regardless of the current offset.

The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines