blob: 723b0ff28790178a4e4d879a237d8799823d29a4 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @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)