// ********************************************************************** // // Copyright (c) 2003 // ZeroC, Inc. // Billerica, MA, USA // // All Rights Reserved. // // Ice is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License version 2 as published by // the Free Software Foundation. // // ********************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include template inline void ice_copy(InputIter first, InputIter last, OutputIter result) { std::copy(first, last, result); } template<> inline void ice_copy(std::vector::const_iterator first, std::vector::const_iterator last, std::vector::iterator result) { if(last != first) { memcpy(&*result, &*first, last - first); } } using namespace std; using namespace Ice; using namespace IceInternal; IceInternal::BasicStream::BasicStream(Instance* instance) : _instance(instance), _currentReadEncaps(0), _currentWriteEncaps(0), _traceSlicing(-1), _marshalFacets(true), _messageSizeMax(_instance->messageSizeMax()) // Cached for efficiency. { } Instance* IceInternal::BasicStream::instance() const { return _instance; } void IceInternal::BasicStream::swap(BasicStream& other) { assert(_instance == other._instance); b.swap(other.b); std::swap(i, other.i); _readEncapsStack.swap(other._readEncapsStack); _writeEncapsStack.swap(other._writeEncapsStack); std::swap(_currentReadEncaps, other._currentReadEncaps); std::swap(_currentWriteEncaps, other._currentWriteEncaps); } void IceInternal::BasicStream::reserve(Container::size_type sz) { if(sz > _messageSizeMax) { throw MemoryLimitException(__FILE__, __LINE__); } b.reserve(sz); } IceInternal::BasicStream::WriteEncaps::WriteEncaps() : writeIndex(0), toBeMarshaledMap(0), marshaledMap(0), typeIdIndex(0), typeIdMap(0) { } IceInternal::BasicStream::WriteEncaps::~WriteEncaps() { if(toBeMarshaledMap) { delete toBeMarshaledMap; delete marshaledMap; delete typeIdMap; } } void IceInternal::BasicStream::startWriteEncaps() { { _writeEncapsStack.push_back(WriteEncaps()); _currentWriteEncaps = &_writeEncapsStack.back(); } _currentWriteEncaps->start = b.size(); write(Int(0)); // Placeholder for the encapsulation length. write(encodingMajor); write(encodingMinor); } void IceInternal::BasicStream::endWriteEncaps() { assert(_currentWriteEncaps); Container::size_type start = _currentWriteEncaps->start; Int sz = static_cast(b.size() - start); // Size includes size and version. Byte* dest = &(*(b.begin() + start)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&sz) + sizeof(Int) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&sz); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif { _writeEncapsStack.pop_back(); if(_writeEncapsStack.empty()) { _currentWriteEncaps = 0; } else { _currentWriteEncaps = &_writeEncapsStack.back(); } } } IceInternal::BasicStream::ReadEncaps::ReadEncaps() : patchMap(0), unmarshaledMap(0), typeIdIndex(0), typeIdMap(0) { } IceInternal::BasicStream::ReadEncaps::~ReadEncaps() { if(patchMap) { delete patchMap; delete unmarshaledMap; delete typeIdMap; } } void IceInternal::BasicStream::startReadEncaps() { { _readEncapsStack.push_back(ReadEncaps()); _currentReadEncaps = &_readEncapsStack.back(); } _currentReadEncaps->start = i - b.begin(); // // I don't use readSize() and writeSize() for encapsulations, // because when creating an encapsulation, I must know in advance // how many bytes the size information will require in the data // stream. If I use an Int, it is always 4 bytes. For // readSize()/writeSize(), it could be 1 or 5 bytes. // Int sz; read(sz); if(sz < 0) { throw NegativeSizeException(__FILE__, __LINE__); } if(i - sizeof(Int) + sz > b.end()) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } _currentReadEncaps->sz = sz; Byte eMajor; Byte eMinor; read(eMajor); read(eMinor); if(eMajor != encodingMajor || static_cast(eMinor) > static_cast(encodingMinor)) { UnsupportedEncodingException ex(__FILE__, __LINE__); ex.badMajor = static_cast(eMajor); ex.badMinor = static_cast(eMinor); ex.major = static_cast(encodingMajor); ex.minor = static_cast(encodingMinor); throw ex; } _currentReadEncaps->encodingMajor = eMajor; _currentReadEncaps->encodingMinor = eMinor; } void IceInternal::BasicStream::endReadEncaps() { assert(_currentReadEncaps); Container::size_type start = _currentReadEncaps->start; Int sz = _currentReadEncaps->sz; i = b.begin() + start + sz; _readEncapsStack.pop_back(); if(_readEncapsStack.empty()) { _currentReadEncaps = 0; } else { _currentReadEncaps = &_readEncapsStack.back(); } } void IceInternal::BasicStream::checkReadEncaps() { assert(_currentReadEncaps); Container::size_type start = _currentReadEncaps->start; Int sz = _currentReadEncaps->sz; if(i != b.begin() + start + sz) { throw EncapsulationException(__FILE__, __LINE__); } } Int IceInternal::BasicStream::getReadEncapsSize() { assert(_currentReadEncaps); return _currentReadEncaps->sz - sizeof(Int) - 2; } void IceInternal::BasicStream::skipEncaps() { Int sz; read(sz); if(sz < 0) { throw NegativeSizeException(__FILE__, __LINE__); } if(i - sizeof(Int) + sz > b.end()) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } i += sz - sizeof(Int); } void IceInternal::BasicStream::startWriteSlice() { write(Int(0)); // Placeholder for the slice length. _writeSlice = b.size(); } void IceInternal::BasicStream::endWriteSlice() { Int sz = static_cast(b.size() - _writeSlice + sizeof(Int)); #if 0 const Byte* p = reinterpret_cast(&sz); #ifdef ICE_BIG_ENDIAN reverse_copy(p, p + sizeof(Int), b.begin() + _writeSlice - sizeof(Int)); #else copy(p, p + sizeof(Int), b.begin() + _writeSlice - sizeof(Int)); #endif #else Byte* dest = &(*(b.begin() + _writeSlice - sizeof(Int))); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&sz) + sizeof(Int) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&sz); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif #endif } void IceInternal::BasicStream::startReadSlice() { Int sz; read(sz); if(sz < 0) { throw NegativeSizeException(__FILE__, __LINE__); } _readSlice = i - b.begin(); } void IceInternal::BasicStream::endReadSlice() { } void IceInternal::BasicStream::skipSlice() { Int sz; read(sz); if(sz < 0) { throw NegativeSizeException(__FILE__, __LINE__); } i += sz - sizeof(Int); if(i > b.end()) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } } void IceInternal::BasicStream::writeSize(Int v) { assert(v >= 0); if(v > 254) { write(Byte(255)); write(v); } else { write(static_cast(v)); } } void IceInternal::BasicStream::readSize(Ice::Int& v) { Byte byte; read(byte); unsigned val = static_cast(byte); if(val == 255) { read(v); if(v < 0) { throw NegativeSizeException(__FILE__, __LINE__); } } else { v = static_cast(static_cast(byte)); } } void IceInternal::BasicStream::writeTypeId(const string& id) { TypeIdWriteMap::const_iterator k = _currentWriteEncaps->typeIdMap->find(id); if(k != _currentWriteEncaps->typeIdMap->end()) { write(true); writeSize(k->second); } else { _currentWriteEncaps->typeIdMap->insert(make_pair(id, ++_currentWriteEncaps->typeIdIndex)); write(false); write(id); } } void IceInternal::BasicStream::readTypeId(string& id) { bool isIndex; read(isIndex); if(isIndex) { Ice::Int index; readSize(index); TypeIdReadMap::const_iterator k = _currentReadEncaps->typeIdMap->find(index); if(k == _currentReadEncaps->typeIdMap->end()) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } id = k->second; } else { read(id); _currentReadEncaps->typeIdMap->insert(make_pair(++_currentReadEncaps->typeIdIndex, id)); } } void IceInternal::BasicStream::writeBlob(const vector& v) { Container::size_type pos = b.size(); resize(pos + v.size()); ice_copy(v.begin(), v.end(), b.begin() + pos); } void IceInternal::BasicStream::readBlob(vector& v, Int sz) { if(b.end() - i < sz) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += sz; v.resize(sz); ice_copy(begin, i, v.begin()); } void IceInternal::BasicStream::writeBlob(const Ice::Byte* v, Container::size_type len) { Container::size_type pos = b.size(); resize(pos + len); ice_copy(&v[0], &v[0 + len], b.begin() + pos); } void IceInternal::BasicStream::readBlob(Ice::Byte* v, Container::size_type len) { if(static_cast(b.end() - i) < len) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += len; ice_copy(begin, i, &v[0]); } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); Container::size_type pos = b.size(); resize(pos + sz); ice_copy(v.begin(), v.end(), b.begin() + pos); } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); if(b.end() - i < sz) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += sz; v.resize(sz); ice_copy(begin, i, v.begin()); } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); Container::size_type pos = b.size(); resize(pos + sz); ice_copy(v.begin(), v.end(), b.begin() + pos); } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); if(b.end() - i < sz) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += sz; v.resize(sz); ice_copy(begin, i, v.begin()); } void IceInternal::BasicStream::write(Short v) { Container::size_type pos = b.size(); resize(pos + sizeof(Short)); Byte* dest = &b[pos]; #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v) + sizeof(Short) - 1; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&v); *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); if(sz > 0) { Container::size_type pos = b.size(); resize(pos + sz * sizeof(Short)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v[0]) + sizeof(Short) - 1; Byte* dest = &(*(b.begin() + pos)); for(int j = 0 ; j < sz ; ++j) { *dest++ = *src--; *dest++ = *src--; src += 2 * sizeof(Short); } #else ice_copy(reinterpret_cast(&v[0]), reinterpret_cast(&v[0]) + sz * sizeof(Short), b.begin() + pos); #endif } } void IceInternal::BasicStream::read(Short& v) { if(b.end() - i < static_cast(sizeof(Short))) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } const Byte* src = &(*i); i += sizeof(Short); #ifdef ICE_BIG_ENDIAN Byte* dest = reinterpret_cast(&v) + sizeof(Short) - 1; *dest-- = *src++; *dest = *src; #else Byte* dest = reinterpret_cast(&v); *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); const int length = sz * static_cast(sizeof(Short)); if(b.end() - i < length) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += length; v.resize(sz); if(sz > 0) { #ifdef ICE_BIG_ENDIAN const Byte* src = &(*begin); Byte* dest = reinterpret_cast(&v[0]) + sizeof(Short) - 1; for(int j = 0 ; j < sz ; ++j) { *dest-- = *src++; *dest-- = *src++; dest += 2 * sizeof(Short); } #else ice_copy(begin, i, reinterpret_cast(&v[0])); #endif } } void IceInternal::BasicStream::write(Int v) { Container::size_type pos = b.size(); resize(pos + sizeof(Int)); Byte* dest = &b[pos]; #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v) + sizeof(Int) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); if(sz > 0) { Container::size_type pos = b.size(); resize(pos + sz * sizeof(Int)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v[0]) + sizeof(Int) - 1; Byte* dest = &(*(b.begin() + pos)); for(int j = 0 ; j < sz ; ++j) { *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; src += 2 * sizeof(Int); } #else ice_copy(reinterpret_cast(&v[0]), reinterpret_cast(&v[0]) + sz * sizeof(Int), b.begin() + pos); #endif } } void IceInternal::BasicStream::read(Int& v) { if(b.end() - i < static_cast(sizeof(Int))) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } const Byte* src = &(*i); i += sizeof(Int); #ifdef ICE_BIG_ENDIAN Byte* dest = reinterpret_cast(&v) + sizeof(Int) - 1; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest = *src; #else Byte* dest = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); const int length = sz * static_cast(sizeof(Int)); if(b.end() - i < length) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += length; v.resize(sz); if(sz > 0) { #ifdef ICE_BIG_ENDIAN const Byte* src = &(*begin); Byte* dest = reinterpret_cast(&v[0]) + sizeof(Int) - 1; for(int j = 0 ; j < sz ; ++j) { *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; dest += 2 * sizeof(Int); } #else ice_copy(begin, i, reinterpret_cast(&v[0])); #endif } } void IceInternal::BasicStream::write(Long v) { Container::size_type pos = b.size(); resize(pos + sizeof(Long)); Byte* dest = &b[pos]; #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v) + sizeof(Long) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); if(sz > 0) { Container::size_type pos = b.size(); resize(pos + sz * sizeof(Long)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v[0]) + sizeof(Long) - 1; Byte* dest = &(*(b.begin() + pos)); for(int j = 0 ; j < sz ; ++j) { *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; src += 2 * sizeof(Long); } #else ice_copy(reinterpret_cast(&v[0]), reinterpret_cast(&v[0]) + sz * sizeof(Long), b.begin() + pos); #endif } } void IceInternal::BasicStream::read(Long& v) { if(b.end() - i < static_cast(sizeof(Long))) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } const Byte* src = &(*i); i += sizeof(Long); #ifdef ICE_BIG_ENDIAN Byte* dest = reinterpret_cast(&v) + sizeof(Long) - 1; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest = *src; #else Byte* dest = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); const int length = sz * static_cast(sizeof(Long)); if(b.end() - i < length) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += length; v.resize(sz); if(sz > 0) { #ifdef ICE_BIG_ENDIAN const Byte* src = &(*begin); Byte* dest = reinterpret_cast(&v[0]) + sizeof(Long) - 1; for(int j = 0 ; j < sz ; ++j) { *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; dest += 2 * sizeof(Long); } #else ice_copy(begin, i, reinterpret_cast(&v[0])); #endif } } void IceInternal::BasicStream::write(Float v) { Container::size_type pos = b.size(); resize(pos + sizeof(Float)); Byte* dest = &b[pos]; #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v) + sizeof(Float) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); if(sz > 0) { Container::size_type pos = b.size(); resize(pos + sz * sizeof(Float)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v[0]) + sizeof(Float) - 1; Byte* dest = &(*(b.begin() + pos)); for(int j = 0 ; j < sz ; ++j) { *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; src += 2 * sizeof(Float); } #else ice_copy(reinterpret_cast(&v[0]), reinterpret_cast(&v[0]) + sz * sizeof(Float), b.begin() + pos); #endif } } void IceInternal::BasicStream::read(Float& v) { if(b.end() - i < static_cast(sizeof(Float))) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } const Byte* src = &(*i); i += sizeof(Float); #ifdef ICE_BIG_ENDIAN Byte* dest = reinterpret_cast(&v) + sizeof(Float) - 1; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest = *src; #else Byte* dest = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); const int length = sz * static_cast(sizeof(Float)); if(b.end() - i < length) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += length; v.resize(sz); if(sz > 0) { #ifdef ICE_BIG_ENDIAN const Byte* src = &(*begin); Byte* dest = reinterpret_cast(&v[0]) + sizeof(Float) - 1; for(int j = 0 ; j < sz ; ++j) { *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; dest += 2 * sizeof(Float); } #else ice_copy(begin, i, reinterpret_cast(&v[0])); #endif } } void IceInternal::BasicStream::write(Double v) { Container::size_type pos = b.size(); resize(pos + sizeof(Double)); Byte* dest = &b[pos]; #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v) + sizeof(Double) - 1; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest = *src; #else const Byte* src = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::write(const vector& v) { Int sz = static_cast(v.size()); writeSize(sz); if(sz > 0) { Container::size_type pos = b.size(); resize(pos + sz * sizeof(Double)); #ifdef ICE_BIG_ENDIAN const Byte* src = reinterpret_cast(&v[0]) + sizeof(Double) - 1; Byte* dest = &(*(b.begin() + pos)); for(int j = 0 ; j < sz ; ++j) { *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; *dest++ = *src--; src += 2 * sizeof(Double); } #else ice_copy(reinterpret_cast(&v[0]), reinterpret_cast(&v[0]) + sz * sizeof(Double), b.begin() + pos); #endif } } void IceInternal::BasicStream::read(Double& v) { if(b.end() - i < static_cast(sizeof(Double))) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } const Byte* src = &(*i); i += sizeof(Double); #ifdef ICE_BIG_ENDIAN Byte* dest = reinterpret_cast(&v) + sizeof(Double) - 1; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest = *src; #else Byte* dest = reinterpret_cast(&v); *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest = *src; #endif } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); const int length = sz * static_cast(sizeof(Double)); if(b.end() - i < length) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } Container::iterator begin = i; i += length; v.resize(sz); if(sz > 0) { #ifdef ICE_BIG_ENDIAN const Byte* src = &(*begin); Byte* dest = reinterpret_cast(&v[0]) + sizeof(Double) - 1; for(int j = 0 ; j < sz ; ++j) { *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; *dest-- = *src++; dest += 2 * sizeof(Double); } #else ice_copy(begin, i, reinterpret_cast(&v[0])); #endif } } void IceInternal::BasicStream::write(const string& v) { Int len = static_cast(v.size()); writeSize(len); if(len > 0) { Container::size_type pos = b.size(); resize(pos + len); memcpy(&b[pos], v.c_str(), len); } } void IceInternal::BasicStream::write(const vector& v) { writeSize(Int(v.size())); vector::const_iterator p; for(p = v.begin(); p != v.end(); ++p) { write(*p); } } void IceInternal::BasicStream::read(string& v) { Int len; readSize(len); if(b.end() - i < len) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } v.assign(reinterpret_cast(&(*i)), len); i += len; } void IceInternal::BasicStream::read(vector& v) { Int sz; readSize(sz); while(sz--) { string s; read(s); v.push_back(s); } } void IceInternal::BasicStream::write(const ObjectPrx& v) { _instance->proxyFactory()->proxyToStream(v, this); } void IceInternal::BasicStream::read(ObjectPrx& v) { v = _instance->proxyFactory()->streamToProxy(this); } void IceInternal::BasicStream::write(const ObjectPtr& v) { if(!_currentWriteEncaps) // Lazy initialization. { _writeEncapsStack.push_back(WriteEncaps()); _currentWriteEncaps = &_writeEncapsStack.back(); _currentWriteEncaps->start = b.size(); _currentWriteEncaps->toBeMarshaledMap = 0; } if(!_currentWriteEncaps->toBeMarshaledMap) // Lazy initialization. { _currentWriteEncaps->toBeMarshaledMap = new PtrToIndexMap; _currentWriteEncaps->marshaledMap = new PtrToIndexMap; _currentWriteEncaps->typeIdMap = new TypeIdWriteMap; } if(v) { // // Look for this instance in the to-be-marshaled map. // PtrToIndexMap::iterator p = _currentWriteEncaps->toBeMarshaledMap->find(v); if(p == _currentWriteEncaps->toBeMarshaledMap->end()) { // // Didn't find it, try the marshaled map next. // PtrToIndexMap::iterator q = _currentWriteEncaps->marshaledMap->find(v); if(q == _currentWriteEncaps->marshaledMap->end()) { // // 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(v, ++_currentWriteEncaps->writeIndex)); } p = q; } // // Write the index for the instance. // write(-(p->second)); } else { write(0); // Write null pointer. } } void IceInternal::BasicStream::read(PatchFunc patchFunc, void* patchAddr) { if(!_currentReadEncaps) // Lazy initialization. { _readEncapsStack.push_back(ReadEncaps()); _currentReadEncaps = &_readEncapsStack.back(); } if(!_currentReadEncaps->patchMap) // Lazy initialization. { _currentReadEncaps->patchMap = new PatchMap; _currentReadEncaps->unmarshaledMap = new IndexToPtrMap; _currentReadEncaps->typeIdMap = new TypeIdReadMap; } ObjectPtr v; Int index; read(index); if(index == 0) { patchFunc(patchAddr, v); // Null Ptr. return; } if(index < 0 && patchAddr) { PatchMap::iterator p = _currentReadEncaps->patchMap->find(-index); if(p == _currentReadEncaps->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; } // // Append a patch entry for this instance. // PatchEntry e; e.patchFunc = patchFunc; e.patchAddr = patchAddr; p->second.push_back(e); patchPointers(-index, _currentReadEncaps->unmarshaledMap->end(), p); return; } assert(index > 0); while(true) { string id; readTypeId(id); // // Try to find a factory registered for the specific type. // ObjectFactoryPtr userFactory = _instance->servantFactoryManager()->find(id); if(userFactory) { v = userFactory->create(id); } // // If that fails, invoke the default factory if one has been registered. // if(!v) { userFactory = _instance->servantFactoryManager()->find(""); if(userFactory) { v = userFactory->create(id); } } // // There isn't a static factory for Ice::Object, so check for that case now. // We do this *after* the factory inquiries above so that a factory could be // registered for "::Ice::Object". // if(!v && id == Ice::Object::ice_staticId()) { v = new ::Ice::Object; } // // Last chance: check the table of static factories (i.e., automatically generated // factories for concrete classes). // if(!v) { ObjectFactoryPtr of = Ice::factoryTable->getObjectFactory(id); if(of) { v = of->create(id); assert(v); } } if(!v) { // // 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", id, _slicingCat, _instance->logger()); } skipSlice(); // Slice off this derived part -- we don't understand it. continue; } IndexToPtrMap::const_iterator unmarshaledPos = _currentReadEncaps->unmarshaledMap->insert(make_pair(index, v)).first; v->__read(this, false); patchPointers(index, unmarshaledPos, _currentReadEncaps->patchMap->end()); return; } // // We can't possibly end up here: at the very least, the type ID "::Ice::Object" must be recognized, or // client and server were compiled with mismatched Slice definitions. // throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } void IceInternal::BasicStream::write(const UserException& v) { write(v.__usesClasses()); v.__write(this); if(v.__usesClasses()) { writePendingObjects(); } } void IceInternal::BasicStream::throwException() { bool usesClasses; read(usesClasses); string id; read(id); while(!id.empty()) { // // Look for a factory for this ID. // UserExceptionFactoryPtr factory = factoryTable->getExceptionFactory(id); if(factory) { // // Got factory -- get the factory to instantiate the // exception, initialize the exception members, and throw // the exception. // try { factory->createAndThrow(); } catch(UserException& ex) { ex.__read(this, false); if(usesClasses) { readPendingObjects(); } ex.ice_throw(); } } 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("exception", id, _slicingCat, _instance->logger()); } skipSlice(); // Slice off what we don't understand. read(id); // Read type id for next slice. } } // // Getting here should be impossible: we can get here only if the // sender has marshaled a sequence of type IDs, none of which we // have factory for. This means that sender and receiver disagree // about the Slice definitions they use. // throw UnknownUserException(__FILE__, __LINE__); } void IceInternal::BasicStream::writePendingObjects() { if(_currentWriteEncaps && _currentWriteEncaps->toBeMarshaledMap) { while(_currentWriteEncaps->toBeMarshaledMap->size()) { PtrToIndexMap savedMap = *_currentWriteEncaps->toBeMarshaledMap; writeSize(static_cast(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(newMap, newMap.begin())); *_currentWriteEncaps->toBeMarshaledMap = newMap; } } writeSize(0); // Zero marker indicates end of sequence of sequences of instances. } void IceInternal::BasicStream::readPendingObjects() { Int num; do { readSize(num); for(Int k = num; k > 0; --k) { read(0, 0); } } while(num); } void IceInternal::BasicStream::marshalFacets(bool b) { _marshalFacets = b; } void IceInternal::BasicStream::throwUnmarshalOutOfBoundsException(const char* file, int line) { throw UnmarshalOutOfBoundsException(file, line); } void IceInternal::BasicStream::throwMemoryLimitException(const char* file, int line) { throw MemoryLimitException(file, line); } void IceInternal::BasicStream::writeInstance(const ObjectPtr& v, Int index) { write(index); v->__write(this, _marshalFacets); } 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 patchPost 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. // assert( (unmarshaledPos != _currentReadEncaps->unmarshaledMap->end() && patchPos == _currentReadEncaps->patchMap->end()) || (unmarshaledPos == _currentReadEncaps->unmarshaledMap->end() && patchPos != _currentReadEncaps->patchMap->end()) ); if(unmarshaledPos != _currentReadEncaps->unmarshaledMap->end()) { // // We have just unmarshaled an instance -- check if something // needs patching for that instance. // patchPos = _currentReadEncaps->patchMap->find(index); if(patchPos == _currentReadEncaps->patchMap->end()) { return; // We don't have anything to patch for the instance just unmarshaled. } } else { // // We have just unmarshaled an index -- check if we have // unmarshaled the instance for that index yet. // unmarshaledPos = _currentReadEncaps->unmarshaledMap->find(index); if(unmarshaledPos == _currentReadEncaps->unmarshaledMap->end()) { return; // We haven't unmarshaled the instance yet. } } assert(patchPos->second.size() > 0); ObjectPtr v = unmarshaledPos->second; assert(v); // // Patch all pointers that refer to the instance. // for(PatchList::iterator k = patchPos->second.begin(); k != patchPos->second.end(); ++k) { (*k->patchFunc)(k->patchAddr, v); } // // Clear out the patch map for that index -- there is nothing left // to patch for that index for the time being. // _currentReadEncaps->patchMap->erase(patchPos); }