PagedBuffer.h
// PagedBuffer.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2004
#pragma once
#ifndef Ceda_cxUtils_PagedBuffer_H
#define Ceda_cxUtils_PagedBuffer_H
#include "cxUtils.h"
#include "xvector.h"
#include "xstring.h"
#include "Archive.h"
#include "VariableLengthSerialise.h"
#ifdef _MSC_VER
// struct 'X' needs to have dll-interface to be used by clients of class 'Y'
#pragma warning(disable:4251)
#endif
namespace ceda
{
class xostream;
///////////////////////////////////////////////////////////////////////////////////////////////////
// PagedBuffer
class cxUtils_API PagedBuffer
{
private:
typedef octet_t Page;
public:
explicit PagedBuffer(ssize_t pageSize = 4096);
~PagedBuffer();
PagedBuffer(const PagedBuffer& other);
PagedBuffer& operator=(const PagedBuffer& other);
bool operator==(const PagedBuffer& rhs) const;
bool operator!=(const PagedBuffer& rhs) const { return !operator==(rhs); }
void Clear();
void swap(PagedBuffer& rhs);
ssize_t size() const { return m_totalSize; }
ssize_t GetSize() const { return m_totalSize; }
// Set the current write position.
// If necessary the size of the PagedBuffer will grow (padded with zeros) to accommodate the
// given write position.
// If truncateToWritePos is set and the current size of this PagedBuffer exceeds the given
// write position then this PagedBuffer is truncated to the given write position.
void SetWritePos(ssize_t pos, bool truncateToWritePos);
// Write the given buffer at the current write position.
// If necessary the size of this PagedBuffer will grow to accommodate the given data.
// The write position is advanced by the given number of bytes.
void Write(const void* buffer, ssize_t numBytes);
// Write the contents of the PagedBuffer to the given buffer
void WriteTo(octet_t* buffer) const;
// Write the sequence of octets in this PagedBuffer to the given IOutputStream.
void WriteTo(IOutputStream& os) const;
// Write the sequence of octets in this PagedBuffer to the given xvector<octet_t>.
void WriteTo(xvector<octet_t>& b) const;
// Write the sequence of octets in this PagedBuffer to the given Archive.
template<typename Archive>
void WriteContent(Archive& ar) const
{
const ssize_t last = m_numPages - 1; // index of the last page
if (last >= 0)
{
for (ssize_t i=0 ; i < last ; ++i)
{
ar.WriteBuffer(m_pages[i],m_pageSize);
}
const ssize_t x = m_totalSize - last*m_pageSize;
cxAssert(1 <= x && x <= m_pageSize);
ar.WriteBuffer(m_pages[last],x);
}
}
template<typename Archive>
void Serialise(Archive& ar) const
{
ar << AsCompressedInt(size());
WriteContent(ar);
}
void Deserialise(InputArchive& ar);
void GetString(xstring& s);
class cxUtils_API Reader
{
cxNotCloneable(Reader)
public:
// Note that it is permissible for a PagedBuffer::Reader to bind to its PageBuffer before data has
// been written to the PagedBuffer.
Reader(const PagedBuffer& pb);
ssize_t GetPos() const;
void SetPos(ssize_t pos);
ssize_t Read(void* buffer, ssize_t numBytes);
private:
const PagedBuffer& m_pb;
ssize_t m_pageIndex;
const Page* m_rpage; // Current page being read
ssize_t m_rpos; // Position within current page
ssize_t m_overallPos; // Overall position
};
private:
void CopyFrom(const PagedBuffer& other);
// Set new size without regard for the current write position
void SetSize(ssize_t size);
#ifdef CEDA_CHECK_ASSERTIONS
void Validate() const;
#endif
private:
typedef xvector<Page*> PAGES;
ssize_t m_pageSize;
PAGES m_pages;
ssize_t m_numPages;
ssize_t m_totalSize;
ssize_t m_writePos; // Current write position in range [0,m_totalSize]
friend class Reader;
};
cxUtils_API void DumpPagedBuffer(xostream& os, ssize_t numPerLine, const PagedBuffer& pb);
cxUtils_API xostream& operator<<(xostream& os, const PagedBuffer& pb);
} // namespace ceda
#endif // include guard