| /* ----------------------------------------------------------------------- *//** |
| * |
| * @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 <class T, bool IsMutable> |
| struct DynamicStructType { |
| typedef Ref<T, IsMutable> type; |
| }; |
| |
| template <bool IsMutable> |
| struct DynamicStructType<eigen_integration::ColumnVector, IsMutable> { |
| typedef eigen_integration::HandleMap< |
| typename boost::mpl::if_c<IsMutable, |
| eigen_integration::ColumnVector, |
| const eigen_integration::ColumnVector>::type, |
| TransparentHandle<double, IsMutable> > type; |
| }; |
| |
| template <bool IsMutable> |
| struct DynamicStructType<eigen_integration::IntegerVector, IsMutable> { |
| typedef eigen_integration::HandleMap< |
| typename boost::mpl::if_c<IsMutable, |
| eigen_integration::IntegerVector, |
| const eigen_integration::IntegerVector>::type, |
| TransparentHandle<int, IsMutable> > type; |
| }; |
| |
| template <bool IsMutable> |
| struct DynamicStructType<eigen_integration::Matrix, IsMutable> { |
| typedef eigen_integration::HandleMap< |
| typename boost::mpl::if_c<IsMutable, |
| eigen_integration::Matrix, |
| const eigen_integration::Matrix>::type, |
| TransparentHandle<double, IsMutable> > type; |
| }; |
| |
| // DynamicStructRootContainer<Storage, TypeTraits> |
| |
| template <class Storage, template <class T> class TypeTraits> |
| DynamicStructRootContainer<Storage, TypeTraits>::DynamicStructRootContainer( |
| const DynamicStructRootContainer<Storage, TypeTraits>::Storage_type& |
| inStorage) |
| : mByteStreamBuf(inStorage) { } |
| |
| template <class Storage, template <class T> class TypeTraits> |
| const typename DynamicStructRootContainer<Storage, TypeTraits>::StreamBuf_type& |
| DynamicStructRootContainer<Storage, TypeTraits>::streambuf() const { |
| return mByteStreamBuf; |
| } |
| |
| template <class Storage, template <class T> class TypeTraits> |
| typename DynamicStructRootContainer<Storage, TypeTraits>::StreamBuf_type& |
| DynamicStructRootContainer<Storage, TypeTraits>::streambuf() { |
| return |
| const_cast<StreamBuf_type&>( |
| static_cast<const DynamicStructRootContainer*>(this)->streambuf() |
| ); |
| } |
| |
| |
| // DynamicStructBase<Derived, Container, IsMutable> |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| DynamicStructBase<Derived, Container, IsMutable>::DynamicStructBase( |
| Init_type& inContainer) |
| : mContainer(inContainer) { } |
| |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| const typename DynamicStructBase<Derived, Container, IsMutable> |
| ::RootContainer_type& |
| DynamicStructBase<Derived, Container, IsMutable>::rootContainer() const { |
| return mContainer.rootContainer(); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| void |
| DynamicStructBase<Derived, Container, IsMutable>::initialize() { } |
| |
| |
| template <class Derived, bool IsMutable, class Storage, |
| template <class T> class TypeTraits> |
| inline |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable> |
| ::DynamicStructBase(Init_type& inStorage) |
| : mContainer(inStorage), mByteStream(&mContainer.streambuf()) { } |
| |
| template <class Derived, bool IsMutable, class Storage, |
| template <class T> class TypeTraits> |
| inline |
| const typename DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, |
| IsMutable>::RootContainer_type& |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable> |
| ::rootContainer() const { |
| |
| return static_cast<RootContainer_type&>(*this); |
| } |
| |
| template <class Derived, bool IsMutable, class Storage, template <class T> class TypeTraits> |
| inline |
| const typename DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, |
| IsMutable>::Storage_type& |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable> |
| ::storage() const { |
| |
| return mContainer.streambuf().storage(); |
| } |
| |
| template <class Derived, bool IsMutable, class Storage, |
| template <class T> class TypeTraits> |
| inline |
| const typename DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable> |
| ::ByteStream_type& |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable>::byteStream() |
| const { |
| |
| return mByteStream; |
| } |
| |
| |
| // DynamicStructBase<Derived, Container, Mutable> |
| |
| template <class Derived, class Container> |
| template <class SubStruct> |
| void |
| DynamicStructBase<Derived, Container, Mutable>::setSize( |
| SubStruct& inSubStruct, size_t inSize) { |
| |
| Base::mContainer.setSize(inSubStruct, inSize); |
| } |
| |
| /** |
| * @brief Change the size of a sub-struct |
| */ |
| template <class Derived, class Storage, template <class T> class TypeTraits> |
| template <class SubStruct> |
| inline |
| void |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, 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<Derived&>(*this); |
| |
| if (mByteStream.eof()) |
| throw std::runtime_error("Out-of-bounds byte-string access " |
| "detected during resize."); |
| } |
| |
| |
| // DynamicStructBase<Derived, DynamicStructRootContainer<Storage, TypeTraits>, |
| // IsMutable> |
| |
| template <class Derived, bool IsMutable, class Storage, |
| template <class T> class TypeTraits> |
| inline |
| void |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, IsMutable>::initialize() { |
| |
| mByteStream.seek(0, std::ios_base::beg); |
| mByteStream >> static_cast<Derived&>(*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<Derived&>(*this); |
| |
| if (mByteStream.eof()) |
| throw std::runtime_error("Out-of-bounds byte-string access " |
| "detected during initialization of mutable dynamic struct."); |
| } |
| } |
| |
| |
| // DynamicStructBase<Derived, DynamicStructRootContainer<Storage, TypeTraits>, |
| // Mutable> |
| |
| /* FIXME: Remove this. |
| |
| template <class Derived, class Storage, template <class T> class TypeTraits> |
| inline |
| void |
| DynamicStructBase<Derived, |
| DynamicStructRootContainer<Storage, TypeTraits>, Mutable>::initialize() { |
| |
| mByteStream.seek(0, std::ios_base::beg); |
| mByteStream >> static_cast<Derived&>(*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<Derived&>(*this); |
| |
| if (mByteStream.eof()) |
| throw std::runtime_error("Out-of-bounds byte-string access " |
| "detected during initialization of mutable dynamic struct."); |
| } |
| } |
| */ |
| |
| // DynamicStruct<Derived, Container, IsMutable> |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| DynamicStruct<Derived, Container, IsMutable>::DynamicStruct(Init_type& inInitialization) |
| : Base(inInitialization) { } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| typename DynamicStruct<Derived, Container, IsMutable>::RootContainer_type& |
| DynamicStruct<Derived, Container, IsMutable>::rootContainer() { |
| return const_cast<RootContainer_type&>( |
| static_cast<const DynamicStruct*>(this)->rootContainer() |
| ); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| typename DynamicStruct<Derived, Container, IsMutable>::Storage_type& |
| DynamicStruct<Derived, Container, IsMutable>::storage() { |
| return const_cast<Storage_type&>( |
| static_cast<const DynamicStruct*>(this)->storage() |
| ); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| typename DynamicStruct<Derived, Container, IsMutable>::ByteStream_type& |
| DynamicStruct<Derived, Container, IsMutable>::byteStream() { |
| return const_cast<ByteStream_type&>( |
| static_cast<const DynamicStruct*>(this)->byteStream() |
| ); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| size_t |
| DynamicStruct<Derived, Container, IsMutable>::begin() const { |
| return mBegin; |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| size_t |
| DynamicStruct<Derived, Container, IsMutable>::end() const { |
| return mEnd; |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| typename DynamicStruct<Derived, Container, IsMutable>::char_type* |
| DynamicStruct<Derived, Container, IsMutable>::ptr() { |
| return const_cast<char_type*>( |
| static_cast<const DynamicStruct*>(this)->ptr() |
| ); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| const typename DynamicStruct<Derived, Container, IsMutable>::char_type* |
| DynamicStruct<Derived, Container, IsMutable>::ptr() const { |
| return this->storage().ptr() + begin(); |
| } |
| |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| size_t |
| DynamicStruct<Derived, Container, IsMutable>::size() const { |
| return end() - begin(); |
| } |
| |
| /* |
| * Note that there is also a version for |
| * DynamicStruct<Derived, Container, Mutable>! |
| */ |
| template <class Derived, class Container, bool IsMutable> |
| inline |
| void |
| DynamicStruct<Derived, Container, IsMutable>::bindToStream( |
| typename DynamicStruct<Derived, Container, IsMutable>::ByteStream_type& |
| inStream) { |
| |
| inStream.template seek<ByteStream_type::maximumAlignment>(0, |
| std::ios_base::cur); |
| |
| if (!inStream.isInDryRun()) |
| this->mBegin = inStream.tell(); |
| |
| static_cast<Derived*>(this)->bind(inStream); |
| inStream.template seek<ByteStream_type::maximumAlignment>(0, |
| std::ios_base::cur); |
| |
| if (!inStream.isInDryRun()) |
| this->mEnd = inStream.tell(); |
| } |
| |
| |
| // DynamicStruct<Derived, Container, Mutable> |
| |
| template <class Derived, class Container> |
| inline |
| DynamicStruct<Derived, Container, Mutable>::DynamicStruct( |
| Init_type& inInitialization) |
| : Base(inInitialization), mSizeIsLocked(false) { } |
| |
| |
| /** |
| * @brief Internal function to change size. |
| * |
| * This assumes that \c inSize is the correct size! |
| */ |
| template <class Derived, class Container> |
| inline |
| void |
| DynamicStruct<Derived, Container, Mutable>::setSize(size_t inSize) { |
| this->setSize(static_cast<Derived&>(*this), inSize); |
| Base::mEnd = Base::mBegin + inSize; |
| } |
| |
| template <class Derived, class Container> |
| inline |
| void |
| DynamicStruct<Derived, Container, Mutable>::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<Derived&>(*this); |
| dryRun.leave(); |
| |
| stream.template seek<ByteStream_type::maximumAlignment>(0, |
| std::ios_base::cur); |
| size_t newEnd = stream.tell(); |
| this->setSize(newEnd - begin); |
| } |
| |
| template <class Derived, class Container> |
| template <class OtherDerived> |
| DynamicStruct<Derived, Container, Mutable>& |
| DynamicStruct<Derived, Container, Mutable>::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 |
| * <tt>mSizeIsLocked == true</tt>. |
| */ |
| template <class Derived, class Container> |
| inline |
| void |
| DynamicStruct<Derived, Container, Mutable>::bindToStream( |
| typename DynamicStruct<Derived, Container, Mutable>::ByteStream_type& |
| inStream) { |
| |
| inStream.template seek<ByteStream_type::maximumAlignment>(0, |
| std::ios_base::cur); |
| |
| size_t begin = inStream.tell(); |
| size_t size = this->size(); |
| |
| if (!inStream.isInDryRun()) |
| this->mBegin = begin; |
| |
| static_cast<Derived*>(this)->bind(inStream); |
| |
| if (mSizeIsLocked) |
| inStream.seek(begin + size, std::ios_base::beg); |
| else |
| inStream.template seek<ByteStream_type::maximumAlignment>(0, |
| std::ios_base::cur); |
| |
| if (!inStream.isInDryRun()) |
| this->mEnd = inStream.tell(); |
| } |
| |
| } // namespace dbal |
| |
| } // namespace madlib |
| |
| #endif // defined(MADLIB_POSTGRES_DYNAMICSTRUCT_IMPL_HPP) |