On this page:

The InputStream API in C++

An InputStream that uses the Ice encoding can be created using the following functions:

{zcode:cpp}
namespace Ice {
    InputStreamPtr createInputStream(
        const CommunicatorPtr& communicator,
        const std::vector<Ice::Byte>& data);
 
    InputStreamPtr createInputStream(
        const CommunicatorPtr& communicator,
        const std::vector<Ice::Byte>& data,
        const EncodingVersion& version);

    InputStreamPtr createInputStream(
        const CommunicatorPtr& communicator,
        const std::pair<const Ice::Byte*, const Ice::Byte*>& data);

    InputStreamPtr createInputStream(
        const CommunicatorPtr& communicator,
        const std::pair<const Ice::Byte*, const Ice::Byte*>& data,
        const EncodingVersion& version);
 
    InputStreamPtr wrapInputStream(
        const CommunicatorPtr& communicator,
        const std::vector<Ice::Byte>& data);
 
    InputStreamPtr wrapInputStream(
        const CommunicatorPtr& communicator,
        const std::vector<Ice::Byte>& data,
        const EncodingVersion& version);

    InputStreamPtr wrapInputStream(
        const CommunicatorPtr& communicator,
        const std::pair<const Ice::Byte*, const Ice::Byte*>& data);

    InputStreamPtr wrapInputStream(
        const CommunicatorPtr& communicator,
        const std::pair<const Ice::Byte*, const Ice::Byte*>& data,
        const EncodingVersion& version);
}
{zcode}

You can optionally specify an encoding version for the stream, otherwise the stream uses the communicator's default encoding version.

Note that the createInputStream functions make a copy of the supplied data, whereas the wrapInputStream functions avoid copies by keeping a reference to the data. If you use wrapInputStream, it is your responsibility to ensure that the memory buffer remains valid and unmodified for the lifetime of the InputStream object.

The InputStream class is shown below.

{zcode:cpp}
namespace Ice {
    class InputStream : ... {
    public:
        virtual CommunicatorPtr communicator() const = 0;

        virtual void sliceObjects(bool slice) = 0;

        virtual void read(bool& v) = 0;
        virtual void read(Byte& v) = 0;
        virtual void read(Short& v) = 0;
        virtual void read(Int& v) = 0;
        virtual void read(Long& v) = 0;
        virtual void read(Float& v) = 0;
        virtual void read(Double& v) = 0;
        virtual void read(std::string& s, bool convert = true) = 0;
        virtual void read(std::vector<std::string>& s, bool convert) = 0;
        virtual void read(std::wstring& s) = 0;
 
        virtual void read(::std::vector<bool>&) = 0;

        Int readEnum(Int maxValue) { ... }
 
        template<typename T> inline void 
        read(T& v) { ... }

        virtual void read(std::vector<std::string>& v, bool convert) = 0;

        virtual void read(std::pair<const bool*, const bool*>&,
                          IceUtil::ScopedArray<bool>&) = 0;

        virtual void read(std::pair<const Byte*, const Byte*>&) = 0;

        virtual void read(std::pair<const Short*, const Short*>&,
                          IceUtil::ScopedArray<Short>&) = 0;

        virtual void read(std::pair<const Int*, const Int*>&,
                          IceUtil::ScopedArray<Int>&) = 0;

        virtual void read(std::pair<const Long*, const Long*>&,
                          IceUtil::ScopedArray<Long>&) = 0;

        virtual void read(std::pair<const Float*, const Float*>&,
                          IceUtil::ScopedArray<Float>&) = 0;

        virtual void read(std::pair<const Double*, const Double*>&,
                          IceUtil::ScopedArray<Double>&) = 0;

        virtual Int readSize() = 0;
        virtual Int readAndCheckSeqSize(int minWireSize) = 0;

        virtual ObjectPrx readProxy() = 0;

        template<typename T> inline void
        read(IceInternal::ProxyHandle<T>& v) { ... }

