#ifndef BLOCK_LIST_BUFFER__H_ #define BLOCK_LIST_BUFFER__H_ #ifdef _WIN32 #pragma once #endif struct _TBinaryBlock { char * pData; char * pDataOffset; int nSize; }; typedef struct _TBinaryBlock TBinaryBlock; class HBlockListBuffer : public HObject { public: HBlockListBuffer(int nBlockSize) { m_nBlockSize = nBlockSize; m_nTotalSize = 0; //... } ~HBlockListBuffer() { RemoveAll(); } inline size_t GetCount() { return listBinaryBlock.size(); } inline int GetTotalSize() { int nTotalSize = 0; for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { if (iter->nSize > 0) nTotalSize += iter->nSize; } return nTotalSize; } inline bool Enqueue(const char * pData, int nSize) { if (nSize <= 0) //... command, -1 = end mark { TBinaryBlock blockNew; blockNew.nSize = nSize; listBinaryBlock.push_back(blockNew); return true; } if (listBinaryBlock.empty() == false) { #if 1 std::list::iterator iter = listBinaryBlock.end(); iter--; if (iter->nSize <= 0) return false; int nRemainBufer = m_nBlockSize - iter->nSize - (iter->pDataOffset - iter->pData); if (nRemainBufer > nSize) { memcpy(iter->pDataOffset + iter->nSize, pData, nSize); iter->nSize += nSize; return true; } else { if (nRemainBufer > 0) { memcpy(iter->pDataOffset + iter->nSize, pData, nRemainBufer); iter->nSize += nRemainBufer; pData += nRemainBufer; nSize -= nRemainBufer; } } #endif } while (nSize > 0) { TBinaryBlock blockNew; blockNew.pData = (char *)malloc(m_nBlockSize); blockNew.pDataOffset = blockNew.pData; if (nSize <= m_nBlockSize) { memcpy(blockNew.pDataOffset, pData, nSize); blockNew.nSize = nSize; nSize = 0; } else { memcpy(blockNew.pDataOffset, pData, m_nBlockSize); blockNew.nSize = m_nBlockSize; pData += m_nBlockSize; nSize -= m_nBlockSize; } listBinaryBlock.push_back(blockNew); } return true; } inline bool Dequeue(char * pDst, int nCount) { if (nCount > GetTotalSize()) return false; int nRemainSize = nCount; std::list::iterator iter = listBinaryBlock.begin(); while (iter != listBinaryBlock.end()) { if (iter->nSize < 0) return false; if (nRemainSize < nCount) { if (iter->nSize < nRemainSize) { memcpy(pDst, iter->pDataOffset, iter->nSize); pDst += iter->nSize; nRemainSize -= iter->nSize; free(iter->pData); iter = listBinaryBlock.erase(iter); } else { memcpy(pDst, iter->pDataOffset, nRemainSize); if (iter->nSize == nRemainSize) { free(iter->pData); listBinaryBlock.erase(iter); } else { iter->pDataOffset += nRemainSize; iter->nSize -= nRemainSize; } return true; } } else if (iter->nSize > 0) { if (iter->nSize < nCount) { memcpy(pDst, iter->pDataOffset, iter->nSize); pDst += iter->nSize; nRemainSize -= iter->nSize; free(iter->pData); iter = listBinaryBlock.erase(iter); } else { memcpy(pDst, iter->pDataOffset, nCount); if (iter->nSize == nCount) { free(iter->pData); listBinaryBlock.erase(iter); } else { iter->pDataOffset += nCount; iter->nSize -= nCount; } return true; } } } return false; } bool DequeueAll(char * pDst) { std::list::iterator iter = listBinaryBlock.begin(); while (iter != listBinaryBlock.end()) { if (iter->nSize <= 0) //... return false; memcpy(pDst, iter->pDataOffset, iter->nSize); pDst += iter->nSize; free(iter->pData); iter = listBinaryBlock.erase(iter); } return true; } inline bool GetFront(char ** ppData, int * pnSize) { std::list::iterator iter = listBinaryBlock.begin(); if (iter == listBinaryBlock.end()) return false; if (iter->nSize > 0) *ppData = iter->pDataOffset; *pnSize = iter->nSize; return true; } inline void PopFront() { std::list::iterator iter = listBinaryBlock.begin(); if (iter == listBinaryBlock.end()) return; if (iter->nSize > 0) free(iter->pData); listBinaryBlock.erase(iter); } inline bool ReduceFront(int nSize) { if (nSize > m_nBlockSize) return false; std::list::iterator iter = listBinaryBlock.begin(); if (iter == listBinaryBlock.end()) return false; if (iter->nSize <= 0) { return false; } else if (nSize > iter->nSize) { return false; } else if (nSize == iter->nSize) { free(iter->pData); listBinaryBlock.erase(iter); return true; } iter->pDataOffset += nSize; iter->nSize -= nSize; return true; } inline void RemoveAll() { for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { if (iter->nSize > 0) free(iter->pData); } listBinaryBlock.clear(); } HDynamicArray ChangeAndClear(int * pnSize, int nExtra) { *pnSize = GetTotalSize(); if (*pnSize <= 0) return (char *)NULL; char * pBuffer = (char *)malloc(*pnSize + nExtra); char * pOffset = pBuffer; for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { if (iter->nSize > 0) //... { memcpy(pOffset, iter->pDataOffset, iter->nSize); pOffset += iter->nSize; } free(iter->pData); } listBinaryBlock.clear(); return pBuffer; } inline bool Copy(char * pDst, int nStartPos, int nCount) { int nRemainSize = nCount; int i = 0; for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { if (iter->nSize < 0) return false; i += iter->nSize; if (nRemainSize < nCount) { if (iter->nSize < nRemainSize) { memcpy(pDst, iter->pDataOffset, iter->nSize); pDst += iter->nSize; nRemainSize -= iter->nSize; } else { memcpy(pDst, iter->pDataOffset, nRemainSize); return true; } } else if (i > nStartPos) //... { int nBlockRemain = i - nStartPos; int nBlockStartIndex = iter->nSize - nBlockRemain; if (nBlockRemain < nCount) { memcpy(pDst, iter->pDataOffset + nBlockStartIndex, nBlockRemain); pDst += nBlockRemain; nRemainSize -= nBlockRemain; } else { memcpy(pDst, iter->pDataOffset + nBlockStartIndex, nCount); return true; } } } return false; } int SearchChr(int nStartPos, char ch) { int i = 0, j; for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { if (iter->nSize < 0) return -1; if (i + iter->nSize > nStartPos) { for (j = 0; j < iter->nSize; j++) { if (i >= nStartPos && iter->pDataOffset[j] == ch) return i; i++; } } else i += iter->nSize; } return -1; } #ifdef _DEBUG void Print() { printf("Print, count = %d\n", listBinaryBlock.size()); int i = 0; for (std::list::iterator iter = listBinaryBlock.begin(); iter != listBinaryBlock.end(); iter++) { printf("%d, ", i++); if (iter->nSize > 0) { for (int j = 0; j < iter->nSize; j++) putchar(iter->pDataOffset[j]); } putchar('\n'); } } #endif protected: std::list listBinaryBlock; int m_nBlockSize; int m_nTotalSize; }; #endif // BLOCK_LIST_BUFFER__H_