On this page:

The OutputStream API in C++

An OutputStream is created using the following function:

{zcode:cpp}
namespace Ice {
    OutputStreamPtr createOutputStream(const Ice::CommunicatorPtr& communicator);
}
{zcode}

The OutputStream class is shown below.

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

        virtual void write(bool v) = 0;
        virtual void write(Byte v) = 0;
        virtual void write(Short v) = 0;
        virtual void write(Int v) = 0;
        virtual void write(Long v) = 0;
        virtual void write(Float v) = 0;
        virtual void write(Double v) = 0;
        virtual void write(const std::string& v, bool convert = true) = 0;
        virtual void write(const char* v, bool convert = true) = 0;
        virtual void write(const std::wstring& v) = 0;

        virtual void write(const bool* begin, const bool* end) = 0;
        virtual void write(const Byte* begin, const Byte* end) = 0;
        virtual void write(const Short* begin, const Short* end) = 0;
        virtual void write(const Int* begin, const Int* end) = 0;
        virtual void write(const Long* begin, const Long* end) = 0;
        virtual void write(const Float* begin, const Float* end) = 0;
        virtual void write(const Double* begin, const Double* end) = 0;    

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

        template<typename T> inline void
        write(const T& v) {
            StreamWriter<StreamTrait<T>::type>::write(this, v);
        }

        virtual void writeSize(Ice::Int sz) = 0;

        virtual void writeProxy(const Ice::ObjectPrx& v) = 0;

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

        virtual void writeObject(const Ice::ObjectPtr& v) = 0;

        template<typename T> inline void
        write(const IceInternal::Handle<T>& v) {
            // ...
        }

        virtual void writeTypeId(const std::string& id) = 0;

        virtual void writeException(const Ice::UserException& e) = 0;

        virtual void startSlice() = 0;
        virtual void endSlice() = 0;

        virtual void startEncapsulation() = 0;
        virtual void endEncapsulation() = 0;

        virtual void writePendingObjects() = 0;

        virtual void finished(std::vector<Ice::Byte>& v) = 0;

        virtual void reset(bool) = 0;
    };
}
{zcode}

Inserting Built-In Types in C++

Member functions are provided to insert any of the built-in types. For example, you can insert a double value followed by a string into a stream as follows:

{zcode:cpp}
out = Ice::createOutputStream(communicator);
Ice::Double d = 3.14;
out->write(d);
string s = "Hello";
out->write(s);
{zcode}

Inserting Sequences of Built-In Types in C++

For types other than built-in types, the following template member function performs the insertion:

{zcode:cpp}
template<typename T> inline void
write(const T& v) {
    StreamWriter<StreamTrait<T>::type>::write(this, v);
}
{zcode}

For example, you can insert a sequence of integers as follows:

{zcode:cpp}
out = Ice::createOutputStream(communicator);
IntSeq s = ...;
out->write(s);
{zcode}

The Ice run time provides an implementation of the StreamWriter template whose write method writes a sequence of any of the built-in types. Note that, when writing a sequence, this writes both the sequence size that precedes the sequence elements and the sequence elements that follow the size.

If you are using a custom container for your sequence of built-in type, you must provide a specialization of the StreamTrait template in order to insert your sequence. For example, the following definition allows you to use the QVector container from the Qt library:

{zcode:cpp}
//
// StreamTrait specialization for QVector
//
template<typename T>
struct StreamTrait< QVector<T> >
{
    static const StreamTraitType type = StreamTraitTypeSequence;
    static const int minWireSize = 1;
};
{zcode}

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

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

{zcode:cpp}
out = Ice::createOutputStream(communicator);
vector<Ice::Byte> data = ...;
out->write(&v[0], &v[v.size()]);
{zcode}

The same insertion technique works for the other built-in integral and floating-point types, such int and double. Insertion in this way can avoid an additional data copy during marshaling if the internal representation of the data in memory is the same as the on-the-wire representation. (Note that the two pointers must point at a contiguous block of memory.)

Inserting Structures in C++

Without the --stream option to slice2cpp, you must insert structures member by member according to the data encoding rules. Otherwise, with --stream, slice2cpp generates code that allows you to insert the structure directly. For example, here is how you can insert a Slice structure called MyStruct into a stream:

{zcode:cpp}
out = Ice::createOutputStream(communicator);
MyStruct myStruct;
// Initialize myStruct...
out->write(myStruct);
{zcode}

Inserting Dictionaries in C++

Without the --stream option to slice2cpp, you can insert any dictionary whose key and value types are built-in types; for any other dictionary, you must insert it as a size followed by its entries according to the data encoding rules. If you are using a custom container for your dictionary of built-in types, you must provide a specialization of the StreamTrait template in order to insert your dictionary. For example, the following definition allows you to use the QMap container from the Qt library:

{zcode:cpp}
//
// StreamTrait specialization for QMap
//
template<typename K, typename V>
struct StreamTrait< QMap<K, V> >
{
    static const StreamTraitType type = StreamTraitTypeDictionary;
    static const int minWireSize = 1;
};
{zcode}

With the --stream option, slice2cpp generates code that allows you to insert any dictionary directly, for example:

{zcode:cpp}
out = Ice::createOutputStream(communicator);
MyDict myDict; // Slice: dictionary<int, SomeType> MyDict;
// Initialize myDict...
out->write(myDict);
{zcode}

Inserting Sequences of User-Defined Types in C++

Without the --stream option to slice2cpp, you must insert sequences of user-defined type as a size followed by the element type according to the data encoding rules. Otherwise, with --stream, slice2cpp generates code that allows you to insert a sequence directly, for example:

{zcode:cpp}
out = Ice::createOutputStream(communicator);
MyEnumS myEnumS; // Slice: sequence<MyEnum> myEnumS;
// Initialize myEnumS...
out->write(myEnumS);
{zcode}

Other OutputStream Methods in C++

The remaining member functions of OutputStream have the following semantics:

See Also