        virtual void readObject(const ReadObjectCallbackPtr& cb) = 0;

        template<typename T> inline void
        read(IceInternal::Handle<T>& v) { ... }
 
        virtual void throwException() = 0;
        virtual void throwException(const UserExceptionReaderFactoryPtr&) = 0;
 
        virtual void startObject() = 0;
        virtual SlicedDataPtr endObject(bool preserve) = 0;
 
        virtual void startException() = 0;
        virtual SlicedDataPtr endException(bool preserve) = 0;

        virtual std::string startSlice() = 0;
        virtual void endSlice() = 0;
        virtual void skipSlice() = 0;

        virtual EncodingVersion startEncapsulation() = 0;
        virtual void endEncapsulation() = 0;
        virtual EncodingVersion skipEncapsulation() = 0;
 
        virtual EncodingVersion getEncoding() = 0;

        virtual void readPendingObjects() = 0;

        virtual void rewind() = 0;
 
        virtual void skip(Int sz) = 0;
        virtual void skipSize() = 0;
 
        virtual bool readOptional(Int tag, OptionalFormat fmt) = 0;
 
        virtual void closure(void* p) = 0;
        virtual void* closure() const = 0;
    };
    typedef ... InputStreamPtr;
}
{zcode}

Extracting from an InputStream in C++

An InputStream provides a number of overloaded read member functions that allow you to read any parameter from the stream by simply calling read.

For example, you can extract a double value followed by a string from a stream as follows:

{zcode:cpp}
vector<Ice::Byte> data = ...;
in = Ice::createInputStream(communicator, data);
double d;
in->read(d);
string s;
in->read(s);
{zcode}

Likewise, you can extract a sequence of a built-in type, or a complex type, or any other type from the stream as follows:

{zcode:cpp}
vector<Ice::Byte> data = ...;
in = Ice::createInputStream(communicator, data);
// ...
IntSeq s; // Slice: sequence<int> IntSeq;
in->read(s);
 
ComplexType c;
in->read(c);
{zcode}

Extracting Sequences of Built-In Types using Zero-Copy in C++

InputStream provides a number of overloads that accept a pair of pointers. For example, you can extract a sequence of bytes as follows:

{zcode:cpp}
vector<Ice::Byte> data = ...;
in = Ice::wrapInputStream(communicator, data);
std::pair<const Ice::Byte*, const Ice::Byte*> p;
in->read(p);
{zcode}

The same extraction works for the other built-in integral and floating-point types, such int and double.

If the extraction is for a byte sequence, the returned pointers always point at memory in the stream's internal marshaling buffer.

For the other built-in types, the pointers refer to the internal marshaling buffer only if the Ice encoding is compatible with the machine and compiler representation of the type, otherwise the pointers refer to a temporary array allocated to hold the unmarshaled data. The overloads for zero-copy extraction accept an additional parameter of type IceUtil::ScopedArray that holds this temporary array when necessary.

Here is an example to illustrate how to extract a sequence of integers, regardless of whether the machine's encoding of integers matches the on-the-wire representation or not:

{zcode:cpp}
#include <IceUtil/ScopedArray.h>
...
in = Ice::wrapInputStream(communicator, data);
std::pair<const Ice::Int*, const Ice::Int*> p;
IceUtil::ScopedArray<Ice::Int> a;
in->read(p, a);

for(const Ice::Int* i = p.first; i != p.second; ++i) {
    cout << *i << endl;
}
{zcode}

If the on-the-wire encoding matches that of the machine, and therefore zero-copy is possible, the returned pair of pointers points into the run time's internal marshaling buffer. Otherwise, the run time allocates an array, unmarshals the data into the array, and sets the pair of pointers to point into that array. Use of the ScopedArray helper template ensures that the array is deallocated once you let the ScopedArray go out of scope, so there is no need to call delete[]. ScopedArray is comparable to a std::unique_ptr for arrays.

Other InputStream Methods in C++

The remaining member functions of InputStream have the following semantics:

See Also