// ********************************************************************** // // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_STREAM_H #define ICE_STREAM_H #include #include #include #include #include #include namespace Ice { // // COMPILERFIX: VC++ 6 compiler bug doesn't allow using templates for // the Stream API. // // see: http://support.microsoft.com/kb/240866 // http://support.microsoft.com/kb/241569 // #if !defined(_MSC_VER) || (_MSC_VER >= 1300) enum StreamTraitType { StreamTraitTypeBuiltin, StreamTraitTypeStruct, StreamTraitTypeStructClass, // struct with cpp:class metadata StreamTraitTypeByteEnum, // Enums with up to 127 enumerators StreamTraitTypeShortEnum, // Enums with up to 32767 enumerators StreamTraitTypeIntEnum, // Enums with more than 32767 enumerators StreamTraitTypeSequence, #ifndef __BCPLUSPLUS__ // COMPILERFIX: See StreamTrait> comment below StreamTraitTypeSequenceBool, #endif StreamTraitTypeDictionary, StreamTraitTypeUserException, StreamTraitTypeUnknown }; // Forward declaration required for writer specializations. class MarshalException; // // Base trait template. This doesn't actually do anything -- we just // use it as a template that we can specialize. // template struct StreamTrait { static const StreamTraitType type = StreamTraitTypeUnknown; static const int minWireSize = 0; }; // // StreamTrait specialization for std::vector // template struct StreamTrait< ::std::vector > { static const StreamTraitType type = StreamTraitTypeSequence; static const int minWireSize = 1; }; // // StreamTrait specialization for std::vector. Sequences of bool // are handled specifically because C++ optimizations for vector // prevent us from reading vector of bools the same way as other // sequences (see StreamReader::read // implementation below) // // COMPILERFIX: BCC2010 doesn't allow use of full specialization over // partial specialization. // #ifndef __BCPLUSPLUS__ template<> struct StreamTrait< ::std::vector > { static const StreamTraitType type = StreamTraitTypeSequenceBool; static const int minWireSize = 1; }; #endif template<> struct StreamTrait { static const StreamTraitType type = StreamTraitTypeUserException; }; // // StreamTrait specialization for std::map. // template struct StreamTrait< ::std::map > { static const StreamTraitType type = StreamTraitTypeDictionary; static const int minWireSize = 1; }; // // StreamTrait specialization for builtins (these are needed for sequence // marshalling to figure out the minWireSize of each built-in). // template<> struct StreamTrait< bool> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 1; }; template<> struct StreamTrait< Byte> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 1; }; template<> struct StreamTrait< Short> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 2; }; template<> struct StreamTrait< Int> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 4; }; template<> struct StreamTrait< Long> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 8; }; template<> struct StreamTrait< Float> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 4; }; template<> struct StreamTrait< Double> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 8; }; template<> struct StreamTrait< ::std::string> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 1; }; template<> struct StreamTrait< ::std::wstring> { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 1; }; template struct StreamTrait< ::IceInternal::ProxyHandle > { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 2; }; template struct StreamTrait< ::IceInternal::Handle > { static const StreamTraitType type = StreamTraitTypeBuiltin; static const int minWireSize = 4; }; // // This is the non-specialized version of the writer. For each kind of // user-defined type (enum, struct, etc), we specialize this template // to call the correct member function that writes an instance of that // type to the stream. // template struct StreamWriter { template static void write(const OutputStreamPtr&, const T&) { // This asserts because we end up writing something for which // we never defined a trait. assert(false); } }; // // This is the non-specialized version of the reader. For each kind of // user-defined type (enum, struct, etc), we specialize this template // to call the correct member function that reads an instance of that // type to the stream. // template struct StreamReader { template static void read(const InputStreamPtr&, T&) { // This asserts because we end up reading something for which // we never define a trait. assert(false); } }; #endif class ICE_API ReadObjectCallback : public ::IceUtil::Shared { public: virtual void invoke(const ObjectPtr&) = 0; }; typedef IceUtil::Handle ReadObjectCallbackPtr; template class ReadObjectCallbackI : public ReadObjectCallback { public: ReadObjectCallbackI(::IceInternal::Handle& v) : _v(v) { } virtual void invoke(const ObjectPtr& p) { _v = ::IceInternal::Handle::dynamicCast(p); if(p && !_v) { IceInternal::Ex::throwUOE(T::ice_staticId(), p->ice_id()); } } private: ::IceInternal::Handle& _v; }; class ICE_API InputStream : public ::IceUtil::Shared { public: virtual CommunicatorPtr communicator() const = 0; virtual void sliceObjects(bool) = 0; // // COMPILERFIX: BCC2010 doesn't allow use of full specialization over // partial specialization. // #ifdef __BCPLUSPLUS__ void read(::std::_Vb_reference v) { v = readBool(); } #endif ICE_DEPRECATED_API virtual bool readBool() = 0; ICE_DEPRECATED_API virtual Byte readByte() = 0; ICE_DEPRECATED_API virtual Short readShort() = 0; ICE_DEPRECATED_API virtual Int readInt() = 0; ICE_DEPRECATED_API virtual Long readLong() = 0; ICE_DEPRECATED_API virtual Float readFloat() = 0; ICE_DEPRECATED_API virtual Double readDouble() = 0; ICE_DEPRECATED_API virtual ::std::string readString(bool = true) = 0; ICE_DEPRECATED_API virtual ::std::wstring readWstring() = 0; ICE_DEPRECATED_API virtual ::std::vector readBoolSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readByteSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readShortSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readIntSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readLongSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readFloatSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector readDoubleSeq() = 0; ICE_DEPRECATED_API virtual ::std::vector< ::std::string> readStringSeq(bool = true) = 0; ICE_DEPRECATED_API virtual ::std::vector< ::std::wstring> readWstringSeq() = 0; ICE_DEPRECATED_API virtual bool* readBoolSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual void readByteSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual Short* readShortSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual Int* readIntSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual Long* readLongSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual Float* readFloatSeq(::std::pair&) = 0; ICE_DEPRECATED_API virtual Double* readDoubleSeq(::std::pair&) = 0; virtual Int readSize() = 0; virtual Int readAndCheckSeqSize(int) = 0; virtual ObjectPrx readProxy() = 0; virtual void readObject(const ReadObjectCallbackPtr&) = 0; virtual ::std::string readTypeId() = 0; virtual void throwException() = 0; virtual void startSlice() = 0; virtual void endSlice() = 0; virtual void skipSlice() = 0; virtual void startEncapsulation() = 0; virtual void endEncapsulation() = 0; virtual void skipEncapsulation() = 0; virtual void readPendingObjects() = 0; virtual void rewind() = 0; virtual void read(bool&) = 0; virtual void read(Byte&) = 0; virtual void read(Short&) = 0; virtual void read(Int&) = 0; virtual void read(Long&) = 0; virtual void read(Float&) = 0; virtual void read(Double&) = 0; virtual void read(::std::string&, bool = true) = 0; virtual void read(::std::vector< ::std::string>&, bool) = 0; // Overload required for additional bool argument. virtual void read(::std::wstring&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; virtual void read(::std::pair&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; virtual void read(::std::pair&, ::IceUtil::ScopedArray&) = 0; template inline void read(::IceInternal::ProxyHandle& v) { ObjectPrx proxy = readProxy(); if(!proxy) { v = 0; } else { v = new T; v->__copyFrom(proxy); } } template inline void read(::IceInternal::Handle& v) { ReadObjectCallbackPtr cb = new ReadObjectCallbackI(v); readObject(cb); } // // COMPILERFIX: VC++ 6 compiler bugs doesn't allow using templates for // the Stream API. // // see: http://support.microsoft.com/kb/240866 // http://support.microsoft.com/kb/241569 // #if !defined(_MSC_VER) || (_MSC_VER >= 1300) template inline void read(T& v) { StreamReader< StreamTrait::type>::read(this, v); } #endif }; class ICE_API OutputStream : public ::IceUtil::Shared { public: virtual CommunicatorPtr communicator() const = 0; ICE_DEPRECATED_API virtual void writeBool(bool) = 0; ICE_DEPRECATED_API virtual void writeByte(Byte) = 0; ICE_DEPRECATED_API virtual void writeShort(Short) = 0; ICE_DEPRECATED_API virtual void writeInt(Int) = 0; ICE_DEPRECATED_API virtual void writeLong(Long) = 0; ICE_DEPRECATED_API virtual void writeFloat(Float) = 0; ICE_DEPRECATED_API virtual void writeDouble(Double) = 0; ICE_DEPRECATED_API virtual void writeString(const ::std::string&, bool = true) = 0; ICE_DEPRECATED_API virtual void writeWstring(const ::std::wstring&)= 0; ICE_DEPRECATED_API virtual void writeBoolSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeByteSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeShortSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeIntSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeLongSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeFloatSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeDoubleSeq(const ::std::vector&) = 0; ICE_DEPRECATED_API virtual void writeStringSeq(const ::std::vector< ::std::string>&, bool = true) = 0; ICE_DEPRECATED_API virtual void writeWstringSeq(const ::std::vector< ::std::wstring>&) = 0; ICE_DEPRECATED_API virtual void writeBoolSeq(const bool*, const bool*) = 0; ICE_DEPRECATED_API virtual void writeByteSeq(const Byte*, const Byte*) = 0; ICE_DEPRECATED_API virtual void writeShortSeq(const Short*, const Short*) = 0; ICE_DEPRECATED_API virtual void writeIntSeq(const Int*, const Int*) = 0; ICE_DEPRECATED_API virtual void writeLongSeq(const Long*, const Long*) = 0; ICE_DEPRECATED_API virtual void writeFloatSeq(const Float*, const Float*) = 0; ICE_DEPRECATED_API virtual void writeDoubleSeq(const Double*, const Double*) = 0; virtual void writeSize(Int) = 0; virtual void writeProxy(const ObjectPrx&) = 0; virtual void writeObject(const ObjectPtr&) = 0; virtual void writeTypeId(const ::std::string&) = 0; virtual void writeException(const UserException&) = 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&) = 0; virtual void reset(bool) = 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 ::std::vector< ::std::string>&, bool) = 0; // Overload required for bool argument. virtual void write(const char*, bool = true) = 0; virtual void write(const ::std::wstring&) = 0; virtual void write(const bool*, const bool*) = 0; virtual void write(const Byte*, const Byte*) = 0; virtual void write(const Short*, const Short*) = 0; virtual void write(const Int*, const Int*) = 0; virtual void write(const Long*, const Long*) = 0; virtual void write(const Float*, const Float*) = 0; virtual void write(const Double*, const Double*) = 0; template inline void write(const ::IceInternal::ProxyHandle& v) { writeProxy(v); } template inline void write(const ::IceInternal::Handle& v) { writeObject(v); } // // COMPILERFIX: VC++ 6 compiler bugs doesn't allow using templates for // the Stream API. // // see: http://support.microsoft.com/kb/240866 // http://support.microsoft.com/kb/241569 // #if !defined(_MSC_VER) || (_MSC_VER >= 1300) template inline void write(const T& v) { StreamWriter::type>::write(this, v); } #endif protected: }; // // COMPILERFIX: VC++ 6 compiler bugs doesn't allow using templates for // the Stream API. // // see: http://support.microsoft.com/kb/240866 // http://support.microsoft.com/kb/241569 // #if !defined(_MSC_VER) || (_MSC_VER >= 1300) template<> // StreamWriter specialization for structs struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { v.ice_write(outS); } }; template<> // StreamReader specialization for structs struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { v.ice_read(inS); } }; template<> // StreamWriter specialization for structs with cpp:class metadata struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { v->ice_write(outS); } }; template<> // StreamReader specialization for structs with cpp:class metadata struct StreamReader { template static void read(const InputStreamPtr& inS, const T& v) { v->ice_read(inS); } }; template<> // StreamWriter specialization for byte enums struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { if(static_cast(v) < 0 || static_cast(v) >= StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } outS->write(static_cast(v)); } }; template<> // StreamReader specialization for byte enums struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Byte val; inS->read(val); if(val > StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } v = static_cast(val); } }; template<> // StreamWriter specialization for short enums struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { if(static_cast(v) < 0 || static_cast(v) >= StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } outS->write(static_cast(v)); } }; template<> // StreamReader specialization for short enums struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Short val; inS->read(val); if(val < 0 || val > StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } v = static_cast(val); } }; template<> // StreamWriter specialization for int enums struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { if(static_cast(v) < 0 || static_cast(v) >= StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } outS->write(static_cast(v)); } }; template<> // StreamReader specialization for int enums struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Int val; inS->read(val); if(val < 0 || val > StreamTrait::enumLimit) { throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); } v = static_cast(val); } }; template<> // StreamWriter specialization for sequences struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { outS->writeSize(static_cast(v.size())); for(typename T::const_iterator p = v.begin(); p != v.end(); ++p) { outS->write(*p); } } }; template<> // StreamReader specialization for sequences struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Int sz = inS->readAndCheckSeqSize(StreamTrait::minWireSize); v.resize(sz); for(typename T::iterator p = v.begin(); p != v.end(); ++p) { inS->read(*p); } } }; #ifndef __BCPLUSPLUS__ // COMPILERFIX: See StreamTrait> comment above template<> // StreamWriter specialization for sequences of bool struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { outS->writeSize(static_cast(v.size())); for(typename T::const_iterator p = v.begin(); p != v.end(); ++p) { outS->write(*p); } } }; template<> // Reader specialization for sequences of bool struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Int sz = inS->readAndCheckSeqSize(StreamTrait::minWireSize); v.resize(sz); for(typename T::iterator p = v.begin(); p != v.end(); ++p) { // // We can't just call inS->read(*p) here because *p is // a compiler dependent bit reference. // bool b; inS->read(b); *p = b; } } }; #endif template<> // StreamWriter specialization for dictionaries. struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { outS->writeSize(static_cast(v.size())); typename T::const_iterator p; for(p = v.begin(); p != v.end(); ++p) { outS->write(p->first); outS->write(p->second); } } }; template<> // StreamReader specialization for dictionaries. struct StreamReader { template static void read(const InputStreamPtr& inS, T& v) { Int sz = inS->readSize(); while(sz--) { typename T::value_type p; inS->read(const_cast(p.first)); typename T::iterator i = v.insert(v.end(), p); inS->read(i->second); } } }; template<> // StreamWriter specialization for UserExceptions. struct StreamWriter { template static void write(const OutputStreamPtr& outS, const T& v) { outS->writeException(v); } }; #endif class ICE_API ObjectReader : public Object { public: virtual void read(const InputStreamPtr&, bool) = 0; private: virtual void __write(::IceInternal::BasicStream*) const; virtual void __read(::IceInternal::BasicStream*, bool = true); virtual void __write(const OutputStreamPtr&) const; virtual void __read(const InputStreamPtr&, bool); }; typedef ::IceInternal::Handle ObjectReaderPtr; class ICE_API ObjectWriter : public Object { public: virtual void write(const OutputStreamPtr&) const = 0; private: virtual void __write(::IceInternal::BasicStream*) const; virtual void __read(::IceInternal::BasicStream*, bool = true); virtual void __write(const OutputStreamPtr&) const; virtual void __read(const InputStreamPtr&, bool); }; typedef ::IceInternal::Handle ObjectWriterPtr; class ICE_API UserExceptionWriter : public UserException { public: UserExceptionWriter(const CommunicatorPtr&); ~UserExceptionWriter() throw(); virtual void write(const OutputStreamPtr&) const = 0; virtual bool usesClasses() const = 0; virtual ::std::string ice_name() const = 0; virtual Exception* ice_clone() const = 0; virtual void ice_throw() const = 0; virtual void __write(IceInternal::BasicStream*) const; virtual void __read(IceInternal::BasicStream*, bool); virtual bool __usesClasses() const; protected: const CommunicatorPtr _communicator; }; } #endif