00001
00006 #include <new>
00007 #include <stdexcept>
00008
00009 #include "ReadWriteBuffer.h"
00010
00012
00013
00014 ReadWriteBuffer::ReadWriteBuffer()
00015 : mBufSiz(0)
00016 , mBufLen(0)
00017 , mBufIdx(0)
00018 , mGrowBy(1024)
00019 , mBuf(NULL)
00020 {
00021 }
00022
00023 ReadWriteBuffer::ReadWriteBuffer(
00024 const ReadWriteBuffer & rhs
00025 )
00026 : mBufSiz(0)
00027 , mBufLen(0)
00028 , mBufIdx(0)
00029 , mGrowBy(1024)
00030 , mBuf(NULL)
00031 {
00032 operator=(rhs);
00033 }
00034
00035 ReadWriteBuffer &
00036 ReadWriteBuffer::operator=(
00037 const ReadWriteBuffer & rhs
00038 )
00039 {
00040 Deallocate();
00041 if (rhs.mBufSiz > 0) {
00042 SetInternalBuffer(rhs.mBufSiz, rhs.mGrowBy ? rhs.mGrowBy : 1024);
00043 char * pBuf = GetWriteBuffer(rhs.mBufLen);
00044 memcpy(pBuf, rhs.mBuf, rhs.mBufLen);
00045 mBufIdx = rhs.mBufIdx;
00046 mBufLen = rhs.mBufLen;
00047 }
00048 return *this;
00049 }
00050
00051 ReadWriteBuffer::~ReadWriteBuffer()
00052 {
00053 Deallocate();
00054 }
00055
00056 void
00057 ReadWriteBuffer::Deallocate()
00058 {
00059 if (mBuf && mGrowBy) {
00060 free(mBuf);
00061 }
00062
00063 mBuf = NULL;
00064 mBufSiz = 0;
00065 mBufIdx = 0;
00066 mBufLen = 0;
00067 mGrowBy = 1024;
00068 }
00069
00070 void
00071 ReadWriteBuffer::SetEmpty()
00072 {
00073 mBufIdx = 0;
00074 mBufLen = 0;
00075 }
00076
00077 void
00078 ReadWriteBuffer::SetExternalBuffer(
00079 void * a_pBuf,
00080 size_t a_nBufSiz,
00081 size_t a_nBufLen
00082 )
00083 {
00084 if (!a_pBuf) throw std::invalid_argument("a_pBuf");
00085 if (a_nBufSiz < 1) throw std::invalid_argument("a_nBufSiz");
00086 if (a_nBufLen > a_nBufSiz) throw std::invalid_argument("a_nBufLen");
00087
00088 Deallocate();
00089
00090 mBuf = (char *) a_pBuf;
00091 mBufSiz = a_nBufSiz;
00092 mBufIdx = 0;
00093 mBufLen = a_nBufLen;
00094 mGrowBy = 0;
00095 }
00096
00101 static inline size_t roundup(size_t nValue, size_t nBlock) {
00102 if ((nValue % nBlock) != 0) {
00103 nValue = (nValue / nBlock) * nBlock + nBlock;
00104 }
00105 return nValue;
00106 }
00107
00108 void
00109 ReadWriteBuffer::SetInternalBuffer(
00110 size_t a_nInitialSize,
00111 size_t a_nGrowBy
00112 )
00113 {
00114 if (a_nInitialSize < 1) throw std::invalid_argument("a_nInitialSize");
00115 if (a_nGrowBy < 1) throw std::invalid_argument("a_nGrowBy");
00116
00117 Deallocate();
00118
00119
00120 a_nInitialSize = roundup(a_nInitialSize, a_nGrowBy);
00121 mBuf = (char *) malloc(a_nInitialSize);
00122 if (!mBuf) throw std::bad_alloc();
00123 mBufSiz = a_nInitialSize;
00124 mGrowBy = a_nGrowBy;
00125 }
00126
00127 char *
00128 ReadWriteBuffer::GetWriteBuffer(
00129 size_t a_nMinBytes
00130 )
00131 {
00132 if (mBufLen + a_nMinBytes > mBufSiz) {
00133 if (0 == mGrowBy) throw std::overflow_error("external buffer full");
00134 size_t nNewSiz = mBufSiz + roundup(a_nMinBytes, mGrowBy);
00135
00136 char * pBuf = (char *) realloc(mBuf, nNewSiz);
00137 if (!pBuf) throw std::bad_alloc();
00138
00139 mBuf = pBuf;
00140 mBufSiz = nNewSiz;
00141 }
00142 return mBuf + mBufLen;
00143 }
00144
00145 void
00146 ReadWriteBuffer::CommitWriteBytes(
00147 size_t a_nBytes
00148 )
00149 {
00150 if (mBufLen + a_nBytes > mBufSiz) throw std::invalid_argument("a_nBytes");
00151 mBufLen += a_nBytes;
00152 }
00153
00154 size_t
00155 ReadWriteBuffer::GetWriteSize() const
00156 {
00157 return mBufSiz - mBufLen;
00158 }
00159
00160 void
00161 ReadWriteBuffer::WriteBytes(
00162 const void * a_pBuf,
00163 size_t a_nBufLen
00164 )
00165 {
00166 char * pBuf = GetWriteBuffer(a_nBufLen);
00167 memcpy(pBuf, a_pBuf, a_nBufLen);
00168 CommitWriteBytes(a_nBufLen);
00169 }
00170
00171 const char *
00172 ReadWriteBuffer::GetReadBuffer() const
00173 {
00174 return mBuf + mBufIdx;
00175 }
00176
00177 void
00178 ReadWriteBuffer::CommitReadBytes(
00179 size_t a_nBytes
00180 )
00181 {
00182 if (mBufIdx + a_nBytes > mBufLen) throw std::invalid_argument("a_nBytes");
00183 mBufIdx += a_nBytes;
00184 }
00185
00186 size_t
00187 ReadWriteBuffer::GetReadSize() const
00188 {
00189 return mBufLen - mBufIdx;
00190 }
00191
00192 void
00193 ReadWriteBuffer::Compact()
00194 {
00195 if (GetReadSize() > 0) {
00196 memmove(mBuf, GetReadBuffer(), GetReadSize());
00197 }
00198
00199 mBufLen -= mBufIdx;
00200 mBufIdx = 0;
00201 }
00202
00203 bool
00204 ReadWriteBuffer::operator==(
00205 const ReadWriteBuffer & rhs
00206 ) const
00207 {
00208 if (GetReadSize() != rhs.GetReadSize()) {
00209 return false;
00210 }
00211 return 0 == memcmp(GetReadBuffer(), rhs.GetReadBuffer(), GetReadSize());
00212 }