// ********************************************************************** // // Copyright (c) 2003-2004 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_BASIC_STREAM_H #define ICE_BASIC_STREAM_H #include #include #include #include #include namespace Ice { class UserException; } namespace IceInternal { class ICE_API BasicStream : public Buffer { public: typedef void (*PatchFunc)(void*, Ice::ObjectPtr&); BasicStream(Instance*); ~BasicStream(); // // Must return Instance*, because we don't hold an InstancePtr for // optimization reasons (see comments below). // Instance* instance() const; void swap(BasicStream&); void resize(Container::size_type sz) { if(sz > _messageSizeMax) { throwMemoryLimitException(__FILE__, __LINE__); } Container::size_type capacity = b.capacity(); if(capacity < sz) { // // COMPILERBUG: Stupid Visual C++ defines max as a // macro. But I can't undefine it in a header file, // because this might cause side effects with other code // that depends on this macro being defined. // //b.reserve(std::max(sz, 2 * capacity)); b.reserve(sz > 2 * capacity ? sz : 2 * capacity); } b.resize(sz); } void reserve(Container::size_type); void startSeq(int, int); void checkSeq(); void checkSeq(int); void endElement() { assert(_seqDataStack); --_seqDataStack->numElements; } void endSeq(int); void checkFixedSeq(int, int); // For sequences of fixed-size types. void startWriteEncaps(); void endWriteEncaps(); void startReadEncaps(); void endReadEncaps(); void checkReadEncaps(); Ice::Int getReadEncapsSize(); void skipEncaps(); void startWriteSlice(); void endWriteSlice(); void startReadSlice(); void endReadSlice(); void skipSlice(); void writeSize(Ice::Int); void readSize(Ice::Int&); void writeTypeId(const std::string&); void readTypeId(std::string&); void writeBlob(const std::vector&); void readBlob(std::vector&, Ice::Int); void writeBlob(const Ice::Byte*, Container::size_type); void readBlob(Ice::Byte*, Container::size_type); void write(Ice::Byte v) { b.push_back(v); } void write(const std::vector&); void read(Ice::Byte& v) { if(i >= b.end()) { throwUnmarshalOutOfBoundsException(__FILE__, __LINE__); } v = *i++; } void read(std::vector&); void write(bool v) { b.push_back(static_cast(v)); } void write(const std::vector&); void read(bool& v) { if(i >= b.end()) { throwUnmarshalOutOfBoundsException(__FILE__, __LINE__); } v = *i++; } void read(std::vector&); void write(Ice::Short); void write(const std::vector&); void read(Ice::Short&); void read(std::vector&); void write(Ice::Int); void write(const std::vector&); void read(Ice::Int&); void read(std::vector&); void write(Ice::Long); void write(const std::vector&); void read(Ice::Long&); void read(std::vector&); void write(Ice::Float); void write(const std::vector&); void read(Ice::Float&); void read(std::vector&); void write(Ice::Double); void write(const std::vector&); void read(Ice::Double&); void read(std::vector&); // // NOTE: This function is not implemented. It is declared here to // catch programming errors that assume a call such as write("") // will invoke write(const std::string&), when in fact the compiler // will silently select a different overloading. A link error is the // intended result. // void write(const char*); void write(const std::string&); void write(const std::vector&); void read(std::string&); void read(std::vector&); void write(const Ice::ObjectPrx&); void read(Ice::ObjectPrx&); void write(const Ice::ObjectPtr&); void read(PatchFunc, void*); void write(const Ice::UserException&); void throwException(); void writePendingObjects(); void readPendingObjects(); void sliceObjects(bool); struct PatchEntry { PatchFunc patchFunc; void* patchAddr; }; typedef std::vector PatchList; typedef std::map PatchMap; typedef std::map IndexToPtrMap; typedef std::map TypeIdReadMap; typedef std::map PtrToIndexMap; typedef std::map TypeIdWriteMap; typedef std::vector ObjectList; private: // // I can't throw these exception from inline functions from within // this file, because I cannot include the header with the // exceptions. Doing so would screw up the whole include file // ordering. // void throwUnmarshalOutOfBoundsException(const char*, int); void throwMemoryLimitException(const char*, int); // // Optimization. The instance may not be deleted while a // stack-allocated BasicStream still holds it. // Instance* _instance; class ICE_API ReadEncaps : public ::IceUtil::noncopyable { public: ReadEncaps(); ~ReadEncaps(); void reset(); void swap(ReadEncaps&); Container::size_type start; Ice::Int sz; Ice::Byte encodingMajor; Ice::Byte encodingMinor; PatchMap* patchMap; IndexToPtrMap* unmarshaledMap; TypeIdReadMap* typeIdMap; Ice::Int typeIdIndex; ReadEncaps* previous; }; class ICE_API WriteEncaps : public ::IceUtil::noncopyable { public: WriteEncaps(); ~WriteEncaps(); void reset(); void swap(WriteEncaps&); Container::size_type start; Ice::Int writeIndex; PtrToIndexMap* toBeMarshaledMap; PtrToIndexMap* marshaledMap; TypeIdWriteMap* typeIdMap; Ice::Int typeIdIndex; WriteEncaps* previous; }; ReadEncaps* _currentReadEncaps; WriteEncaps* _currentWriteEncaps; ReadEncaps _preAllocatedReadEncaps; WriteEncaps _preAllocatedWriteEncaps; Container::size_type _readSlice; Container::size_type _writeSlice; void writeInstance(const Ice::ObjectPtr&, Ice::Int); void patchPointers(Ice::Int, IndexToPtrMap::const_iterator, PatchMap::iterator); int _traceSlicing; const char* _slicingCat; bool _sliceObjects; const Container::size_type _messageSizeMax; struct SeqData { SeqData(int, int); int numElements; int minSize; SeqData* previous; }; SeqData* _seqDataStack; ObjectList* _objectList; }; } #endif