The OutputStream Interface in C++

On this page:

The OutputStream API in C++

An OutputStream is created using the following functions:

C++
namespace Ice {
    OutputStreamPtr createOutputStream(const CommunicatorPtr& communicator);
 
    OutputStreamPtr createOutputStream(constCommunicatorPtr& communicator,
                                       const EncodingVersion& version);
}

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

The OutputStream class is shown below.

C++
namespace Ice {
    class OutputStream : ... {
    public:
        virtual CommunicatorPtr communicator() const = 0;

        virtual void write(bool) = 0;
        virtual void write(Byte) = 0;
        virtual void write(Short) = 0;
        virtual void write(Int) = 0;
        virtual void write(Long) = 0;
        virtual void write(Float) = 0;
        virtual void write(Double) = 0;
        virtual void write(const std::string&, bool = true) = 0;
        virtual void write(const char*, size_t, bool = true) = 0;
        virtual void write(const char*, bool = true) = 0;
        virtual void write(const std::wstring&) = 0;
 
        virtual void write(const std::vector<bool>&) = 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;
 
        void writeEnum(Int v, Int maxValue) { ... }
 
        virtual bool writeOptional(Int tag, OptionalFormat fmt) = 0;
 
        template<typename T> inline void 
        write(const T& v) { ... }

        virtual void writeSize(Int sz) = 0;
        virtual void startSize() = 0;
        virtual void endSize() = 0;

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

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

        virtual void writeObject(const ObjectPtr&) = 0;

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

        virtual void writeException(const UserException& e) = 0;
 
        virtual void startObject(const SlicedDataPtr& sd) = 0;
        virtual void endObject() = 0;

        virtual void startException(const SlicedDataPtr& sd) = 0;
        virtual void endException() = 0;

        virtual void startSlice(const std::string& typeId, bool last) = 0;
        virtual void endSlice() = 0;

        virtual void startEncapsulation(const EncodingVersion& v, FormatType fmt) = 0;
        virtual void startEncapsulation() = 0;
        virtual void endEncapsulation() = 0;

        virtual EncodingVersion getEncoding() const = 0;

        virtual void writePendingObjects() = 0;

        virtual void finished(std::vector<Byte>& v) = 0;
        virtual std::pair<const Byte*, const Byte*> finished() = 0;
 
        virtual size_type pos() = 0;
        virtual void rewrite(Int v, size_type pos) = 0;

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

Inserting into an OutputStream in C++

An OutputStream provides a number of overloaded write member functions that allow you to insert any parameter into the stream by simply calling write.

For example, you can insert a double value followed by a string into a stream as follows:

C++
out = Ice::createOutputStream(communicator);
Ice::Double d = 3.14;
out->write(d);
string s = "Hello";
out->write(s);

Likewise, you can insert a sequence of built-in type, or a sequence of a complex constructed type, or any other type, with the same syntax:

C++
out = Ice::createOutputStream(communicator);
IntSeq s = ...;
out->write(s);
 
ComplexType c = ...;
out->write(c);

Inserting Sequences of Built-In Types 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:

C++
out = Ice::createOutputStream(communicator);
vector<Ice::Byte> v = ...;
out->write(&v[0], &v[v.size()]);

The same insertion technique works for the other built-in integral and floating-point types, such int and double. Insertion with these functions is a straight copy into the marshaling buffer when 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.)

Other OutputStream Member Functions in C++

The remaining member functions of OutputStream have the following semantics:

  • void write(const std::string& v, bool convert = true)
    void write(const char* v, size_t vlen, bool convert = true)
    void write(const char* v, bool convert = true)
    void write(const std::vector<std::string>&, bool convert)
    The boolean argument determines whether the strings marshaled by these methods are processed by the string converter, if one is installed. The default behavior is to convert the strings.
  • void writeEnum(Int val, Int maxValue)
    Writes the integer value of an enumerator. The maxValue argument represents the highest enumerator value in the enumeration. Consider the following definitions:

    Slice
    enum Color { red, green, blue };
    enum Fruit { Apple, Pear=3, Orange };
    

