MemCacheClient

ReadWriteBuffer.cpp

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