/* ----------------------------------------------------------------------- *//** * * @file OutputStreamBufferBase_impl.hpp * *//* ----------------------------------------------------------------------- */ #ifndef MADLIB_DBAL_OUTPUTSTREAMBUFFERBASE_IMPL_HPP #define MADLIB_DBAL_OUTPUTSTREAMBUFFERBASE_IMPL_HPP #include // Needed for std::memcpy namespace madlib { namespace dbal { /** * @internal One extra byte is allocated for the terminating null character. */ template OutputStreamBufferBase::OutputStreamBufferBase() : mAllocator(), mStorageSize(kInitialBufferSize), mStorage(mAllocator.allocate(mStorageSize + 1)) { this->setp(mStorage, mStorage + mStorageSize); } template OutputStreamBufferBase::~OutputStreamBufferBase() { mAllocator.deallocate(mStorage, mStorageSize + 1); } /** * @brief Output a string * * Subclasses are required to implement this method and to feed the message * to the DBMS-specific logging routine. * @param inMsg Null-terminated string to be output. * @param inLength Length of inMsg (for convenience). */ template void OutputStreamBufferBase::output(C* inMsg, std::size_t inLength) const { static_cast(this)->output(inMsg, inLength); } /** * @brief Handle case when stream receives a character that does not fit * into the current buffer any more * * This function will allocate a new buffer of twice the old buffer size. If * the buffer has already the maximum size kMaxBufferSize, eof is returned * to indicate that the buffer cannot take any more input before a flush. */ template typename OutputStreamBufferBase::int_type OutputStreamBufferBase::overflow(int_type c) { if (this->pptr() >= this->epptr()) { if (mStorageSize >= kMaxBufferSize) return traits_type::eof(); uint32_t newStorageSize = mStorageSize * 2; C* newStorage = mAllocator.allocate(newStorageSize + 1); std::copy(mStorage, mStorage + mStorageSize, newStorage); mAllocator.deallocate(mStorage, mStorageSize + 1); mStorage = newStorage; madlib_assert( this->pptr() == this->epptr() && this->pptr() - this->pbase() == static_cast(mStorageSize), std::logic_error("Internal error: Logging buffer has become " "inconsistent")); this->setp(mStorage, mStorage + newStorageSize); this->pbump(mStorageSize); mStorageSize = newStorageSize; } else if (c == traits_type::eof()) return traits_type::eof(); *this->pptr() = static_cast(c); this->pbump(1); return traits_type::not_eof(c); } /** * @brief Flush and reset buffer. */ template int OutputStreamBufferBase::sync() { std::ptrdiff_t length = this->pptr() - this->pbase(); mStorage[length] = '\0'; output(mStorage, length); this->setp(mStorage, mStorage + mStorageSize); return 0; } } // namespace dbal } // namespace madlib #endif // defined(MADLIB_OUTPUTSTREAMBUFFERBASE_IMPL_HPP)