On this page:
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} |
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} |
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} |
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.)
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} |
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} |
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} |
OutputStream
Methods 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, bool convert = true)
void write(const std::vector<std::string>&, bool convert = true)
void writeSize(Ice::Int sz)
void writeProxy(const Ice::ObjectPtr & v)
template<typename T> inline void
write(const IceInternal::Handle<T>& v)
writeObject
. You can pass a smart pointer of any type as the parameter v
.void writeObject(const Ice::ObjectPtr & v)
writePendingObjects
is invoked on the stream.template<typename T> inline void
write(const IceInternal::ProxyHandle<T>& v)
writeProxy
. You can pass a proxy of any type as the parameter v
.void writeTypeId(const std::string & id)
writeTypeId
may only be invoked in the context of a call to writePendingObjects
(see below).void writeException(const Ice::UserException & ex)
write(const T&)
to insert a user exception.void startEncapsulation()
void endEncapsulation()
void writePendingObjects()
writeObject
. This member function must only be called once.void finished(std::vector< Ice::Byte > & data)
void reset(bool clearBuffer)
clearBuffer
is true, the stream releases the memory it has allocated to hold the encoded data.