summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2012-05-18 11:11:20 +0200
committerBenoit Foucher <benoit@zeroc.com>2012-05-18 11:11:20 +0200
commit58905f8e2f23f5c60312bf4163170be1d63ca31e (patch)
tree322dbc9ccaafdef7ef3ac266a7dd578911b40b31
parentparser support for optional data members (diff)
downloadice-58905f8e2f23f5c60312bf4163170be1d63ca31e.tar.bz2
ice-58905f8e2f23f5c60312bf4163170be1d63ca31e.tar.xz
ice-58905f8e2f23f5c60312bf4163170be1d63ca31e.zip
BasicStream refactoring
-rw-r--r--cpp/include/Ice/BasicStream.h385
-rw-r--r--cpp/include/Ice/Stream.h4
-rwxr-xr-xcpp/src/Ice/BasicStream.cpp1845
-rw-r--r--cpp/src/Ice/StreamI.cpp4
4 files changed, 983 insertions, 1255 deletions
diff --git a/cpp/include/Ice/BasicStream.h b/cpp/include/Ice/BasicStream.h
index ca1e2264999..65533921b07 100644
--- a/cpp/include/Ice/BasicStream.h
+++ b/cpp/include/Ice/BasicStream.h
@@ -48,9 +48,7 @@ public:
{
// Inlined for performance reasons.
- if(_currentReadEncaps != &_preAllocatedReadEncaps ||
- _currentWriteEncaps != &_preAllocatedWriteEncaps ||
- _objectList)
+ if(_currentReadEncaps != &_preAllocatedReadEncaps || _currentWriteEncaps != &_preAllocatedWriteEncaps)
{
clear(); // Not inlined.
}
@@ -84,17 +82,49 @@ public:
void format(Ice::FormatType);
- void startWriteObject(const Ice::SlicedDataPtr&);
- void endWriteObject();
+ void startWriteObject(const Ice::SlicedDataPtr& data)
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->startObject(data);
+ }
+ void endWriteObject()
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->endObject();
+ }
- void startReadObject();
- Ice::SlicedDataPtr endReadObject(bool);
+ void startReadObject()
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ _currentReadEncaps->decoder->startObject();
+ }
+ Ice::SlicedDataPtr endReadObject(bool preserve)
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ return _currentReadEncaps->decoder->endObject(preserve);
+ }
- void startWriteException(const Ice::SlicedDataPtr&);
- void endWriteException();
+ void startWriteException(const Ice::SlicedDataPtr& data)
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->startException(data);
+ }
+ void endWriteException()
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->endException();
+ }
- void startReadException();
- Ice::SlicedDataPtr endReadException(bool);
+ void startReadException()
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ _currentReadEncaps->decoder->startException();
+ }
+ Ice::SlicedDataPtr endReadException(bool preserve)
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ return _currentReadEncaps->decoder->endException(preserve);
+ }
void startWriteEncaps();
@@ -121,6 +151,7 @@ public:
void endWriteEncaps()
{
assert(_currentWriteEncaps);
+
Container::size_type start = _currentWriteEncaps->start;
Ice::Int sz = static_cast<Ice::Int>(b.size() - start); // Size includes size and version.
Ice::Byte* dest = &(*(b.begin() + start));
@@ -291,12 +322,47 @@ public:
Ice::Int getReadEncapsSize();
Ice::EncodingVersion skipEncaps();
- void startWriteSlice(const std::string&, bool);
- void endWriteSlice();
+ void startWriteSlice(const std::string& typeId, bool last)
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->startSlice(typeId, last);
+ }
+ void endWriteSlice()
+ {
+ assert(_currentWriteEncaps && _currentWriteEncaps->encoder);
+ _currentWriteEncaps->encoder->endSlice();
+ }
+
+ std::string startReadSlice() // Returns type ID of next slice
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ return _currentReadEncaps->decoder->startSlice();
+ }
+ void endReadSlice()
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ _currentReadEncaps->decoder->endSlice();
+ }
+ void skipSlice()
+ {
+ assert(_currentReadEncaps && _currentReadEncaps->decoder);
+ _currentReadEncaps->decoder->skipSlice();
+ }
- std::string startReadSlice(); // Returns type ID of next slice
- void endReadSlice();
- void skipSlice();
+ void readPendingObjects()
+ {
+ if(_currentReadEncaps && _currentReadEncaps->decoder)
+ {
+ _currentReadEncaps->decoder->readPendingObjects();
+ }
+ }
+ void writePendingObjects()
+ {
+ if(_currentWriteEncaps && _currentWriteEncaps->encoder)
+ {
+ _currentWriteEncaps->encoder->writePendingObjects();
+ }
+ }
void writeSize(Ice::Int v) // Inlined for performance reasons.
{
@@ -311,25 +377,21 @@ public:
write(static_cast<Ice::Byte>(v));
}
}
+ void writeSizeSeq(const std::vector<Ice::Int>& v)
+ {
+ writeSize(v.size());
+ for(std::vector<Ice::Int>::const_iterator p = v.begin(); p != v.end(); ++p)
+ {
+ writeSize(*p);
+ }
+ }
void rewriteSize(Ice::Int v, Container::iterator dest)
{
assert(v >= 0);
if(v > 254)
{
*dest++ = Ice::Byte(255);
-#ifdef ICE_BIG_ENDIAN
- const Ice::Byte* src = reinterpret_cast<const Ice::Byte*>(&v) + sizeof(Ice::Int) - 1;
- *dest++ = *src--;
- *dest++ = *src--;
- *dest++ = *src--;
- *dest = *src;
-#else
- const Ice::Byte* src = reinterpret_cast<const Ice::Byte*>(&v);
- *dest++ = *src++;
- *dest++ = *src++;
- *dest++ = *src++;
- *dest = *src;
-#endif
+ write(v, dest);
}
else
{
@@ -354,6 +416,23 @@ public:
v = static_cast<Ice::Int>(static_cast<unsigned char>(byte));
}
}
+ void readSizeSeq(std::vector<Ice::Int>& v)
+ {
+ Ice::Int sz;
+ readSize(sz);
+ if(sz > 0)
+ {
+ v.resize(sz);
+ for(Ice::Int n = 0; n < sz; ++n)
+ {
+ readSize(v[n]);
+ }
+ }
+ else
+ {
+ v.clear();
+ }
+ }
void readAndCheckSeqSize(int, Ice::Int&);
@@ -397,6 +476,7 @@ public:
{
if(i >= b.end())
{
+ assert(false);
throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
}
v = *i++;
@@ -433,7 +513,10 @@ public:
{
Container::size_type pos = b.size();
resize(pos + sizeof(Ice::Int));
- Ice::Byte* dest = &b[pos];
+ write(v, &b[pos]);
+ }
+ void write(Ice::Int v, Container::iterator dest)
+ {
#ifdef ICE_BIG_ENDIAN
const Ice::Byte* src = reinterpret_cast<const Ice::Byte*>(&v) + sizeof(Ice::Int) - 1;
*dest++ = *src--;
@@ -448,6 +531,7 @@ public:
*dest = *src;
#endif
}
+
void write(Ice::Int, int limit);
void read(Ice::Int& v) // Inlined for performance reasons.
@@ -562,14 +646,27 @@ public:
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(const UserExceptionFactoryPtr& = 0);
-
- void writePendingObjects();
- void readPendingObjects();
+ void write(const Ice::ObjectPtr& v)
+ {
+ initWriteEncaps();
+ _currentWriteEncaps->encoder->write(v);
+ }
+ void read(PatchFunc patchFunc, void* patchAddr)
+ {
+ assert(patchFunc && patchAddr);
+ initReadEncaps();
+ _currentReadEncaps->decoder->read(patchFunc, patchAddr);
+ }
+ void write(const Ice::UserException& e)
+ {
+ initWriteEncaps();
+ _currentWriteEncaps->encoder->write(e);
+ }
+ void throwException(const UserExceptionFactoryPtr& factory = 0)
+ {
+ initReadEncaps();
+ _currentReadEncaps->decoder->throwException(factory);
+ }
void sliceObjects(bool);
@@ -624,100 +721,177 @@ private:
//
void* _closure;
- class ICE_API ReadEncaps : private ::IceUtil::noncopyable
+ class ReadEncaps;
+ class WriteEncaps;
+ enum SliceType { NoSlice, ObjectSlice, ExceptionSlice };
+
+ class EncapsDecoder : private ::IceUtil::noncopyable
+ {
+ public:
+ EncapsDecoder(BasicStream* stream, ReadEncaps* encaps, bool sliceObjects) :
+ _stream(stream), _encaps(encaps), _sliceObjects(sliceObjects), _traceSlicing(-1), _sliceType(NoSlice),
+ _typeIdIndex(0)
+ {
+ }
+
+ void read(PatchFunc, void*);
+ void throwException(const UserExceptionFactoryPtr&);
+
+ void startObject();
+ Ice::SlicedDataPtr endObject(bool);
+
+ void startException();
+ Ice::SlicedDataPtr endException(bool);
+
+ const std::string& startSlice();
+ void endSlice();
+ void skipSlice();
+
+ void readPendingObjects();
+
+ private:
+
+ const std::string& readTypeId() const;
+ Ice::ObjectPtr readInstance();
+ void addPatchEntry(Ice::Int, PatchFunc, void*);
+ Ice::SlicedDataPtr readSlicedData();
+
+ BasicStream* _stream;
+ ReadEncaps* _encaps;
+ const bool _sliceObjects;
+
+ int _traceSlicing;
+ const char* _slicingCat;
+
+ // Object/exception attributes
+ SliceType _sliceType;
+ bool _skipFirstSlice;
+ Ice::SliceInfoSeq _slices; // Preserved slices.
+ IndexListList _indirectionTables; // Indirection tables for the preserved slices.
+
+ // Slice attributes
+ Ice::Byte _sliceFlags;
+ Ice::Int _sliceSize;
+ std::string _typeId;
+ IndirectPatchList _indirectPatchList;
+
+ // Encapsulation attributes for object un-marshalling
+ PatchMap _patchMap;
+ IndexToPtrMap _unmarshaledMap;
+ TypeIdReadMap _typeIdMap;
+ Ice::Int _typeIdIndex;
+ };
+
+ class EncapsEncoder : private ::IceUtil::noncopyable
+ {
+ public:
+ EncapsEncoder(BasicStream* stream, WriteEncaps* encaps, Ice::FormatType format) :
+ _stream(stream), _encaps(encaps), _format(format), _sliceType(NoSlice), _objectIdIndex(0), _typeIdIndex(0)
+ {
+ }
+
+ void write(const Ice::ObjectPtr&);
+ void write(const Ice::UserException&);
+
+ void startObject(const Ice::SlicedDataPtr&);
+ void endObject();
+
+ void startException(const Ice::SlicedDataPtr&);
+ void endException();
+
+ void startSlice(const std::string&, bool);
+ void endSlice();
+
+ void writePendingObjects();
+
+ private:
+
+ void writeTypeId(const std::string&);
+ void writeInstance(const Ice::ObjectPtr&, Ice::Int);
+ void writeSlicedData(const Ice::SlicedDataPtr&);
+ Ice::Int registerObject(const Ice::ObjectPtr&);
+
+ BasicStream* _stream;
+ WriteEncaps* _encaps;
+ const Ice::FormatType _format;
+
+ // Object/exception attributes
+ SliceType _sliceType;
+ bool _firstSlice;
+
+ // Slice attributes
+ Ice::Byte _sliceFlags;
+ Container::size_type _writeSlice; // Position of the slice data members
+ Container::size_type _sliceFlagsPos; // Position of the slice flags
+ IndexList _indirectionTable;
+ IndirectionMap _indirectionMap;
+
+ // Encapsulation attributes for object marshalling.
+ Ice::Int _objectIdIndex;
+ PtrToIndexMap _toBeMarshaledMap;
+ PtrToIndexMap _marshaledMap;
+ TypeIdWriteMap _typeIdMap;
+ Ice::Int _typeIdIndex;
+ };
+
+ class ReadEncaps : private ::IceUtil::noncopyable
{
public:
- ReadEncaps() : patchMap(0), unmarshaledMap(0), typeIdMap(0), typeIdIndex(0), indirectPatchList(0), previous(0)
+ ReadEncaps() : decoder(0), previous(0)
{
// Inlined for performance reasons.
}
~ReadEncaps()
{
// Inlined for performance reasons.
- delete patchMap;
- delete unmarshaledMap;
- delete typeIdMap;
- delete indirectPatchList;
+ delete decoder;
}
void reset()
{
// Inlined for performance reasons.
- delete patchMap;
- delete unmarshaledMap;
- delete typeIdMap;
- delete indirectPatchList;
-
- patchMap = 0;
- unmarshaledMap = 0;
- typeIdMap = 0;
- typeIdIndex = 0;
- indirectPatchList = 0;
+ delete decoder;
+ decoder = 0;
+
previous = 0;
}
- void swap(ReadEncaps&);
Container::size_type start;
Ice::Int sz;
Ice::EncodingVersion encoding;
- PatchMap* patchMap;
- IndexToPtrMap* unmarshaledMap;
- TypeIdReadMap* typeIdMap;
- Ice::Int typeIdIndex;
- IndirectPatchList* indirectPatchList;
+ EncapsDecoder* decoder;
ReadEncaps* previous;
};
- class ICE_API WriteEncaps : private ::IceUtil::noncopyable
+ class WriteEncaps : private ::IceUtil::noncopyable
{
+
public:
- WriteEncaps() : writeIndex(0), toBeMarshaledMap(0), marshaledMap(0), typeIdMap(0), typeIdIndex(0),
- indirectionTable(0), indirectionMap(0), previous(0)
+ WriteEncaps() : encoder(0), previous(0)
{
// Inlined for performance reasons.
}
~WriteEncaps()
{
// Inlined for performance reasons.
- delete toBeMarshaledMap;
- delete marshaledMap;
- delete typeIdMap;
- delete indirectionTable;
- delete indirectionMap;
+ delete encoder;
}
void reset()
{
// Inlined for performance reasons.
- delete toBeMarshaledMap;
- delete marshaledMap;
- delete typeIdMap;
- delete indirectionTable;
- delete indirectionMap;
-
- writeIndex = 0;
- toBeMarshaledMap = 0;
- marshaledMap = 0;
- typeIdMap = 0;
- typeIdIndex = 0;
- indirectionTable = 0;
- indirectionMap = 0;
+ delete encoder;
+ encoder = 0;
+
previous = 0;
}
- void swap(WriteEncaps&);
Container::size_type start;
Ice::EncodingVersion encoding;
- Ice::Int writeIndex;
- PtrToIndexMap* toBeMarshaledMap;
- PtrToIndexMap* marshaledMap;
- TypeIdWriteMap* typeIdMap;
- Ice::Int typeIdIndex;
- IndexList* indirectionTable;
- IndirectionMap* indirectionMap;
+ EncapsEncoder* encoder;
WriteEncaps* previous;
};
@@ -739,37 +913,6 @@ private:
ReadEncaps _preAllocatedReadEncaps;
WriteEncaps _preAllocatedWriteEncaps;
- Container::size_type _readSlice;
- Container::size_type _writeSlice;
- Container::size_type _writeFlags;
-
- enum SliceType { NoSlice, ObjectSlice, ExceptionSlice };
- SliceType _sliceType;
-
- bool _firstSlice; // This is true if we are in the initial slice (writing)
-
- bool _needSliceHeader; // This is true if the slice header needs to be read (reading)
- Ice::Byte _sliceFlags; // The flags for the current slice (reading)
- std::string _typeId; // The type ID of the current slice (reading)
-
- Ice::SliceInfoSeq _slices; // Preserved slices.
- IndexListList _indirectionTables; // Indirection tables for the preserved slices.
-
- void readSliceHeader();
- void writeSliceHeader(Ice::Byte, const std::string&);
- void readTypeId(bool, std::string&);
- bool registerTypeId(const std::string&, Ice::Int&);
- Ice::Int registerObject(const Ice::ObjectPtr&);
- void writeInstance(const Ice::ObjectPtr&, Ice::Int);
- void readInstance();
- void patchPointers(Ice::Int, IndexToPtrMap::const_iterator, PatchMap::iterator);
- void addPatchEntry(Ice::Int, PatchFunc, void*);
- void writeSlicedData(const Ice::SlicedDataPtr&);
- Ice::SlicedDataPtr prepareSlicedData();
-
- int _traceSlicing;
- const char* _slicingCat;
-
bool _sliceObjects;
const Container::size_type _messageSizeMax;
@@ -781,8 +924,6 @@ private:
int _startSeq;
int _minSeqSize;
- ObjectList* _objectList;
-
Ice::FormatType _format;
static const Ice::Byte FLAG_HAS_TYPE_ID_STRING;
diff --git a/cpp/include/Ice/Stream.h b/cpp/include/Ice/Stream.h
index adfcabf7991..3d758a8a25d 100644
--- a/cpp/include/Ice/Stream.h
+++ b/cpp/include/Ice/Stream.h
@@ -767,10 +767,10 @@ public:
private:
virtual void __write(::IceInternal::BasicStream*) const;
- virtual void __read(::IceInternal::BasicStream*, bool = true);
+ virtual void __read(::IceInternal::BasicStream*);
virtual void __write(const OutputStreamPtr&) const;
- virtual void __read(const InputStreamPtr&, bool);
+ virtual void __read(const InputStreamPtr&);
};
typedef ::IceInternal::Handle<ObjectWriter> ObjectWriterPtr;
diff --git a/cpp/src/Ice/BasicStream.cpp b/cpp/src/Ice/BasicStream.cpp
index 3d4749c2830..a207e14b88e 100755
--- a/cpp/src/Ice/BasicStream.cpp
+++ b/cpp/src/Ice/BasicStream.cpp
@@ -92,18 +92,12 @@ IceInternal::BasicStream::BasicStream(Instance* instance, const EncodingVersion&
_encoding(encoding),
_currentReadEncaps(0),
_currentWriteEncaps(0),
- _sliceType(NoSlice),
- _firstSlice(false),
- _needSliceHeader(true),
- _sliceFlags(0),
- _traceSlicing(-1),
_sliceObjects(true),
_messageSizeMax(_instance->messageSizeMax()), // Cached for efficiency.
_unlimited(unlimited),
_stringConverter(instance->initializationData().stringConverter),
_wstringConverter(instance->initializationData().wstringConverter),
_startSeq(-1),
- _objectList(0),
_format(_instance->defaultsAndOverrides()->defaultFormat)
{
//
@@ -133,12 +127,6 @@ IceInternal::BasicStream::clear()
_startSeq = -1;
- delete _objectList;
- _objectList = 0;
- _sliceType = NoSlice;
- _firstSlice = false;
- _needSliceHeader = true;
- _sliceFlags = 0;
_sliceObjects = true;
}
@@ -166,98 +154,23 @@ IceInternal::BasicStream::swap(BasicStream& other)
std::swap(_closure, other._closure);
//
- // Swap is never called for BasicStreams that have more than one
- // encaps.
+ // Swap is never called for BasicStreams that have encapsulations being read/write.
//
- assert(!_currentReadEncaps || _currentReadEncaps == &_preAllocatedReadEncaps);
- assert(!_currentWriteEncaps || _currentWriteEncaps == &_preAllocatedWriteEncaps);
- assert(!other._currentReadEncaps || other._currentReadEncaps == &other._preAllocatedReadEncaps);
- assert(!other._currentWriteEncaps || other._currentWriteEncaps == &other._preAllocatedWriteEncaps);
-
- if(_currentReadEncaps || other._currentReadEncaps)
- {
- _preAllocatedReadEncaps.swap(other._preAllocatedReadEncaps);
-
- if(!_currentReadEncaps)
- {
- _currentReadEncaps = &_preAllocatedReadEncaps;
- other._currentReadEncaps = 0;
- }
- else if(!other._currentReadEncaps)
- {
- other._currentReadEncaps = &other._preAllocatedReadEncaps;
- _currentReadEncaps = 0;
- }
- }
-
- if(_currentWriteEncaps || other._currentWriteEncaps)
- {
- _preAllocatedWriteEncaps.swap(other._preAllocatedWriteEncaps);
-
- if(!_currentWriteEncaps)
- {
- _currentWriteEncaps = &_preAllocatedWriteEncaps;
- other._currentWriteEncaps = 0;
- }
- else if(!other._currentWriteEncaps)
- {
- other._currentWriteEncaps = &other._preAllocatedWriteEncaps;
- _currentWriteEncaps = 0;
- }
- }
+ assert(!_currentReadEncaps);
+ assert(!_currentWriteEncaps);
+ assert(!other._currentReadEncaps);
+ assert(!other._currentWriteEncaps);
std::swap(_unlimited, other._unlimited);
std::swap(_startSeq, other._startSeq);
std::swap(_minSeqSize, other._minSeqSize);
- std::swap(_sliceType, other._sliceType);
- std::swap(_firstSlice, other._firstSlice);
- std::swap(_needSliceHeader, other._needSliceHeader);
- std::swap(_sliceFlags, other._sliceFlags);
- std::swap(_typeId, other._typeId);
- _slices.swap(other._slices);
- _indirectionTables.swap(other._indirectionTables);
- std::swap(_objectList, other._objectList);
std::swap(_format, other._format);
}
void
-IceInternal::BasicStream::ReadEncaps::swap(ReadEncaps& other)
-{
- std::swap(start, other.start);
- std::swap(sz, other.sz);
- std::swap(encoding, other.encoding);
-
- std::swap(patchMap, other.patchMap);
- std::swap(unmarshaledMap, other.unmarshaledMap);
- std::swap(typeIdMap, other.typeIdMap);
- std::swap(typeIdIndex, other.typeIdIndex);
-
- std::swap(indirectPatchList, other.indirectPatchList);
-
- std::swap(previous, other.previous);
-}
-
-void
-IceInternal::BasicStream::WriteEncaps::swap(WriteEncaps& other)
-{
- std::swap(start, other.start);
- std::swap(encoding, other.encoding);
-
- std::swap(writeIndex, other.writeIndex);
- std::swap(toBeMarshaledMap, other.toBeMarshaledMap);
- std::swap(marshaledMap, other.marshaledMap);
- std::swap(typeIdMap, other.typeIdMap);
- std::swap(typeIdIndex, other.typeIdIndex);
-
- std::swap(indirectionTable, other.indirectionTable);
- std::swap(indirectionMap, other.indirectionMap);
-
- std::swap(previous, other.previous);
-}
-
-void
IceInternal::BasicStream::format(Ice::FormatType format)
{
+ // TODO: XXX: shouldn't this compare format instead of _format?
if(_format != DefaultFormat)
{
_format = format;
@@ -265,176 +178,6 @@ IceInternal::BasicStream::format(Ice::FormatType format)
}
void
-IceInternal::BasicStream::startWriteObject(const SlicedDataPtr& slicedData)
-{
- assert(_currentWriteEncaps);
- assert(_sliceType == ObjectSlice); // Already set in writeInstance.
-
- //
- // We only remarshal preserved slices if the target encoding is > 1.0 and we are
- // using the sliced format. Otherwise, we ignore the preserved slices, which
- // essentially "slices" the object into the most-derived type known by the sender.
- //
- if(slicedData && _currentWriteEncaps->encoding != Encoding_1_0 && _format == SlicedFormat)
- {
- writeSlicedData(slicedData);
- }
-
- if(_format == CompactFormat)
- {
- _firstSlice = true;
- }
-}
-
-void
-IceInternal::BasicStream::endWriteObject()
-{
- assert(_currentWriteEncaps);
- assert(_sliceType == ObjectSlice);
-
- if(_currentWriteEncaps->encoding == Encoding_1_0)
- {
- //
- // Write the Ice::Object slice.
- //
- startWriteSlice(Object::ice_staticId(), true);
- writeSize(0); // For compatibility with the old AFM.
- endWriteSlice();
- }
-
- _sliceType = NoSlice;
-}
-
-void
-IceInternal::BasicStream::startReadObject()
-{
- assert(_currentReadEncaps);
- assert(_sliceType == ObjectSlice); // Already set in readInstance.
-}
-
-SlicedDataPtr
-IceInternal::BasicStream::endReadObject(bool preserve)
-{
- assert(_currentReadEncaps);
- assert(_sliceType == ObjectSlice);
-
- SlicedDataPtr slicedData;
-
- if(_currentReadEncaps->encoding == Encoding_1_0)
- {
- //
- // Read the Ice::Object slice.
- //
- startReadSlice();
-
- //
- // For compatibility with the old AFM.
- //
- Int sz;
- readSize(sz);
- if(sz != 0)
- {
- throw MarshalException(__FILE__, __LINE__, "invalid Object slice");
- }
-
- endReadSlice();
- }
- else
- {
- //
- // The object should end with the last slice.
- //
- if((_sliceFlags & FLAG_IS_LAST_SLICE) == 0)
- {
- throw MarshalException(__FILE__, __LINE__, "object did not end on last slice");
- }
-
- if(preserve)
- {
- slicedData = prepareSlicedData();
- }
- }
-
- _sliceType = NoSlice;
- _slices.clear();
- _indirectionTables.clear();
- _needSliceHeader = true;
-
- return slicedData;
-}
-
-void
-IceInternal::BasicStream::startWriteException(const SlicedDataPtr& slicedData)
-{
- initWriteEncaps();
-
- assert(_sliceType == NoSlice);
-
- _sliceType = ExceptionSlice;
-
- //
- // We only remarshal preserved slices if the target encoding is > 1.0 and we are
- // using the sliced format. Otherwise, we ignore the preserved slices, which
- // essentially "slices" the object into the most-derived type known by the sender.
- //
- if(slicedData && _currentWriteEncaps->encoding != Encoding_1_0 && _format == SlicedFormat)
- {
- writeSlicedData(slicedData);
- }
-
- if(_format == CompactFormat)
- {
- _firstSlice = true;
- }
-}
-
-void
-IceInternal::BasicStream::endWriteException()
-{
- assert(_sliceType == ExceptionSlice);
-
- _sliceType = NoSlice;
-}
-
-void
-IceInternal::BasicStream::startReadException()
-{
- initReadEncaps();
-
- _sliceType = ExceptionSlice;
-}
-
-SlicedDataPtr
-IceInternal::BasicStream::endReadException(bool preserve)
-{
- assert(_sliceType == ExceptionSlice);
-
- SlicedDataPtr slicedData;
-
- if(_currentReadEncaps->encoding != Encoding_1_0)
- {
- //
- // The object should end with the last slice.
- //
- if((_sliceFlags & FLAG_IS_LAST_SLICE) == 0)
- {
- throw MarshalException(__FILE__, __LINE__, "exception did not end on last slice");
- }
-
- if(preserve)
- {
- slicedData = prepareSlicedData();
- }
- }
-
- _sliceType = NoSlice;
- _slices.clear();
- _indirectionTables.clear();
-
- return slicedData;
-}
-
-void
IceInternal::BasicStream::startWriteEncaps()
{
//
@@ -501,264 +244,6 @@ IceInternal::BasicStream::skipEncaps()
}
void
-IceInternal::BasicStream::startWriteSlice(const string& typeId, bool lastSlice)
-{
- assert(_currentWriteEncaps);
- assert(_sliceType != NoSlice);
-
- if(_currentWriteEncaps->encoding == Encoding_1_0)
- {
- writeSliceHeader(0, typeId);
- write(Int(0)); // Placeholder for the slice length.
- _writeSlice = b.size();
- }
- else
- {
- Byte flags = lastSlice ? FLAG_IS_LAST_SLICE : 0;
-
- if(_format == CompactFormat)
- {
- if(_firstSlice)
- {
- //
- // The first slice in the compact format includes the type ID.
- //
- writeSliceHeader(flags, typeId);
-
- _firstSlice = false;
- }
- else
- {
- //
- // Type IDs are omitted in subsequent slices of the compact format.
- //
- write(flags);
- }
- }
- else
- {
- //
- // The sliced format always includes the type ID and the slice size.
- //
- flags |= FLAG_HAS_SLICE_SIZE;
- writeSliceHeader(flags, typeId);
-
- write(Int(0)); // Placeholder for the slice length.
- _writeSlice = b.size();
- }
- }
-}
-
-void
-IceInternal::BasicStream::endWriteSlice()
-{
- assert(_currentWriteEncaps);
- assert(_sliceType != NoSlice);
-
- if(_currentWriteEncaps->encoding == Encoding_1_0 || _format == SlicedFormat)
- {
- Int sz = static_cast<Int>(b.size() - _writeSlice + sizeof(Int));
- Byte* dest = &(*(b.begin() + _writeSlice - sizeof(Int)));
-#ifdef ICE_BIG_ENDIAN
- const Byte* src = reinterpret_cast<const Byte*>(&sz) + sizeof(Int) - 1;
- *dest++ = *src--;
- *dest++ = *src--;
- *dest++ = *src--;
- *dest = *src;
-#else
- const Byte* src = reinterpret_cast<const Byte*>(&sz);
- *dest++ = *src++;
- *dest++ = *src++;
- *dest++ = *src++;
- *dest = *src;
-#endif
- }
-
- //
- // Only write the indirection table if it contains entries.
- //
- if(!_currentWriteEncaps->indirectionTable->empty())
- {
- assert(_currentWriteEncaps->encoding != Encoding_1_0);
- assert(_format == SlicedFormat);
-
- //
- // Write the indirection table as a sequence<size> to conserve space.
- //
- writeSize(_currentWriteEncaps->indirectionTable->size());
- for(vector<Int>::iterator p = _currentWriteEncaps->indirectionTable->begin();
- p != _currentWriteEncaps->indirectionTable->end(); ++p)
- {
- writeSize(*p);
- }
-
- _currentWriteEncaps->indirectionTable->clear();
- _currentWriteEncaps->indirectionMap->clear();
-
- //
- // Now we need to add FLAG_HAS_INDIRECTION_TABLE to the flag we've already written.
- //
- Byte* dest = &(*(b.begin() + _writeFlags));
- *dest |= FLAG_HAS_INDIRECTION_TABLE;
- }
-}
-
-string
-IceInternal::BasicStream::startReadSlice()
-{
- assert(_currentReadEncaps);
- assert(_sliceType != NoSlice);
-
- if(_needSliceHeader)
- {
- readSliceHeader();
- }
- else
- {
- //
- // The stream has already read the flags and the type ID. We need to read them next time.
- //
- _needSliceHeader = true;
- }
-
- if(_currentReadEncaps->encoding == Encoding_1_0 || (_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
- {
- //
- // Read the size of the slice.
- //
- Int sz;
- read(sz);
- if(sz < 4)
- {
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
- }
- _readSlice = i - b.begin();
- }
-
- return _typeId;
-}
-
-void
-IceInternal::BasicStream::endReadSlice()
-{
- assert(_currentReadEncaps);
- assert(_sliceType != NoSlice);
-
- //
- // Read the indirection table if one is present.
- //
- if(_currentReadEncaps->encoding != Encoding_1_0 && (_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
- {
- //
- // The table is written as a sequence<size> to conserve space.
- //
- IndexList indirectionTable;
- Int size;
- readSize(size);
- for(Int i = 0; i < size; ++i)
- {
- Int index;
- readSize(index);
- indirectionTable.push_back(index);
- }
-
- //
- // Sanity checks.
- //
- if(indirectionTable.empty() && !_currentReadEncaps->indirectPatchList->empty())
- {
- throw MarshalException(__FILE__, __LINE__, "empty indirection table");
- }
- else if(!indirectionTable.empty() && _currentReadEncaps->indirectPatchList->empty())
- {
- throw MarshalException(__FILE__, __LINE__, "no references to indirection table");
- }
-
- //
- // Convert indirect references into direct references.
- //
- for(IndirectPatchList::iterator p = _currentReadEncaps->indirectPatchList->begin();
- p != _currentReadEncaps->indirectPatchList->end(); ++p)
- {
- assert(p->index >= 0);
- if(p->index >= static_cast<Int>(indirectionTable.size()))
- {
- throw MarshalException(__FILE__, __LINE__, "indirection out of range");
- }
- const Int id = indirectionTable[p->index];
- if(id <= 0)
- {
- //
- // Entries in the table must be positive, just like a regular object reference.
- //
- throw MarshalException(__FILE__, __LINE__, "invalid id in object indirection table");
- }
- addPatchEntry(id, p->patchFunc, p->patchAddr);
- }
-
- _currentReadEncaps->indirectPatchList->clear();
- }
-}
-
-void
-IceInternal::BasicStream::skipSlice()
-{
- assert(_currentReadEncaps);
-
- Container::iterator start = i;
-
- if(_currentReadEncaps->encoding == Encoding_1_0 || (_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
- {
- Int sz;
- read(sz);
- if(sz < 4)
- {
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
- }
- i += sz - sizeof(Int);
- if(i > b.end())
- {
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
- }
- }
- else
- {
- throw MarshalException(__FILE__, __LINE__, "compact format prevents slicing");
- }
-
- if(_currentReadEncaps->encoding != Encoding_1_0)
- {
- //
- // Preserve this slice.
- //
- SliceInfoPtr info = new SliceInfo;
- info->typeId = _typeId;
- vector<Byte>(start, i).swap(info->bytes);
- _slices.push_back(info);
-
- _indirectionTables.push_back(IndexList());
-
- if((_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
- {
- //
- // Read the indirection table, which is written as a sequence<size> to conserve space.
- //
- Int size;
- readSize(size);
- if(size > 0)
- {
- for(Int n = 0; n < size; ++n)
- {
- Int index;
- readSize(index);
- _indirectionTables.back().push_back(index);
- }
- }
- }
- }
-}
-
-void
IceInternal::BasicStream::readAndCheckSeqSize(int minSize, Int& sz)
{
readSize(sz);
@@ -2070,10 +1555,55 @@ IceInternal::BasicStream::read(ObjectPrx& v)
}
void
-IceInternal::BasicStream::write(const ObjectPtr& v)
+IceInternal::BasicStream::sliceObjects(bool doSlice)
+{
+ _sliceObjects = doSlice;
+}
+
+void
+IceInternal::BasicStream::throwUnmarshalOutOfBoundsException(const char* file, int line)
+{
+ throw UnmarshalOutOfBoundsException(file, line);
+}
+
+void
+IceInternal::BasicStream::throwEncapsulationException(const char* file, int line)
{
- initWriteEncaps();
+ throw EncapsulationException(file, line);
+}
+void
+IceInternal::BasicStream::initReadEncaps()
+{
+ if(!_currentReadEncaps) // Lazy initialization.
+ {
+ _currentReadEncaps = &_preAllocatedReadEncaps;
+ }
+
+ if(!_currentReadEncaps->decoder) // Lazy initialization.
+ {
+ _currentReadEncaps->decoder = new EncapsDecoder(this, _currentReadEncaps, _sliceObjects);
+ }
+}
+
+void
+IceInternal::BasicStream::initWriteEncaps()
+{
+ if(!_currentWriteEncaps) // Lazy initialization.
+ {
+ _currentWriteEncaps = &_preAllocatedWriteEncaps;
+ _currentWriteEncaps->start = b.size();
+ }
+
+ if(!_currentWriteEncaps->encoder) // Lazy initialization.
+ {
+ _currentWriteEncaps->encoder = new EncapsEncoder(this, _currentWriteEncaps, _format);
+ }
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::write(const ObjectPtr& v)
+{
if(v)
{
//
@@ -2081,51 +1611,42 @@ IceInternal::BasicStream::write(const ObjectPtr& v)
//
Int index = registerObject(v);
- if(_currentWriteEncaps->encoding == Encoding_1_0)
+ if(_encaps->encoding == Encoding_1_0)
{
//
// Object references are encoded as a negative integer in 1.0.
//
- write(-index);
+ _stream->write(-index);
}
- else if(_format == SlicedFormat)
+ else if(_sliceType != NoSlice && _format == SlicedFormat)
{
- if(_sliceType != NoSlice)
+ //
+ // An object reference that appears inside a slice of an
+ // object or exception encoded as a positive non-zero
+ // index into a per-slice indirection table.
+ //
+ // We use _indirectionMap to keep track of the object
+ // references in the current slice; it maps the object
+ // reference to the position in the indirection list. Note
+ // that the position is offset by one (e.g., the first
+ // position = 1).
+ //
+ IndirectionMap::iterator p = _indirectionMap.find(index);
+ if(p == _indirectionMap.end())
{
- //
- // An object reference that appears inside a slice of an object or
- // exception is encoded as a positive non-zero index into a per-slice
- // indirection table. We use _currentWriteEncaps->indirectionMap to keep
- // track of the object references in the current slice; it maps the object
- // reference to the position in the indirection list. Note that the position
- // is offset by one (e.g., the first position = 1).
- //
- IndirectionMap::iterator p = _currentWriteEncaps->indirectionMap->find(index);
- if(p == _currentWriteEncaps->indirectionMap->end())
- {
- _currentWriteEncaps->indirectionTable->push_back(index);
- const Int sz = static_cast<Int>(_currentWriteEncaps->indirectionTable->size()); // Position + 1
- _currentWriteEncaps->indirectionMap->insert(make_pair(index, sz));
- writeSize(sz);
- }
- else
- {
- writeSize(p->second);
- }
+ _indirectionTable.push_back(index);
+ const Int sz = static_cast<Int>(_indirectionTable.size()); // Position + 1
+ _indirectionMap.insert(make_pair(index, sz));
+ _stream->writeSize(sz);
}
else
{
- writeSize(index);
+ _stream->writeSize(p->second);
}
}
else
{
- //
- // No indirection table is used in the compact format, we just encode the
- // index as a size.
- //
- assert(_format == CompactFormat);
- writeSize(index);
+ _stream->writeSize(index);
}
}
else
@@ -2133,34 +1654,340 @@ IceInternal::BasicStream::write(const ObjectPtr& v)
//
// Write nil reference.
//
- if(_currentWriteEncaps->encoding == Encoding_1_0)
+ if(_encaps->encoding == Encoding_1_0)
{
- write(0);
+ _stream->write(0);
}
else
{
- writeSize(0);
+ _stream->writeSize(0);
}
}
}
void
-IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr)
+IceInternal::BasicStream::EncapsEncoder::write(const UserException& v)
+{
+ //
+ // TODO: Eliminate leading usesClasses flag?
+ //
+ const bool usesClasses = v.__usesClasses();
+ _stream->write(usesClasses);
+ v.__write(_stream);
+ if(usesClasses)
+ {
+ writePendingObjects();
+ }
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::startObject(const SlicedDataPtr& data)
{
- assert(patchFunc && patchAddr);
+ _sliceType = ObjectSlice;
+ _firstSlice = true;
+ if(data)
+ {
+ writeSlicedData(data);
+ }
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::endObject()
+{
+ if(_encaps->encoding == Encoding_1_0)
+ {
+ //
+ // Write the Object slice.
+ //
+ startSlice(Object::ice_staticId(), true);
+ _stream->writeSize(0); // For compatibility with the old AFM.
+ endSlice();
+ }
+ _sliceType = NoSlice;
+}
- initReadEncaps();
+void
+IceInternal::BasicStream::EncapsEncoder::startException(const SlicedDataPtr& data)
+{
+ _sliceType = ExceptionSlice;
+ _firstSlice = true;
+ if(data)
+ {
+ writeSlicedData(data);
+ }
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::endException()
+{
+ _sliceType = NoSlice;
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::startSlice(const string& typeId, bool last)
+{
+ assert(_indirectionTable.empty() && _indirectionMap.empty());
+ _sliceFlags = 0;
+ _sliceFlagsPos = _stream->b.size();
+
+ //
+ // Encode the slice size for the old encoding and if using the
+ // sliced format.
+ //
+ if(_encaps->encoding == Encoding_1_0 || _format == SlicedFormat)
+ {
+ _sliceFlags |= FLAG_HAS_SLICE_SIZE;
+ }
+
+ //
+ // This is the last slice.
+ //
+ if(last)
+ {
+ _sliceFlags |= FLAG_IS_LAST_SLICE;
+ }
+
+ //
+ // For object slices, encode the flag and the type ID either as a
+ // string or index. For exception slices, don't encode slice flags
+ // for the old encoding and always encode the type ID a string.
+ //
+ if(_sliceType == ObjectSlice)
+ {
+ _stream->write(Byte(0)); // Placeholder for the slice flags
+
+ //
+ // Encode the type ID (only in the first slice for the compact
+ // encoding).
+ //
+ if(_format == SlicedFormat || _encaps->encoding == Encoding_1_0 || _firstSlice)
+ {
+ //
+ // If the type ID has already been seen, write the index
+ // of the type ID, otherwise allocate a new type ID and
+ // write the string.
+ //
+ TypeIdWriteMap::const_iterator p = _typeIdMap.find(typeId);
+ if(p != _typeIdMap.end())
+ {
+ _sliceFlags |= FLAG_HAS_TYPE_ID_INDEX;
+ _stream->writeSize(p->second);
+ }
+ else
+ {
+ _sliceFlags |= FLAG_HAS_TYPE_ID_STRING;
+ _typeIdMap.insert(make_pair(typeId, ++_typeIdIndex));
+ _stream->write(typeId, false);
+ }
+ }
+ }
+ else
+ {
+ if(_encaps->encoding != Encoding_1_0)
+ {
+ _stream->write(Byte(0)); // Placeholder for the slice flags
+ }
+ _stream->write(typeId, false);
+ }
+
+ if(_sliceFlags & FLAG_HAS_SLICE_SIZE)
+ {
+ _stream->write(Int(0)); // Placeholder for the slice length.
+ }
+
+ _writeSlice = _stream->b.size();
+ _firstSlice = false;
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::endSlice()
+{
+ //
+ // Write the slice length if necessary.
+ //
+ if(_sliceFlags & FLAG_HAS_SLICE_SIZE)
+ {
+ Int sz = static_cast<Int>(_stream->b.size() - _writeSlice + sizeof(Int));
+ Byte* dest = &(*(_stream->b.begin() + _writeSlice - sizeof(Int)));
+ _stream->write(sz, dest);
+ }
+
+ //
+ // Only write the indirection table if it contains entries.
+ //
+ if(!_indirectionTable.empty())
+ {
+ assert(_format == SlicedFormat);
+ _sliceFlags |= FLAG_HAS_INDIRECTION_TABLE;
+
+ //
+ // Write the indirection table as a sequence<size> to conserve space.
+ //
+ _stream->writeSizeSeq(_indirectionTable);
+
+ _indirectionTable.clear();
+ _indirectionMap.clear();
+ }
+
+ //
+ // Finally, update the slice flags.
+ //
+ if(_encaps->encoding == Encoding_1_0)
+ {
+ if(_sliceType == ObjectSlice) // No flags for 1.0 exception slices.
+ {
+ Byte* dest = &(*(_stream->b.begin() + _sliceFlagsPos));
+ *dest = static_cast<Byte>(_sliceFlags & FLAG_HAS_TYPE_ID_INDEX ? true : false);
+ }
+ }
+ else
+ {
+ Byte* dest = &(*(_stream->b.begin() + _sliceFlagsPos));
+ *dest = _sliceFlags;
+ }
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::writePendingObjects()
+{
+ while(!_toBeMarshaledMap.empty())
+ {
+ //
+ // Consider the to be marshalled objects as marshalled now,
+ // this is necessary to avoid adding again the "to be
+ // marshalled objects" into _toBeMarshaledMap while writing
+ // objects.
+ //
+ _marshaledMap.insert(_toBeMarshaledMap.begin(), _toBeMarshaledMap.end());
+
+ PtrToIndexMap savedMap;
+ savedMap.swap(_toBeMarshaledMap);
+ _stream->writeSize(static_cast<Int>(savedMap.size()));
+ for(PtrToIndexMap::iterator p = savedMap.begin(); p != savedMap.end(); ++p)
+ {
+ //
+ // Add an instance from the old to-be-marshaled map to
+ // the marshaled map and then ask the instance to
+ // marshal itself. Any new class instances that are
+ // triggered by the classes marshaled are added to
+ // toBeMarshaledMap.
+ //
+ writeInstance(p->first, p->second);
+ }
+ }
+ _stream->writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+}
+void
+IceInternal::BasicStream::EncapsEncoder::writeInstance(const ObjectPtr& v, Int index)
+{
+ if(_encaps->encoding == Encoding_1_0)
+ {
+ _stream->write(index);
+ }
+ else
+ {
+ _stream->writeSize(index);
+ }
+
+ try
+ {
+ v->ice_preMarshal();
+ }
+ catch(const std::exception& ex)
+ {
+ Warning out(_stream->instance()->initializationData().logger);
+ out << "std::exception raised by ice_preMarshal:\n" << ex;
+ }
+ catch(...)
+ {
+ Warning out(_stream->instance()->initializationData().logger);
+ out << "unknown exception raised by ice_preMarshal";
+ }
+
+ v->__write(_stream);
+}
+
+void
+IceInternal::BasicStream::EncapsEncoder::writeSlicedData(const SlicedDataPtr& slicedData)
+{
+ assert(slicedData);
+
+ //
+ // We only remarshal preserved slices if the target encoding is > 1.0 and we are
+ // using the sliced format. Otherwise, we ignore the preserved slices, which
+ // essentially "slices" the object into the most-derived type known by the sender.
+ //
+ if(_encaps->encoding == Encoding_1_0 || _format != SlicedFormat)
+ {
+ return;
+ }
+
+ for(SliceInfoSeq::const_iterator p = slicedData->slices.begin(); p != slicedData->slices.end(); ++p)
+ {
+ startSlice((*p)->typeId, false); // last = false, sliced data never contains the last slice.
+
+ //
+ // Write the bytes associated with this slice.
+ //
+ _stream->writeBlob((*p)->bytes);
+
+ //
+ // Assemble and write the indirection table. The table must have the same order
+ // as the list of objects.
+ //
+ for(vector<ObjectPtr>::const_iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q)
+ {
+ _indirectionTable.push_back(registerObject(*q));
+ }
+
+ endSlice();
+ }
+}
+
+Int
+IceInternal::BasicStream::EncapsEncoder::registerObject(const ObjectPtr& v)
+{
+ assert(v);
+
+ //
+ // Look for this instance in the to-be-marshaled map.
+ //
+ PtrToIndexMap::const_iterator p = _toBeMarshaledMap.find(v);
+ if(p != _toBeMarshaledMap.end())
+ {
+ return p->second;
+ }
+
+ //
+ // Didn't find it, try the marshaled map next.
+ //
+ PtrToIndexMap::const_iterator q = _marshaledMap.find(v);
+ if(q != _marshaledMap.end())
+ {
+ return q->second;
+ }
+
+ //
+ // We haven't seen this instance previously, create a new
+ // index, and insert it into the to-be-marshaled map.
+ //
+ _toBeMarshaledMap.insert(make_pair(v, ++_objectIdIndex));
+ return _objectIdIndex;
+}
+
+void
+IceInternal::BasicStream::EncapsDecoder::read(PatchFunc patchFunc, void* patchAddr)
+{
ObjectPtr v;
Int index;
-
- if(_currentReadEncaps->encoding == Encoding_1_0)
+ if(_encaps->encoding == Encoding_1_0)
{
//
// Object references are encoded as a negative integer in 1.0.
//
- read(index);
+ _stream->read(index);
if(index > 0)
{
throw MarshalException(__FILE__, __LINE__, "invalid object id");
@@ -2172,7 +1999,7 @@ IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr)
//
// Later versions use a size.
//
- readSize(index);
+ _stream->readSize(index);
if(index < 0)
{
throw MarshalException(__FILE__, __LINE__, "invalid object id");
@@ -2188,8 +2015,7 @@ IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr)
ObjectPtr nil;
patchFunc(patchAddr, nil);
}
- else if(_currentReadEncaps->encoding != Encoding_1_0 && _sliceType != NoSlice &&
- (_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
+ else if(_sliceType != NoSlice && _sliceFlags & FLAG_HAS_INDIRECTION_TABLE)
{
//
// Maintain a list of indirect references. Note that the indirect index
@@ -2200,7 +2026,7 @@ IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr)
e.index = index - 1;
e.patchFunc = patchFunc;
e.patchAddr = patchAddr;
- _currentReadEncaps->indirectPatchList->push_back(e);
+ _indirectPatchList.push_back(e);
}
else
{
@@ -2209,53 +2035,36 @@ IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr)
}
void
-IceInternal::BasicStream::write(const UserException& v)
-{
- initWriteEncaps();
-
- //
- // TODO: Eliminate leading usesClasses flag?
- //
- const bool usesClasses = v.__usesClasses();
- write(usesClasses);
- v.__write(this);
- if(usesClasses)
- {
- writePendingObjects();
- }
-}
-
-void
-IceInternal::BasicStream::throwException(const UserExceptionFactoryPtr& factory)
+IceInternal::BasicStream::EncapsDecoder::throwException(const UserExceptionFactoryPtr& factory)
{
- initReadEncaps();
+ assert(_sliceType == NoSlice);
+ // TODO: Get rid of this for 1.1?
bool usesClasses;
- read(usesClasses);
+ _stream->read(usesClasses);
_sliceType = ExceptionSlice;
-
- assert(_needSliceHeader);
- readSliceHeader();
+ _skipFirstSlice = false;
//
- // Set a flag to indicate we've already read the first slice header.
+ // Read the first slice header.
//
- _needSliceHeader = false;
-
- const string origId = _typeId;
+ startSlice();
+ const string mostDerivedId = _typeId;
UserExceptionFactoryPtr exceptionFactory = factory;
-
- for(;;)
+ while(true)
{
+ //
+ // Look for a statically-generated factory for this ID.
+ //
if(!exceptionFactory)
{
- //
- // Look for a statically-generated factory for this ID.
- //
exceptionFactory = factoryTable->getExceptionFactory(_typeId);
}
+ //
+ // We found a factory, we get out of this loop.
+ //
if(exceptionFactory)
{
//
@@ -2265,486 +2074,348 @@ IceInternal::BasicStream::throwException(const UserExceptionFactoryPtr& factory)
//
try
{
+ assert(exceptionFactory);
exceptionFactory->createAndThrow(_typeId);
}
catch(UserException& ex)
{
- ex.__read(this);
+ ex.__read(_stream);
ex.__usesClasses(usesClasses);
-
+
if(usesClasses)
{
readPendingObjects();
}
-
+
ex.ice_throw();
-
+
// Never reached.
}
}
//
- // If we reach here, either we didn't find a factory, or the factory
- // didn't recognize the type. We slice the exception if possible.
- //
-
- //
// Performance sensitive, so we use lazy initialization
// for tracing.
//
if(_traceSlicing == -1)
{
- _traceSlicing = _instance->traceLevels()->slicing;
- _slicingCat = _instance->traceLevels()->slicingCat;
+ _traceSlicing = _stream->instance()->traceLevels()->slicing;
+ _slicingCat = _stream->instance()->traceLevels()->slicingCat;
}
if(_traceSlicing > 0)
{
- traceSlicing("exception", _typeId, _slicingCat, _instance->initializationData().logger);
+ traceSlicing("exception", _typeId, _slicingCat, _stream->instance()->initializationData().logger);
}
- skipSlice(); // Slice off what we don't understand.
+ if(_sliceFlags & FLAG_IS_LAST_SLICE)
+ {
+ // TODO: Consider adding a new exception, such as NoExceptionFactory?
+ throw UnmarshalOutOfBoundsException(__FILE__, __LINE__, "unknown exception type `" + mostDerivedId + "'");
+ }
- //
- // An oversight in the 1.0 encoding means there is no marker to indicate
- // the last slice of an exception. As a result, we just try to read the
- // next type ID, which raises UnmarshalOutOfBoundsException when the
- // input buffer underflows.
- //
- if(_currentReadEncaps->encoding == Encoding_1_0)
+ skipSlice(); // Slice off what we don't understand.
+ try
{
- try
- {
- readSliceHeader();
- }
- catch(UnmarshalOutOfBoundsException& ex)
- {
- //
- // Set the reason member to a more helpful message.
- //
- ex.reason = "unknown exception type `" + origId + "'";
- throw;
- }
+ startSlice();
}
- else
+ catch(UnmarshalOutOfBoundsException& ex)
{
//
- // Throw an exception if the flag indicates this is the last slice.
+ // An oversight in the 1.0 encoding means there is no marker to indicate
+ // the last slice of an exception. As a result, we just try to read the
+ // next type ID, which raises UnmarshalOutOfBoundsException when the
+ // input buffer underflows.
//
- if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
+ if(_encaps->encoding == Encoding_1_0)
{
- // TODO: Consider adding a new exception, such as NoExceptionFactory?
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__, "unknown exception type `" + origId + "'");
- }
- else
- {
- readSliceHeader();
+ // Set the reason member to a more helpful message.
+ ex.reason = "unknown exception type `" + mostDerivedId + "'";
}
+ throw;
}
}
-
- //
- // The only way out of the loop above is to find an exception for
- // which the receiver has a factory. If this does not happen,
- // sender and receiver disagree about the Slice definitions they
- // use. In that case, the receiver will eventually fail to read
- // another type ID and throw a MarshalException.
- //
}
-void
-IceInternal::BasicStream::writePendingObjects()
+void
+IceInternal::BasicStream::EncapsDecoder::startObject()
{
- if(_currentWriteEncaps && _currentWriteEncaps->toBeMarshaledMap)
- {
- while(_currentWriteEncaps->toBeMarshaledMap->size())
- {
- PtrToIndexMap savedMap = *_currentWriteEncaps->toBeMarshaledMap;
- writeSize(static_cast<Int>(savedMap.size()));
- for(PtrToIndexMap::iterator p = savedMap.begin(); p != savedMap.end(); ++p)
- {
- //
- // Add an instance from the old to-be-marshaled map to
- // the marshaled map and then ask the instance to
- // marshal itself. Any new class instances that are
- // triggered by the classes marshaled are added to
- // toBeMarshaledMap.
- //
- _currentWriteEncaps->marshaledMap->insert(*p);
- writeInstance(p->first, p->second);
- }
-
- //
- // We have marshaled all the instances for this pass,
- // substract what we have marshaled from the
- // toBeMarshaledMap.
- //
- PtrToIndexMap newMap;
- set_difference(_currentWriteEncaps->toBeMarshaledMap->begin(),
- _currentWriteEncaps->toBeMarshaledMap->end(),
- savedMap.begin(), savedMap.end(),
- insert_iterator<PtrToIndexMap>(newMap, newMap.begin()));
- *_currentWriteEncaps->toBeMarshaledMap = newMap;
- }
- }
- writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+ assert(_sliceType == ObjectSlice);
+ _skipFirstSlice = true;
}
-void
-IceInternal::BasicStream::readPendingObjects()
+SlicedDataPtr
+IceInternal::BasicStream::EncapsDecoder::endObject(bool preserve)
{
- Int num;
- do
- {
- readSize(num);
- for(Int k = num; k > 0; --k)
- {
- readInstance();
- }
- }
- while(num);
-
- if(_currentReadEncaps && _currentReadEncaps->patchMap && _currentReadEncaps->patchMap->size() != 0)
+ if(_encaps->encoding == Encoding_1_0)
{
//
- // If any entries remain in the patch map, the sender has sent an index for an object, but failed
- // to supply the object.
+ // Read the Ice::Object slice.
//
- throw MarshalException(__FILE__, __LINE__, "index for class received, but no instance");
- }
+ startSlice();
- //
- // Iterate over the object list and invoke ice_postUnmarshal on
- // each object. We must do this after all objects have been
- // unmarshaled in order to ensure that any object data members
- // have been properly patched.
- //
- if(_objectList)
- {
- for(ObjectList::iterator p = _objectList->begin(); p != _objectList->end(); ++p)
+ //
+ // For compatibility with the old AFM.
+ //
+ Int sz;
+ _stream->readSize(sz);
+ if(sz != 0)
{
- try
- {
- (*p)->ice_postUnmarshal();
- }
- catch(const std::exception& ex)
- {
- Warning out(_instance->initializationData().logger);
- out << "std::exception raised by ice_postUnmarshal:\n" << ex;
- }
- catch(...)
- {
- Warning out(_instance->initializationData().logger);
- out << "unknown exception raised by ice_postUnmarshal";
- }
+ throw MarshalException(__FILE__, __LINE__, "invalid Object slice");
}
- }
-}
-void
-IceInternal::BasicStream::sliceObjects(bool doSlice)
-{
- _sliceObjects = doSlice;
-}
+ endSlice();
+ }
-void
-IceInternal::BasicStream::throwUnmarshalOutOfBoundsException(const char* file, int line)
-{
- throw UnmarshalOutOfBoundsException(file, line);
+ _sliceType = NoSlice;
+ SlicedDataPtr slicedData;
+ if(preserve)
+ {
+ slicedData = readSlicedData();
+ }
+ _slices.clear();
+ _indirectionTables.clear();
+ return slicedData;
}
-void
-IceInternal::BasicStream::throwEncapsulationException(const char* file, int line)
+void
+IceInternal::BasicStream::EncapsDecoder::startException()
{
- throw EncapsulationException(file, line);
+ assert(_sliceType == ExceptionSlice);
+ _skipFirstSlice = true;
}
-void
-IceInternal::BasicStream::initReadEncaps()
+SlicedDataPtr
+IceInternal::BasicStream::EncapsDecoder::endException(bool preserve)
{
- if(!_currentReadEncaps) // Lazy initialization.
- {
- _currentReadEncaps = &_preAllocatedReadEncaps;
- }
-
- if(!_currentReadEncaps->patchMap) // Lazy initialization.
+ _sliceType = NoSlice;
+ SlicedDataPtr slicedData;
+ if(preserve)
{
- _currentReadEncaps->patchMap = new PatchMap;
- _currentReadEncaps->unmarshaledMap = new IndexToPtrMap;
- _currentReadEncaps->typeIdMap = new TypeIdReadMap;
- _currentReadEncaps->indirectPatchList = new IndirectPatchList;
+ slicedData = readSlicedData();
}
+ _slices.clear();
+ _indirectionTables.clear();
+ return slicedData;
}
-void
-IceInternal::BasicStream::initWriteEncaps()
+const string&
+IceInternal::BasicStream::EncapsDecoder::startSlice()
{
- if(!_currentWriteEncaps) // Lazy initialization.
- {
- _currentWriteEncaps = &_preAllocatedWriteEncaps;
- _currentWriteEncaps->start = b.size();
- }
-
- if(!_currentWriteEncaps->toBeMarshaledMap) // Lazy initialization.
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(_skipFirstSlice)
{
- _currentWriteEncaps->toBeMarshaledMap = new PtrToIndexMap;
- _currentWriteEncaps->marshaledMap = new PtrToIndexMap;
- _currentWriteEncaps->typeIdMap = new TypeIdWriteMap;
- _currentWriteEncaps->indirectionTable = new IndexList;
- _currentWriteEncaps->indirectionMap = new IndirectionMap;
+ _skipFirstSlice = false;
+ return _typeId;
}
-}
-
-void
-IceInternal::BasicStream::readSliceHeader()
-{
- assert(_currentReadEncaps);
- assert(_sliceType != NoSlice);
- if(_currentReadEncaps->encoding == Encoding_1_0)
+ //
+ // Read the slice flags. For the 1.0 encoding there's no flag but
+ // just a boolean for object slices. The boolean indicates whether
+ // or not the type ID is encoded as a string or as an index.
+ //
+ if(_encaps->encoding == Encoding_1_0)
{
- _sliceFlags = 0;
- if(_sliceType == ObjectSlice)
+ _sliceFlags = FLAG_HAS_SLICE_SIZE;
+ if(_sliceType == ObjectSlice) // For exceptions, the type ID is always encoded as a string
{
bool isIndex;
- read(isIndex);
- readTypeId(isIndex, _typeId);
- }
- else
- {
- read(_typeId, false); // Read a regular string (not a type ID) for an exception slice.
+ _stream->read(isIndex);
+ _sliceFlags |= isIndex ? FLAG_HAS_TYPE_ID_INDEX : FLAG_HAS_TYPE_ID_STRING;
}
}
else
{
- //
- // Read the slice encoding flags.
- //
- read(_sliceFlags);
+ _stream->read(_sliceFlags);
+ }
- //
- // Read the type ID if one is present.
- //
- if((_sliceFlags & FLAG_HAS_TYPE_ID_STRING) != 0)
+ //
+ // Read the type ID, for object slices the type ID is encoded as a
+ // string or as an index, for exceptions it's always encoded as a
+ // string.
+ //
+ if(_sliceType == ObjectSlice)
+ {
+ if(_sliceFlags & FLAG_HAS_TYPE_ID_INDEX)
{
- if(_sliceType == ObjectSlice)
- {
- readTypeId(false, _typeId);
- }
- else
+ Int index;
+ _stream->readSize(index);
+ TypeIdReadMap::const_iterator k = _typeIdMap.find(index);
+ if(k == _typeIdMap.end())
{
- read(_typeId, false); // Read a regular string (not a type ID) for an exception slice.
+ throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
}
+ _typeId = k->second;
}
- else if((_sliceFlags & FLAG_HAS_TYPE_ID_INDEX) != 0)
+ else if(_sliceFlags & FLAG_HAS_TYPE_ID_STRING)
{
- if(_sliceType == ObjectSlice)
- {
- readTypeId(true, _typeId);
- }
- else
- {
- throw MarshalException(__FILE__, __LINE__, "type id index received for exception");
- }
+ _stream->read(_typeId, false);
+ _typeIdMap.insert(make_pair(++_typeIdIndex, _typeId));
}
else
{
- //
- // No type ID in slice.
- //
+ // Only the most derived slice encodes the type ID for the
+ // compact format.
_typeId.clear();
}
+ }
+ else
+ {
+ _stream->read(_typeId, false);
+ }
+
+ //
+ // Read the slice size if necessary.
+ //
+ if(_sliceFlags & FLAG_HAS_SLICE_SIZE)
+ {
+ _stream->read(_sliceSize);
+ if(_sliceSize < 4)
+ {
+ throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
+ }
}
+ else
+ {
+ _sliceSize = 0;
+ }
+
+ //
+ // Reset the indirect patch list for this new slice.
+ //
+ _indirectPatchList.clear();
+ return _typeId;
}
void
-IceInternal::BasicStream::writeSliceHeader(Byte flags, const string& typeId)
+IceInternal::BasicStream::EncapsDecoder::endSlice()
{
- assert(_currentWriteEncaps);
- assert(_sliceType != NoSlice);
-
- if(_sliceType == ObjectSlice)
+ //
+ // Read the indirection table if one is present and transform the
+ // indirect patch list into patch entries with direct references.
+ //
+ if(_sliceFlags & FLAG_HAS_INDIRECTION_TABLE)
{
- Int typeIdIndex;
- const bool writeIndex = registerTypeId(typeId, typeIdIndex);
+ //
+ // The table is written as a sequence<size> to conserve space.
+ //
+ IndexList indirectionTable;
+ _stream->readSizeSeq(indirectionTable);
- if(_currentWriteEncaps->encoding == Encoding_1_0)
+ //
+ // Sanity checks.
+ //
+ if(indirectionTable.empty() && !_indirectPatchList.empty())
{
- write(writeIndex);
+ throw MarshalException(__FILE__, __LINE__, "empty indirection table");
}
- else
+ else if(!indirectionTable.empty() && _indirectPatchList.empty())
{
- //
- // Save the position of the flags byte; we'll need this in endWriteSlice().
- //
- _writeFlags = b.size();
+ throw MarshalException(__FILE__, __LINE__, "no references to indirection table");
+ }
- if(writeIndex)
+ //
+ // Convert indirect references into direct references.
+ //
+ for(IndirectPatchList::iterator p = _indirectPatchList.begin(); p != _indirectPatchList.end(); ++p)
+ {
+ assert(p->index >= 0);
+ if(p->index >= static_cast<Int>(indirectionTable.size()))
{
- flags |= FLAG_HAS_TYPE_ID_INDEX;
+ throw MarshalException(__FILE__, __LINE__, "indirection out of range");
}
- else
+ const Int id = indirectionTable[p->index];
+ if(id <= 0)
{
- flags |= FLAG_HAS_TYPE_ID_STRING;
+ //
+ // Entries in the table must be positive, just like a regular object reference.
+ //
+ throw MarshalException(__FILE__, __LINE__, "invalid id in object indirection table");
}
- write(flags);
- }
-
- if(writeIndex)
- {
- writeSize(typeIdIndex);
- }
- else
- {
- write(typeId, false);
- }
- }
- else
- {
- if(_currentWriteEncaps->encoding != Encoding_1_0)
- {
- //
- // Save the position of the flags byte; we'll need this in endWriteSlice().
- //
- _writeFlags = b.size();
-
- flags |= FLAG_HAS_TYPE_ID_STRING;
- write(flags);
+ addPatchEntry(id, p->patchFunc, p->patchAddr);
}
-
- write(typeId, false); // Write a regular string (not a type ID) for an exception slice.
}
-}
+}
void
-IceInternal::BasicStream::readTypeId(bool isIndex, string& id)
+IceInternal::BasicStream::EncapsDecoder::readPendingObjects()
{
- assert(_currentReadEncaps && _currentReadEncaps->typeIdMap);
-
- if(isIndex)
+ Int num;
+ ObjectList objectList;
+ do
{
- Int index;
- readSize(index);
- TypeIdReadMap::const_iterator k = _currentReadEncaps->typeIdMap->find(index);
- if(k == _currentReadEncaps->typeIdMap->end())
+ _stream->readSize(num);
+ for(Int k = num; k > 0; --k)
{
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
+ objectList.push_back(readInstance());
}
- id = k->second;
- }
- else
- {
- read(id, false);
- _currentReadEncaps->typeIdMap->insert(make_pair(++_currentReadEncaps->typeIdIndex, id));
}
-}
-
-bool
-IceInternal::BasicStream::registerTypeId(const string& id, Int& index)
-{
- assert(_currentWriteEncaps);
-
- //
- // Upon return, the index argument holds the index assigned to this
- // type ID.
- //
- // If the type ID has already been seen, the function returns true
- // and the caller must write the index. Otherwise, the function
- // returns false and the caller must write the string.
- //
+ while(num);
- TypeIdWriteMap::const_iterator p = _currentWriteEncaps->typeIdMap->find(id);
- if(p != _currentWriteEncaps->typeIdMap->end())
+ if(!_patchMap.empty())
{
- index = p->second;
- return true;
- }
- else
- {
- index = ++_currentWriteEncaps->typeIdIndex;
- _currentWriteEncaps->typeIdMap->insert(make_pair(id, index));
- return false;
+ //
+ // If any entries remain in the patch map, the sender has sent an index for an object, but failed
+ // to supply the object.
+ //
+ throw MarshalException(__FILE__, __LINE__, "index for class received, but no instance");
}
-}
-
-Int
-IceInternal::BasicStream::registerObject(const ObjectPtr& v)
-{
- assert(v);
-
- initWriteEncaps();
//
- // Look for this instance in the to-be-marshaled map.
+ // Iterate over the object list and invoke ice_postUnmarshal on
+ // each object. We must do this after all objects have been
+ // unmarshaled in order to ensure that any object data members
+ // have been properly patched.
//
- PtrToIndexMap::iterator p = _currentWriteEncaps->toBeMarshaledMap->find(v);
- if(p == _currentWriteEncaps->toBeMarshaledMap->end())
+ for(ObjectList::iterator p = objectList.begin(); p != objectList.end(); ++p)
{
- //
- // Didn't find it, try the marshaled map next.
- //
- PtrToIndexMap::iterator q = _currentWriteEncaps->marshaledMap->find(v);
- if(q == _currentWriteEncaps->marshaledMap->end())
+ try
{
- //
- // We haven't seen this instance previously, create a
- // new index, and insert it into the to-be-marshaled
- // map.
- //
- q = _currentWriteEncaps->toBeMarshaledMap->insert(
- _currentWriteEncaps->toBeMarshaledMap->end(),
- pair<const ObjectPtr, Int>(v, ++_currentWriteEncaps->writeIndex));
+ (*p)->ice_postUnmarshal();
+ }
+ catch(const std::exception& ex)
+ {
+ Warning out(_stream->instance()->initializationData().logger);
+ out << "std::exception raised by ice_postUnmarshal:\n" << ex;
+ }
+ catch(...)
+ {
+ Warning out(_stream->instance()->initializationData().logger);
+ out << "unknown exception raised by ice_postUnmarshal";
}
- p = q;
}
-
- //
- // Return the index for the instance.
- //
- return p->second;
}
-void
-IceInternal::BasicStream::readInstance()
+ObjectPtr
+IceInternal::BasicStream::EncapsDecoder::readInstance()
{
- assert(_currentReadEncaps);
-
- ObjectPtr v;
-
Int index;
- if(_currentReadEncaps->encoding == Encoding_1_0)
+ if(_encaps->encoding == Encoding_1_0)
{
- //
- // Object id is encoded as an int in 1.0.
- //
- read(index);
+ _stream->read(index);
}
else
{
- //
- // Later versions use a size.
- //
- readSize(index);
+ _stream->readSize(index);
}
+ ObjectPtr v;
if(index <= 0)
{
throw MarshalException(__FILE__, __LINE__, "invalid object id");
}
- //
- // We are about to start reading the slices of an object.
- //
_sliceType = ObjectSlice;
-
- assert(_needSliceHeader);
- readSliceHeader();
+ _skipFirstSlice = false;
//
- // Set a flag to indicate we've already read the first slice header.
+ // Read the first slice header.
//
- _needSliceHeader = false;
-
- string mostDerivedId = _typeId;
+ startSlice();
+ const string mostDerivedId = _typeId;
+ ObjectFactoryManagerPtr servantFactoryManager = _stream->instance()->servantFactoryManager();
while(true)
{
//
@@ -2761,7 +2432,7 @@ IceInternal::BasicStream::readInstance()
//
// Try to find a factory registered for the specific type.
//
- ObjectFactoryPtr userFactory = _instance->servantFactoryManager()->find(_typeId);
+ ObjectFactoryPtr userFactory = servantFactoryManager->find(_typeId);
if(userFactory)
{
v = userFactory->create(_typeId);
@@ -2773,7 +2444,7 @@ IceInternal::BasicStream::readInstance()
//
if(!v)
{
- userFactory = _instance->servantFactoryManager()->find("");
+ userFactory = servantFactoryManager->find("");
if(userFactory)
{
v = userFactory->create(_typeId);
@@ -2794,178 +2465,111 @@ IceInternal::BasicStream::readInstance()
}
}
- if(!v)
+ //
+ // We found a factory, we get out of this loop.
+ //
+ if(v)
{
- //
- // If object slicing is disabled, or if the flags indicate that this is the
- // last slice (for encodings >= 1.1), we raise NoObjectFactoryException.
- //
- if(!_sliceObjects)
- {
- throw NoObjectFactoryException(__FILE__, __LINE__, "object slicing is disabled", _typeId);
- }
- else if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
- {
- throw NoObjectFactoryException(__FILE__, __LINE__, "", _typeId);
- }
- else
- {
- //
- // Performance sensitive, so we use lazy initialization for tracing.
- //
- if(_traceSlicing == -1)
- {
- _traceSlicing = _instance->traceLevels()->slicing;
- _slicingCat = _instance->traceLevels()->slicingCat;
- }
- if(_traceSlicing > 0)
- {
- traceSlicing("class", _typeId, _slicingCat, _instance->initializationData().logger);
- }
-
- skipSlice(); // Slice off what we don't understand.
- readSliceHeader(); // Read ID for next iteration.
- continue;
- }
+ break;
}
- IndexToPtrMap::const_iterator unmarshaledPos =
- _currentReadEncaps->unmarshaledMap->insert(make_pair(index, v)).first;
-
//
- // Record each object instance so that readPendingObjects can
- // invoke ice_postUnmarshal after all objects have been
- // unmarshaled.
+ // If object slicing is disabled, or if the flags indicate that this is the
+ // last slice (for encodings >= 1.1), we raise NoObjectFactoryException.
//
- if(!_objectList)
+ if(!_sliceObjects)
+ {
+ throw NoObjectFactoryException(__FILE__, __LINE__, "object slicing is disabled", _typeId);
+ }
+ else if(_sliceFlags & FLAG_IS_LAST_SLICE)
{
- _objectList = new ObjectList;
+ throw NoObjectFactoryException(__FILE__, __LINE__, "", _typeId);
}
- _objectList->push_back(v);
- v->__read(this);
- patchPointers(index, unmarshaledPos, _currentReadEncaps->patchMap->end());
- return;
+ //
+ // Performance sensitive, so we use lazy initialization for tracing.
+ //
+ if(_traceSlicing == -1)
+ {
+ _traceSlicing = _stream->instance()->traceLevels()->slicing;
+ _slicingCat = _stream->instance()->traceLevels()->slicingCat;
+ }
+ if(_traceSlicing > 0)
+ {
+ traceSlicing("class", _typeId, _slicingCat, _stream->instance()->initializationData().logger);
+ }
+
+ skipSlice(); // Slice off what we don't understand.
+ startSlice(); // Read next Slice header for next iteration.
}
+
+ //
+ // Add the object to the map of un-marshalled objects, this must
+ // be done before reading the objects (for circular references).
+ //
+ _unmarshaledMap.insert(make_pair(index, v));
//
- // We can't possibly end up here: at the very least, we should have
- // detected the last slice, or client and server were compiled with
- // mismatched Slice definitions.
+ // Read the object.
//
- throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
-}
-
-void
-IceInternal::BasicStream::writeInstance(const ObjectPtr& v, Int index)
-{
- assert(_currentWriteEncaps);
-
- _sliceType = ObjectSlice;
-
- if(_currentWriteEncaps->encoding == Encoding_1_0)
- {
- write(index);
- }
- else
- {
- writeSize(index);
- }
-
- try
- {
- v->ice_preMarshal();
- }
- catch(const std::exception& ex)
- {
- Warning out(_instance->initializationData().logger);
- out << "std::exception raised by ice_preMarshal:\n" << ex;
- }
- catch(...)
- {
- Warning out(_instance->initializationData().logger);
- out << "unknown exception raised by ice_preMarshal";
- }
- v->__write(this);
-}
+ v->__read(_stream);
-void
-IceInternal::BasicStream::patchPointers(Int index, IndexToPtrMap::const_iterator unmarshaledPos,
- PatchMap::iterator patchPos)
-{
//
- // Called whenever we have unmarshaled a new instance. The index
- // is the index of the instance. UnmarshaledPos denotes the
- // instance just unmarshaled and patchPos denotes the patch map
- // entry for the index just unmarshaled. (Exactly one of these two
- // iterators must be end().) Patch any pointers in the patch map
- // with the new address.
+ // Patch all instances now that the object is un-marshalled.
//
- assert( (unmarshaledPos != _currentReadEncaps->unmarshaledMap->end()
- && patchPos == _currentReadEncaps->patchMap->end())
- || (unmarshaledPos == _currentReadEncaps->unmarshaledMap->end()
- && patchPos != _currentReadEncaps->patchMap->end())
- );
-
- if(unmarshaledPos != _currentReadEncaps->unmarshaledMap->end())
+ PatchMap::iterator patchPos = _patchMap.find(index);
+ if(patchPos != _patchMap.end())
{
+ assert(patchPos->second.size() > 0);
+
//
- // We have just unmarshaled an instance -- check if something
- // needs patching for that instance.
+ // Patch all pointers that refer to the instance.
//
- patchPos = _currentReadEncaps->patchMap->find(index);
- if(patchPos == _currentReadEncaps->patchMap->end())
+ for(PatchList::iterator k = patchPos->second.begin(); k != patchPos->second.end(); ++k)
{
- return; // We don't have anything to patch for the instance just unmarshaled.
+ (*k->patchFunc)(k->patchAddr, v);
}
- }
- else
- {
+
//
- // We have just unmarshaled an index -- check if we have
- // unmarshaled the instance for that index yet.
+ // Clear out the patch map for that index -- there is nothing left
+ // to patch for that index for the time being.
//
- unmarshaledPos = _currentReadEncaps->unmarshaledMap->find(index);
- if(unmarshaledPos == _currentReadEncaps->unmarshaledMap->end())
- {
- return; // We haven't unmarshaled the instance yet.
- }
+ _patchMap.erase(patchPos);
}
- assert(patchPos->second.size() > 0);
- ObjectPtr v = unmarshaledPos->second;
- assert(v);
+ return v;
+}
+
+void
+IceInternal::BasicStream::EncapsDecoder::addPatchEntry(Int index, PatchFunc patchFunc, void* patchAddr)
+{
+ assert(index > 0);
//
- // Patch all pointers that refer to the instance.
+ // Check if already un-marshalled the object. If that's the case,
+ // just patch the object smart pointer and we're done.
//
- for(PatchList::iterator k = patchPos->second.begin(); k != patchPos->second.end(); ++k)
+ IndexToPtrMap::iterator p = _unmarshaledMap.find(index);
+ if(p != _unmarshaledMap.end())
{
- (*k->patchFunc)(k->patchAddr, v);
+ (*patchFunc)(patchAddr, p->second);
+ return;
}
//
- // Clear out the patch map for that index -- there is nothing left
- // to patch for that index for the time being.
+ // Add patch entry if the object isn't un-marshalled yet, the
+ // smart pointer will be patched when the instance is
+ // un-marshalled.
//
- _currentReadEncaps->patchMap->erase(patchPos);
-}
-
-void
-IceInternal::BasicStream::addPatchEntry(Int index, PatchFunc patchFunc, void* patchAddr)
-{
- assert(index > 0);
- initReadEncaps();
-
- PatchMap::iterator p = _currentReadEncaps->patchMap->find(index);
- if(p == _currentReadEncaps->patchMap->end())
+ PatchMap::iterator q = _patchMap.find(index);
+ if(q == _patchMap.end())
{
//
// We have no outstanding instances to be patched for this
// index, so make a new entry in the patch map.
//
- p = _currentReadEncaps->patchMap->insert(make_pair(index, PatchList())).first;
+ q = _patchMap.insert(make_pair(index, PatchList())).first;
}
//
@@ -2974,69 +2578,57 @@ IceInternal::BasicStream::addPatchEntry(Int index, PatchFunc patchFunc, void* pa
PatchEntry e;
e.patchFunc = patchFunc;
e.patchAddr = patchAddr;
- p->second.push_back(e);
- patchPointers(index, _currentReadEncaps->unmarshaledMap->end(), p);
+ q->second.push_back(e);
}
void
-IceInternal::BasicStream::writeSlicedData(const SlicedDataPtr& slicedData)
+IceInternal::BasicStream::EncapsDecoder::skipSlice()
{
- assert(slicedData);
- assert(_currentWriteEncaps);
- assert(_currentWriteEncaps->encoding != Encoding_1_0);
- assert(_format == SlicedFormat);
+ Container::iterator start = _stream->i;
- for(SliceInfoSeq::const_iterator p = slicedData->slices.begin(); p != slicedData->slices.end(); ++p)
+ if(_sliceFlags & FLAG_HAS_SLICE_SIZE)
{
- Byte flags = FLAG_HAS_SLICE_SIZE;
-
- //
- // Only include an indirection table when necessary.
- //
- if(!(*p)->objects.empty())
+ assert(_sliceSize >= 4);
+ _stream->i += _sliceSize - sizeof(Int);
+ if(_stream->i > _stream->b.end())
{
- flags |= FLAG_HAS_INDIRECTION_TABLE;
+ throw UnmarshalOutOfBoundsException(__FILE__, __LINE__);
}
+ }
+ else
+ {
+ throw MarshalException(__FILE__, __LINE__, "compact format prevents slicing");
+ }
+ if(_encaps->encoding != Encoding_1_0)
+ {
//
- // Write the flags and type ID.
+ // Preserve this slice.
//
- writeSliceHeader(flags, (*p)->typeId);
+ SliceInfoPtr info = new SliceInfo;
+ info->typeId = _typeId;
+ vector<Byte>(start, _stream->i).swap(info->bytes);
+ _slices.push_back(info);
- //
- // Write the bytes associated with this slice.
- //
- writeBlob((*p)->bytes);
+ _indirectionTables.push_back(IndexList());
- //
- // Assemble and write the indirection table. The table must have the same order
- // as the list of objects.
- //
- if(!(*p)->objects.empty())
+ if(_sliceFlags & FLAG_HAS_INDIRECTION_TABLE)
{
- IndexList indirections;
- for(vector<ObjectPtr>::const_iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q)
- {
- Int index = registerObject(*q);
- indirections.push_back(index);
- }
-
//
- // Write the table as a sequence<size> to conserve space.
+ // Read the indirection table, which is written as a sequence<size> to conserve space.
//
- writeSize(indirections.size());
- for(IndexList::iterator r = indirections.begin(); r != indirections.end(); ++r)
- {
- writeSize(*r);
- }
+ _stream->readSizeSeq(_indirectionTables.back());
}
}
}
-SlicedDataPtr
-IceInternal::BasicStream::prepareSlicedData()
+SlicedDataPtr
+IceInternal::BasicStream::EncapsDecoder::readSlicedData()
{
- SlicedDataPtr slicedData;
+ if(_slices.empty()) // No preserved slices.
+ {
+ return 0;
+ }
//
// The _indirectionTables member holds the indirection table for each slice
@@ -3070,10 +2662,5 @@ IceInternal::BasicStream::prepareSlicedData()
}
}
- if(!_slices.empty())
- {
- slicedData = new SlicedData(_slices);
- }
-
- return slicedData;
+ return new SlicedData(_slices);
}
diff --git a/cpp/src/Ice/StreamI.cpp b/cpp/src/Ice/StreamI.cpp
index 756c1da8e8c..b25856f58ad 100644
--- a/cpp/src/Ice/StreamI.cpp
+++ b/cpp/src/Ice/StreamI.cpp
@@ -1073,7 +1073,7 @@ Ice::ObjectWriter::__write(BasicStream* os) const
}
void
-Ice::ObjectWriter::__read(BasicStream*, bool)
+Ice::ObjectWriter::__read(BasicStream*)
{
assert(false);
}
@@ -1085,7 +1085,7 @@ Ice::ObjectWriter::__write(const Ice::OutputStreamPtr&) const
}
void
-Ice::ObjectWriter::__read(const Ice::InputStreamPtr&, bool)
+Ice::ObjectWriter::__read(const Ice::InputStreamPtr&)
{
assert(false);
}