    The maximum value for Color is 2, and the maximum value for Fruit is 4.
    In general, you should simply use write for your enum values. write with an enum parameter calls writeEnum with the maxValue provided by the code generated by slice2cpp.

  • void writeSize(Ice::Int sz)
    The Ice encoding has a compact representation to indicate size. This function converts the given non-negative integer into the proper encoded representation.
  • void startSize()
    void endSize()
    The encoding for optional values uses a 32-bit integer to hold the size of variable-length types. Calling startSize writes a placeholder value for the size; after writing the data, call endSize to patch the placeholder with the actual size.
  • bool writeOptional(Int tag, OptionalFormat fmt)
    Prepares the stream to write an optional value with the given tag and format. Returns true if the value should be written, or false otherwise. A return value of false indicates that the encoding version in use by the stream does not support optional values. If this method returns true, the data associated with that optional value must be written next. Optional values must be written in order by tag from least to greatest. The OptionalFormat enumeration is defined as follows:

    C++
    namespace Ice {
        enum OptionalFormat {
            OptionalFormatF1, OptionalFormatF2, OptionalFormatF4, OptionalFormatF8,
            OptionalFormatSize, OptionalFormatVSize, OptionalFormatFSize,
            OptionalFormatEndMarker
        };
    }
    

    Refer to the encoding discussion for more information on the meaning of these values.

  • void writeProxy(const Ice::ObjectPrx&)
    Inserts a proxy into the stream. It is equivalent to calling write with a proxy parameter.
  • void writeObject(const Ice::ObjectPtr&)
    Inserts an Ice object. The Ice encoding for class instances may cause the insertion of this object to be delayed, in which case the stream retains a reference to the given object and the stream does not insert its state it until writePendingObjects is invoked on the stream. It is equivalent to calling write with a Ptr parameter.
  • void startObject(const SlicedDataPtr& sd)
    void endObject()
    When marshaling the slices of an object, the application must first call startObject, then marshal the slices, and finally call endObject. The caller can pass a SlicedData object containing the preserved slices of unknown more-derived types, or 0 if there are no preserved slices.

  • void startException(const SlicedDataPtr& sd)
    void endException()
    When marshaling the slices of an exception, the application must first call startException, then marshal the slices, and finally call endException. The caller can pass a SlicedData object containing the preserved slices of unknown more-derived types, or 0 if there are no preserved slices.
  • void startSlice(const std::string& typeId, bool last)
    void endSlice()
    Starts and ends a slice of object or exception member data. The call to startSlice must include the type ID for the current slice, and a boolean indicating whether this is the last slice of the object or exception.
  • void startEncapsulation(const EncodingVersion& v, FormatType fmt)
    void startEncapsulation()

    void endEncapsulation()
    Starts and ends an encapsulation, respectively. The first overloading of startEncapsulation allows you to specify the encoding version as well as the format to use for any objects and exceptions marshaled within this encapsulation.
  • EncodingVersion getEncoding()
    Returns the encoding version currently being used by the stream.
  • void writePendingObjects()
    Encodes the state of Ice objects whose insertion was delayed during writeObject. This member function must only be called once. For backward compatibility with encoding version 1.0, this function must only be called when non-optional data members or parameters use class types.
  • void finished(std::vector< Ice::Byte >& data)
    std::pair<const Byte*, const Byte*> finished()

    Indicates that marshaling is complete. This member function must only be called once. In the first overloading, the given byte sequence is filled with a copy of the encoded data. The second overloading avoids a copy by returning a pair of pointers to the stream's internal memory; these pointers are valid for the lifetime of the OutputStream object.
  • size_type pos()
    void rewrite(Int v, size_type pos)
    The pos method returns the stream's current position, and rewrite allows you to overwrite a 32-bit integer value at the given position in the stream. Calling rewrite does not change the stream's current position.
  • void reset(bool clearBuffer)
    Resets the writing position of the stream to the beginning. If clearBuffer is true, the stream releases the memory it has allocated to hold the encoded data.
See Also