diff options
author | Benoit Foucher <benoit@zeroc.com> | 2012-06-11 18:53:17 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2012-06-11 18:53:17 +0200 |
commit | 27b1f7cc1b061fbf3a1582963d0af08d5839d480 (patch) | |
tree | c93c4a0c885ec941ec33116dd2f5683042d96a34 /cpp/src/Ice/BasicStream.cpp | |
parent | Java port (diff) | |
download | ice-27b1f7cc1b061fbf3a1582963d0af08d5839d480.tar.bz2 ice-27b1f7cc1b061fbf3a1582963d0af08d5839d480.tar.xz ice-27b1f7cc1b061fbf3a1582963d0af08d5839d480.zip |
Support for optionals
Diffstat (limited to 'cpp/src/Ice/BasicStream.cpp')
-rwxr-xr-x | cpp/src/Ice/BasicStream.cpp | 519 |
1 files changed, 311 insertions, 208 deletions
diff --git a/cpp/src/Ice/BasicStream.cpp b/cpp/src/Ice/BasicStream.cpp index 0d8ea17953d..e08d7ad9b49 100755 --- a/cpp/src/Ice/BasicStream.cpp +++ b/cpp/src/Ice/BasicStream.cpp @@ -154,12 +154,12 @@ IceInternal::BasicStream::swap(BasicStream& other) std::swap(_closure, other._closure); // - // Swap is never called for BasicStreams that have encapsulations being read/write. + // Swap is never called for BasicStreams that have encapsulations being read/write. However, + // encapsulations might still be set in case marhsalling or un-marhsalling failed. We just + // reset the encapsulations if there are still some set. // - assert(!_currentReadEncaps); - assert(!_currentWriteEncaps); - assert(!other._currentReadEncaps); - assert(!other._currentWriteEncaps); + resetEncaps(); + other.resetEncaps(); std::swap(_unlimited, other._unlimited); std::swap(_startSeq, other._startSeq); @@ -168,6 +168,28 @@ IceInternal::BasicStream::swap(BasicStream& other) } void +IceInternal::BasicStream::resetEncaps() +{ + while(_currentReadEncaps && _currentReadEncaps != &_preAllocatedReadEncaps) + { + ReadEncaps* oldEncaps = _currentReadEncaps; + _currentReadEncaps = _currentReadEncaps->previous; + delete oldEncaps; + } + + while(_currentWriteEncaps && _currentWriteEncaps != &_preAllocatedWriteEncaps) + { + WriteEncaps* oldEncaps = _currentWriteEncaps; + _currentWriteEncaps = _currentWriteEncaps->previous; + delete oldEncaps; + } + + _preAllocatedReadEncaps.reset(); + _preAllocatedWriteEncaps.reset(); +} + + +void IceInternal::BasicStream::format(Ice::FormatType format) { if(format != DefaultFormat) @@ -242,14 +264,14 @@ IceInternal::BasicStream::skipEncaps() return encoding; } -void -IceInternal::BasicStream::readAndCheckSeqSize(int minSize, Int& sz) +Int +IceInternal::BasicStream::readAndCheckSeqSize(int minSize) { - readSize(sz); + Int sz = readSize(); if(sz == 0) { - return; + return sz; } // @@ -288,6 +310,8 @@ IceInternal::BasicStream::readAndCheckSeqSize(int minSize, Int& sz) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } + + return sz; } void @@ -319,15 +343,6 @@ IceInternal::BasicStream::readBlob(vector<Byte>& v, Int sz) } } -void IceInternal::BasicStream::write(Byte v, int end) -{ - if(v >= end) - { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); - } - write(v); -} - void IceInternal::BasicStream::write(const Byte* begin, const Byte* end) { @@ -342,20 +357,25 @@ IceInternal::BasicStream::write(const Byte* begin, const Byte* end) } void -IceInternal::BasicStream::read(Byte& b, int end) +IceInternal::BasicStream::read(std::vector<Ice::Byte>& v) { - read(b); - if(b >= end) + std::pair<const Ice::Byte*, const Ice::Byte*> p; + read(p); + if(p.first != p.second) + { + v.resize(static_cast<Ice::Int>(p.second - p.first)); + copy(p.first, p.second, v.begin()); + } + else { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); + v.clear(); } } void IceInternal::BasicStream::read(pair<const Byte*, const Byte*>& v) { - Int sz; - readAndCheckSeqSize(1, sz); + Int sz = readAndCheckSeqSize(1); if(sz > 0) { v.first = i; @@ -423,8 +443,7 @@ IceInternal::BasicStream::write(const bool* begin, const bool* end) void IceInternal::BasicStream::read(vector<bool>& v) { - Int sz; - readAndCheckSeqSize(1, sz); + Int sz = readAndCheckSeqSize(1); if(sz > 0) { v.resize(sz); @@ -473,8 +492,7 @@ bool* IceInternal::BasicStream::read(pair<const bool*, const bool*>& v) { bool* result = 0; - Int sz; - readAndCheckSeqSize(1, sz); + Int sz = readAndCheckSeqSize(1); if(sz > 0) { result = BasicStreamReadBoolHelper<sizeof(bool)>::read(v, sz, i); @@ -505,16 +523,6 @@ IceInternal::BasicStream::write(Short v) } void -IceInternal::BasicStream::write(Short v, int end) -{ - if(v < 0 || v >= end) - { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); - } - write(v); -} - -void IceInternal::BasicStream::write(const Short* begin, const Short* end) { Int sz = static_cast<Int>(end - begin); @@ -559,20 +567,9 @@ IceInternal::BasicStream::read(Short& v) } void -IceInternal::BasicStream::read(Short& v, int end) -{ - read(v); - if(v < 0 || v >= end) - { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); - } -} - -void IceInternal::BasicStream::read(vector<Short>& v) { - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Short)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Short))); if(sz > 0) { Container::iterator begin = i; @@ -601,8 +598,7 @@ Short* IceInternal::BasicStream::read(pair<const Short*, const Short*>& v) { Short* result = 0; - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Short)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Short))); if(sz > 0) { #if defined(__i386) || defined(_M_IX86) @@ -638,26 +634,6 @@ IceInternal::BasicStream::read(pair<const Short*, const Short*>& v) } void -IceInternal::BasicStream::read(Int& v, int end) -{ - read(v); - if(v < 0 || v >= end) - { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); - } -} - -void -IceInternal::BasicStream::write(Int v, int end) -{ - if(v < 0 || v >= end) - { - throw MarshalException(__FILE__, __LINE__, "enumerator out of range"); - } - write(v); -} - -void IceInternal::BasicStream::write(const Int* begin, const Int* end) { Int sz = static_cast<Int>(end - begin); @@ -686,8 +662,7 @@ IceInternal::BasicStream::write(const Int* begin, const Int* end) void IceInternal::BasicStream::read(vector<Int>& v) { - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Int)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Int))); if(sz > 0) { Container::iterator begin = i; @@ -718,8 +693,7 @@ Int* IceInternal::BasicStream::read(pair<const Int*, const Int*>& v) { Int* result = 0; - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Int)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Int))); if(sz > 0) { #if defined(__i386) || defined(_M_IX86) @@ -850,8 +824,7 @@ IceInternal::BasicStream::read(Long& v) void IceInternal::BasicStream::read(vector<Long>& v) { - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Long)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Long))); if(sz > 0) { Container::iterator begin = i; @@ -886,8 +859,7 @@ Long* IceInternal::BasicStream::read(pair<const Long*, const Long*>& v) { Long* result = 0; - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Long)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Long))); if(sz > 0) { #if defined(__i386) || defined(_M_IX86) @@ -1002,8 +974,7 @@ IceInternal::BasicStream::read(Float& v) void IceInternal::BasicStream::read(vector<Float>& v) { - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Float)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Float))); if(sz > 0) { Container::iterator begin = i; @@ -1034,8 +1005,7 @@ Float* IceInternal::BasicStream::read(pair<const Float*, const Float*>& v) { Float* result = 0; - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Float)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Float))); if(sz > 0) { #if defined(__i386) || defined(_M_IX86) @@ -1203,8 +1173,7 @@ IceInternal::BasicStream::read(Double& v) void IceInternal::BasicStream::read(vector<Double>& v) { - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Double)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Double))); if(sz > 0) { Container::iterator begin = i; @@ -1254,8 +1223,7 @@ Double* IceInternal::BasicStream::read(pair<const Double*, const Double*>& v) { Double* result = 0; - Int sz; - readAndCheckSeqSize(static_cast<int>(sizeof(Double)), sz); + Int sz = readAndCheckSeqSize(static_cast<int>(sizeof(Double))); if(sz > 0) { #if defined(__i386) || defined(_M_IX86) @@ -1407,8 +1375,7 @@ IceInternal::BasicStream::readConverted(string& v, int sz) void IceInternal::BasicStream::read(vector<string>& v, bool convert) { - Int sz; - readAndCheckSeqSize(1, sz); + Int sz = readAndCheckSeqSize(1); if(sz > 0) { v.resize(sz); @@ -1504,8 +1471,7 @@ IceInternal::BasicStream::write(const wstring* begin, const wstring* end) void IceInternal::BasicStream::read(wstring& v) { - Int sz; - readSize(sz); + Int sz = readSize(); if(sz > 0) { if(b.end() - i < sz) @@ -1525,8 +1491,7 @@ IceInternal::BasicStream::read(wstring& v) void IceInternal::BasicStream::read(vector<wstring>& v) { - Int sz; - readAndCheckSeqSize(1, sz); + Int sz = readAndCheckSeqSize(1); if(sz > 0) { v.resize(sz); @@ -1553,12 +1518,209 @@ IceInternal::BasicStream::read(ObjectPrx& v) v = _instance->proxyFactory()->streamToProxy(this); } +Int +IceInternal::BasicStream::readEnum(Int limit) +{ + if(getReadEncoding() == Encoding_1_0) + { + if(limit <= 127) + { + Byte value; + read(value); + return value; + } + else if(limit <= 32767) + { + Short value; + read(value); + return value; + } + else + { + Int value; + read(value); + return value; + } + } + else + { + return readSize(); + } +} + +void +IceInternal::BasicStream::writeEnum(Int v, Int limit) +{ + if(getWriteEncoding() == Encoding_1_0) + { + if(limit <= 127) + { + write(static_cast<Byte>(v)); + } + else if(limit <= 32767) + { + write(static_cast<Short>(v)); + } + else + { + write(v); + } + } + else + { + writeSize(v); + } +} + void IceInternal::BasicStream::sliceObjects(bool doSlice) { _sliceObjects = doSlice; } + +bool +IceInternal::BasicStream::readOptImpl(Int readTag, OptionalType expectedType) +{ + Int tag = 0; + OptionalType type; + do + { + if(i >= b.begin() + _currentReadEncaps->start + _currentReadEncaps->sz) + { + return false; // End of encapsulation also indicates end of optionals. + } + + Byte v; + read(v); + type = static_cast<OptionalType>(v & 0x07); // First 3 bits. + tag = static_cast<Int>(v >> 3); + if(tag == 31) + { + tag = readSize(); + } + } + while(type != OptionalTypeEndMarker && tag < readTag && skipOpt(type)); // Skip optional data members + + if(type == OptionalTypeEndMarker || tag > readTag) + { + // + // Rewind the stream to correctly read the next optional data + // member tag & type next time. + // + i -= tag < 31 ? 1 : (tag < 255 ? 2 : 6); + return false; // No optional data members with the requested tag. + } + + assert(readTag == tag); + if(type != expectedType) + { + ostringstream os; + os << "invalid optional data member `" << tag << "': unexpected type"; + throw MarshalException(__FILE__, __LINE__, os.str()); + } + + // + // We have an optional data member with the requested tag and + // type. + // + return true; +} + +void +IceInternal::BasicStream::writeOptImpl(Int tag, OptionalType type) +{ + Byte v = static_cast<Byte>(type); + if(tag < 31) + { + v |= tag << 3; + write(v); + } + else + { + v |= 0x0F8; // tag = 31 + write(v); + writeSize(tag); + } +} + +bool +IceInternal::BasicStream::skipOpt(OptionalType type) +{ + int sz; + switch(type) + { + case Ice::OptionalTypeF1: + { + sz = 1; + break; + } + case Ice::OptionalTypeF2: + { + sz = 2; + break; + } + case Ice::OptionalTypeF4: + { + sz = 4; + break; + } + case Ice::OptionalTypeF8: + { + sz = 8; + break; + } + case Ice::OptionalTypeSize: + { + skipSize(); + return true; + } + case Ice::OptionalTypeVSize: + { + sz = readSize(); + break; + } + case Ice::OptionalTypeFSize: + { + read(sz); + break; + } + default: + { + return false; + } + } + skip(sz); + return true; +} + +bool +BasicStream::skipOpts() +{ + // + // Skip remaining un-read optional members. + // + OptionalType type; + do + { + if(i >= b.begin() + _currentReadEncaps->start + _currentReadEncaps->sz) + { + return false; // End of encapsulation also indicates end of optionals. + } + + Byte v; + read(v); + type = static_cast<OptionalType>(v & 0x07); // Read first 3 bits. + if(static_cast<Int>(v >> 3) == 31) + { + skipSize(); + } + } + while(skipOpt(type)); + assert(type == OptionalTypeEndMarker); + return true; +} + void IceInternal::BasicStream::throwUnmarshalOutOfBoundsException(const char* file, int line) { @@ -1577,6 +1739,7 @@ IceInternal::BasicStream::initReadEncaps() if(!_currentReadEncaps) // Lazy initialization. { _currentReadEncaps = &_preAllocatedReadEncaps; + _currentReadEncaps->sz = b.size(); } if(!_currentReadEncaps->decoder) // Lazy initialization. @@ -1812,7 +1975,7 @@ IceInternal::BasicStream::EncapsEncoder::endSlice() // if(_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) { - _stream->write(static_cast<Byte>(MemberTypeEndMarker)); + _stream->write(static_cast<Byte>(OptionalTypeEndMarker)); } // @@ -1861,30 +2024,12 @@ IceInternal::BasicStream::EncapsEncoder::endSlice() } void -IceInternal::BasicStream::EncapsEncoder::writeOpt(int tag, MemberType type) -{ - assert(_sliceType != NoSlice); - _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS; - Byte v = static_cast<Byte>(type); - if(tag < 31) - { - v |= tag << 3; - } - else - { - v |= 0x0F8; // tag = 31 - _stream->writeSize(tag); - } -} - -void IceInternal::BasicStream::EncapsEncoder::writePendingObjects() { // - // With the 1.0 encoding, only write pending objects if nil or - // non-nil references were written (_usesClasses = - // true). Otherwise, write pending objects only if some non-nil - // references were written. + // With the 1.0 encoding, write pending objects if nil or non-nil + // references were written (_usesClasses = true). Otherwise, write + // pending objects only if some non-nil references were written. // if(_encaps->encoding == Encoding_1_0) { @@ -1898,6 +2043,14 @@ IceInternal::BasicStream::EncapsEncoder::writePendingObjects() { return; } + else + { + // + // Write end marker for encapsulation optionals before encoding + // the pending objects. + // + _stream->write(static_cast<Byte>(OptionalTypeEndMarker)); + } while(!_toBeMarshaledMap.empty()) { @@ -1973,6 +2126,11 @@ IceInternal::BasicStream::EncapsEncoder::writeSlicedData(const SlicedDataPtr& sl // _stream->writeBlob((*p)->bytes); + if((*p)->hasOptionalMembers) + { + _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS; + } + // // Assemble and write the indirection table. The table must have the same order // as the list of objects. @@ -2041,7 +2199,7 @@ IceInternal::BasicStream::EncapsDecoder::read(PatchFunc patchFunc, void* patchAd // // Later versions use a size. // - _stream->readSize(index); + index = _stream->readSize(); if(index < 0) { throw MarshalException(__FILE__, __LINE__, "invalid object id"); @@ -2141,8 +2299,8 @@ IceInternal::BasicStream::EncapsDecoder::throwException(const UserExceptionFacto } // - // Performance sensitive, so we use lazy initialization - // for tracing. + // Performance sensitive, so we use lazy initialization for + // tracing. // if(_traceSlicing == -1) { @@ -2156,8 +2314,7 @@ IceInternal::BasicStream::EncapsDecoder::throwException(const UserExceptionFacto if(_sliceFlags & FLAG_IS_LAST_SLICE) { - // TODO: Consider adding a new exception, such as NoExceptionFactory? - throw UnmarshalOutOfBoundsException(__FILE__, __LINE__, "unknown exception type `" + mostDerivedId + "'"); + throw NoExceptionFactoryException(__FILE__, __LINE__, "", "unknown exception type `" + mostDerivedId + "'"); } skipSlice(); // Slice off what we don't understand. @@ -2203,8 +2360,7 @@ IceInternal::BasicStream::EncapsDecoder::endObject(bool preserve) // // For compatibility with the old AFM. // - Int sz; - _stream->readSize(sz); + Int sz = _stream->readSize(); if(sz != 0) { throw MarshalException(__FILE__, __LINE__, "invalid Object slice"); @@ -2287,8 +2443,7 @@ IceInternal::BasicStream::EncapsDecoder::startSlice() { if(_sliceFlags & FLAG_HAS_TYPE_ID_INDEX) { - Int index; - _stream->readSize(index); + Int index = _stream->readSize(); TypeIdReadMap::const_iterator k = _typeIdMap.find(index); if(k == _typeIdMap.end()) { @@ -2341,15 +2496,7 @@ IceInternal::BasicStream::EncapsDecoder::endSlice() { if(_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) { - // - // Read remaining un-read optional members. - // - Byte v; - do - { - _stream->read(v); - } - while(skipOpt(static_cast<MemberType>(v & 0x07))); + _stream->skipOpts(); } // @@ -2365,13 +2512,15 @@ IceInternal::BasicStream::EncapsDecoder::endSlice() _stream->readSizeSeq(indirectionTable); // - // Sanity checks. + // Sanity checks. If there are optional members, it's possible + // that not all object references were read if they are from + // unknown optional data members. // if(indirectionTable.empty() && !_indirectPatchList.empty()) { throw MarshalException(__FILE__, __LINE__, "empty indirection table"); } - else if(!indirectionTable.empty() && _indirectPatchList.empty()) + else if(!indirectionTable.empty() && _indirectPatchList.empty() && !(_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS)) { throw MarshalException(__FILE__, __LINE__, "no references to indirection table"); } @@ -2399,73 +2548,13 @@ IceInternal::BasicStream::EncapsDecoder::endSlice() } } -bool -IceInternal::BasicStream::EncapsDecoder::readOpt(int readTag, MemberType expectedType) -{ - assert(_sliceType != NoSlice); - if(!(_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS)) - { - return false; // No optional data members - } - - int tag; - MemberType type; - do - { - Byte v; - _stream->read(v); - - type = static_cast<MemberType>(v & 0x07); // Read first 3 bits. - tag = static_cast<int>(v >> 3); - if(tag == 31) - { - _stream->readSize(tag); - } - } - while(tag < readTag && skipOpt(type)); // Skip optional data members with lower tag values. - - if(type == MemberTypeEndMarker) - { - // - // Clear the optional members flag since we've reach the end. We clear - // the flag to prevent endSlice to skip un-read optional members and - // to prevent other optional members from being read. - // - _sliceFlags &= ~FLAG_HAS_OPTIONAL_MEMBERS; - return false; - } - else if(tag > readTag) - { - // - // Rewind the stream so that we correctly read the next - // optional data member tag & type. - // - _stream->i -= tag < 31 ? 1 : (tag < 255 ? 2 : 6); - return false; // No optional data members with the requested tag. - } - - assert(readTag == tag); - if(type != expectedType) - { - ostringstream os; - os << "invalid optional data member `" << tag << "' in `" << _typeId << "': unexpected type"; - throw MarshalException(__FILE__, __LINE__, os.str()); - } - - // - // We have an optional data member with the requested tag and - // type. - // - return true; -} - void IceInternal::BasicStream::EncapsDecoder::readPendingObjects() { // - // With the 1.0 encoding, only read pending objects if nil or - // non-nil references were read (_usesClasses == true). Otherwise, - // read pending objects only if some non-nil references were read. + // With the 1.0 encoding, read pending objects if nil or non-nil + // references were read (_usesClasses == true). Otherwise, read + // pending objects only if some non-nil references were read. // if(_encaps->encoding == Encoding_1_0) { @@ -2479,12 +2568,20 @@ IceInternal::BasicStream::EncapsDecoder::readPendingObjects() { return; } + else + { + // + // Read unread encapsulation optionals before reading the + // pending objects. + // + _stream->skipOpts(); + } Int num; ObjectList objectList; do { - _stream->readSize(num); + num = _stream->readSize(); for(Int k = num; k > 0; --k) { objectList.push_back(readInstance()); @@ -2536,7 +2633,7 @@ IceInternal::BasicStream::EncapsDecoder::readInstance() } else { - _stream->readSize(index); + index = _stream->readSize(); } ObjectPtr v; @@ -2727,11 +2824,7 @@ IceInternal::BasicStream::EncapsDecoder::skipSlice() if(_sliceFlags & FLAG_HAS_SLICE_SIZE) { assert(_sliceSize >= 4); - _stream->i += _sliceSize - sizeof(Int); - if(_stream->i > _stream->b.end()) - { - throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); - } + _stream->skip(_sliceSize - sizeof(Int)); } else { @@ -2745,7 +2838,17 @@ IceInternal::BasicStream::EncapsDecoder::skipSlice() // SliceInfoPtr info = new SliceInfo; info->typeId = _typeId; - vector<Byte>(start, _stream->i).swap(info->bytes); + info->hasOptionalMembers = _sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS; + if(info->hasOptionalMembers) + { + // Don't include the optional member end marker. It will be re-written by + // endSlice when the sliced data is re-written. + vector<Byte>(start, _stream->i - 1).swap(info->bytes); + } + else + { + vector<Byte>(start, _stream->i).swap(info->bytes); + } _slices.push_back(info); _indirectionTables.push_back(IndexList()); @@ -2796,7 +2899,7 @@ IceInternal::BasicStream::EncapsDecoder::readSlicedData() { throw MarshalException(__FILE__, __LINE__, "invalid id in object indirection table"); } - addPatchEntry(id, __patch__ObjectPtr, &_slices[n]->objects[j++]); + addPatchEntry(id, &patchHandle<Ice::Object>, &_slices[n]->objects[j++]); } } |