/* ----------------------------------------------------------------------- *//** * * @file DynamicStruct_impl.hpp * *//* ----------------------------------------------------------------------- */ #ifndef MADLIB_POSTGRES_DYNAMICSTRUCT_IMPL_HPP #define MADLIB_POSTGRES_DYNAMICSTRUCT_IMPL_HPP namespace madlib { namespace dbal { /** * @brief Meta function for mapping types to the dynamic-struct mapped type * * @tparam T Desired type that is to be stored in the dynamic struct * @tparam IsMutable Indicator if the dynamic struct is mutable */ template struct DynamicStructType { typedef Ref type; }; template struct DynamicStructType { typedef eigen_integration::HandleMap< typename boost::mpl::if_c::type, TransparentHandle > type; }; template struct DynamicStructType { typedef eigen_integration::HandleMap< typename boost::mpl::if_c::type, TransparentHandle > type; }; template struct DynamicStructType { typedef eigen_integration::HandleMap< typename boost::mpl::if_c::type, TransparentHandle > type; }; // DynamicStructRootContainer template class TypeTraits> DynamicStructRootContainer::DynamicStructRootContainer( const DynamicStructRootContainer::Storage_type& inStorage) : mByteStreamBuf(inStorage) { } template class TypeTraits> const typename DynamicStructRootContainer::StreamBuf_type& DynamicStructRootContainer::streambuf() const { return mByteStreamBuf; } template class TypeTraits> typename DynamicStructRootContainer::StreamBuf_type& DynamicStructRootContainer::streambuf() { return const_cast( static_cast(this)->streambuf() ); } // DynamicStructBase template inline DynamicStructBase::DynamicStructBase( Init_type& inContainer) : mContainer(inContainer) { } template inline const typename DynamicStructBase ::RootContainer_type& DynamicStructBase::rootContainer() const { return mContainer.rootContainer(); } template void DynamicStructBase::initialize() { } template class TypeTraits> inline DynamicStructBase, IsMutable> ::DynamicStructBase(Init_type& inStorage) : mContainer(inStorage), mByteStream(&mContainer.streambuf()) { } template class TypeTraits> inline const typename DynamicStructBase, IsMutable>::RootContainer_type& DynamicStructBase, IsMutable> ::rootContainer() const { return static_cast(*this); } template class TypeTraits> inline const typename DynamicStructBase, IsMutable>::Storage_type& DynamicStructBase, IsMutable> ::storage() const { return mContainer.streambuf().storage(); } template class TypeTraits> inline const typename DynamicStructBase, IsMutable> ::ByteStream_type& DynamicStructBase, IsMutable>::byteStream() const { return mByteStream; } // DynamicStructBase template template void DynamicStructBase::setSize( SubStruct& inSubStruct, size_t inSize) { Base::mContainer.setSize(inSubStruct, inSize); } /** * @brief Change the size of a sub-struct */ template class TypeTraits> template inline void DynamicStructBase, Mutable>::setSize( SubStruct& inSubStruct, size_t inSize) { if (inSubStruct.size() == inSize) return; typename Container_type::StreamBuf_type& streamBuf = mContainer.streambuf(); streamBuf.resize(streamBuf.size() + inSize - inSubStruct.size(), inSubStruct.end()); mByteStream.seek(0, std::ios_base::beg); mByteStream >> static_cast(*this); if (mByteStream.eof()) throw std::runtime_error("Out-of-bounds byte-string access " "detected during resize."); } // DynamicStructBase, // IsMutable> template class TypeTraits> inline void DynamicStructBase, IsMutable>::initialize() { mByteStream.seek(0, std::ios_base::beg); mByteStream >> static_cast(*this); if (mByteStream.eof()) { // The assumption is that either // a) we have a valid dynamic struct, in which case we do not end here // b) we have an uninitialized dynamic struct, which only consists of // (too few) zero bytes. // If (b) is violated, then mByteStream.tell() might not have the // correct size information. typedef typename Container_type::StreamBuf_type StreamBuf_type; StreamBuf_type& streamBuf = mContainer.streambuf(); streamBuf = StreamBuf_type(mByteStream.tell()); mByteStream.seek(0, std::ios_base::beg); mByteStream >> static_cast(*this); if (mByteStream.eof()) throw std::runtime_error("Out-of-bounds byte-string access " "detected during initialization of mutable dynamic struct."); } } // DynamicStructBase, // Mutable> /* FIXME: Remove this. template class TypeTraits> inline void DynamicStructBase, Mutable>::initialize() { mByteStream.seek(0, std::ios_base::beg); mByteStream >> static_cast(*this); if (mByteStream.eof()) { typename Container_type::StreamBuf_type& streamBuf = mContainer.streambuf(); streamBuf.resize(mByteStream.tell(), streamBuf.size()); mByteStream.seek(0, std::ios_base::beg); mByteStream >> static_cast(*this); if (mByteStream.eof()) throw std::runtime_error("Out-of-bounds byte-string access " "detected during initialization of mutable dynamic struct."); } } */ // DynamicStruct template inline DynamicStruct::DynamicStruct(Init_type& inInitialization) : Base(inInitialization) { } template inline typename DynamicStruct::RootContainer_type& DynamicStruct::rootContainer() { return const_cast( static_cast(this)->rootContainer() ); } template inline typename DynamicStruct::Storage_type& DynamicStruct::storage() { return const_cast( static_cast(this)->storage() ); } template inline typename DynamicStruct::ByteStream_type& DynamicStruct::byteStream() { return const_cast( static_cast(this)->byteStream() ); } template inline size_t DynamicStruct::begin() const { return mBegin; } template inline size_t DynamicStruct::end() const { return mEnd; } template inline typename DynamicStruct::char_type* DynamicStruct::ptr() { return const_cast( static_cast(this)->ptr() ); } template inline const typename DynamicStruct::char_type* DynamicStruct::ptr() const { return this->storage().ptr() + begin(); } template inline size_t DynamicStruct::size() const { return end() - begin(); } /* * Note that there is also a version for * DynamicStruct! */ template inline void DynamicStruct::bindToStream( typename DynamicStruct::ByteStream_type& inStream) { inStream.template seek(0, std::ios_base::cur); if (!inStream.isInDryRun()) this->mBegin = inStream.tell(); static_cast(this)->bind(inStream); inStream.template seek(0, std::ios_base::cur); if (!inStream.isInDryRun()) this->mEnd = inStream.tell(); } // DynamicStruct template inline DynamicStruct::DynamicStruct( Init_type& inInitialization) : Base(inInitialization), mSizeIsLocked(false) { } /** * @brief Internal function to change size. * * This assumes that \c inSize is the correct size! */ template inline void DynamicStruct::setSize(size_t inSize) { this->setSize(static_cast(*this), inSize); Base::mEnd = Base::mBegin + inSize; } template inline void DynamicStruct::resize() { size_t begin = this->begin(); ByteStream_type& stream = this->byteStream(); stream.seek(begin, std::ios_base::beg); // We use an RAII object here that ensure that dry mode will also be // left in case of exceptions typename ByteStream_type::DryRun dryRun(stream); stream >> static_cast(*this); dryRun.leave(); stream.template seek(0, std::ios_base::cur); size_t newEnd = stream.tell(); this->setSize(newEnd - begin); } template template DynamicStruct& DynamicStruct::copy( const OtherDerived &inOtherStruct) { if (this->size() != inOtherStruct.size()) { this->setSize(inOtherStruct.size()); mSizeIsLocked = true; } // We now have enough space to copy everything from inOtherStruct std::copy(inOtherStruct.ptr(), inOtherStruct.ptr() + this->size(), this->ptr()); mSizeIsLocked = false; this->resize(); return *this; } /* * This method is overridden to take special care of the case when * mSizeIsLocked == true. */ template inline void DynamicStruct::bindToStream( typename DynamicStruct::ByteStream_type& inStream) { inStream.template seek(0, std::ios_base::cur); size_t begin = inStream.tell(); size_t size = this->size(); if (!inStream.isInDryRun()) this->mBegin = begin; static_cast(this)->bind(inStream); if (mSizeIsLocked) inStream.template seek(begin + size, std::ios_base::beg); else inStream.template seek(0, std::ios_base::cur); if (!inStream.isInDryRun()) this->mEnd = inStream.tell(); } } // namespace dbal } // namespace madlib #endif // defined(MADLIB_POSTGRES_DYNAMICSTRUCT_IMPL_HPP)