Index: ext/libicpf/libicpf.vcproj =================================================================== diff -u -N -re17c80d36eaa0430313e7d1058aa7a301d1510af -r6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f --- ext/libicpf/libicpf.vcproj (.../libicpf.vcproj) (revision e17c80d36eaa0430313e7d1058aa7a301d1510af) +++ ext/libicpf/libicpf.vcproj (.../libicpf.vcproj) (revision 6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f) @@ -1,239 +1,245 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: ext/libicpf/src/circ_buffer.cpp =================================================================== diff -u -N --- ext/libicpf/src/circ_buffer.cpp (revision 0) +++ ext/libicpf/src/circ_buffer.cpp (revision 6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f) @@ -0,0 +1,496 @@ +/*************************************************************************** + * Copyright (C) 2004 by J�zef Starosczyk * + * ixen2@o2.pl * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "circ_buffer.h" +#include +#include +#include +#include + +BEGIN_ICPF_NAMESPACE + +// amount of bytes by which the buffer size will be incremented +// if there is one byte to be put in a full buffer +#define _BUFFER_INC (size_t)512ULL + +// if there is at least _BUFFER_DEC free space in the buffer then the buffer +// will be shrank (shrinked?) +#define _BUFFER_DEC (size_t)4096ULL + +// specifies if circular buffer should shrink the buffer size if there is too much free +// space in the buffer +#define _USE_SHRINKING 1 + +// if defined to 1 then function ForwardSeek will empty the whole +// internal buffer if it does not find the specified value inside of it +#define _FAILSEEK_TRUNCATES 1 + +circular_buffer::circular_buffer() +{ + m_pbyBuffer=NULL; + m_tSize=0; + m_tDataSize=0; + m_tBitsAtEndCount=0; +} + +circular_buffer::circular_buffer(const circular_buffer& rSrc) +{ + copy_from(rSrc); +} + +circular_buffer::~circular_buffer() +{ + destroy(); +} + +circular_buffer& circular_buffer::operator=(const circular_buffer& rSrc) +{ + // delete the old stuff + destroy(); + copy_from(rSrc); + + return *this; +} + +void circular_buffer::copy_from(const circular_buffer& rSrc) +{ + if (rSrc.m_pbyBuffer && rSrc.m_tSize > 0) + { + // copy the old stuff + m_pbyBuffer=new byte_t[rSrc.m_tSize]; + memcpy(m_pbyBuffer, rSrc.m_pbyBuffer, rSrc.m_tDataSize); + m_tSize=rSrc.m_tSize; + m_tDataSize=rSrc.m_tDataSize; + } + else + { + m_pbyBuffer=NULL; + m_tSize=0; + m_tDataSize=0; + } +} + +void circular_buffer::destroy() +{ + delete [] m_pbyBuffer; + m_pbyBuffer=NULL; + m_tSize=0; + m_tDataSize=0; +} + +void circular_buffer::push_data(const byte_t* pbyBuffer, size_t tCount) +{ + // check if there is enough space + if (m_tDataSize+tCount > m_tSize) + resize_buffer(m_tDataSize+tCount); + + // now there is enough space - fill it + memcpy(m_pbyBuffer+m_tDataSize, pbyBuffer, tCount); + + // increase the counters + m_tDataSize+=tCount; +} + +void circular_buffer::push_data(circular_buffer& rcb) +{ + if (rcb.m_pbyBuffer && rcb.m_tDataSize) + push_data(rcb.m_pbyBuffer, rcb.m_tDataSize); +} + +// pushes length and a string +void circular_buffer::push_string(const char_t* pszString) +{ + if (pszString) + { + ulong_t ulLen=(ulong_t)(strlen(pszString)+1); + push_ulong(ulLen); + push_data((const uchar_t*)pszString, ulLen); + } + else + { + push_ulong(0); + } +} + +void circular_buffer::push_ulonglong(ull_t ull) +{ + push_data((uchar_t*)&ull, sizeof(ull_t)); +} + +// pushes an unsigned long value +void circular_buffer::push_ulong(ulong_t ulData) +{ + push_data((uchar_t*)&ulData, sizeof(ulong_t)); +} + +void circular_buffer::push_ushort(ushort_t wData) +{ + push_data((uchar_t*)&wData, sizeof(ushort_t)); +} + +void circular_buffer::push_uchar(uchar_t byData) +{ + push_data(&byData, 1); +} + +size_t circular_buffer::pop_data(byte_t* pbyBuffer, size_t tCount) +{ + if (m_pbyBuffer == NULL || m_tDataSize == 0) + return 0; + + // how much data we are going to spare + size_t tRealCount=tCount; + if (m_tDataSize < tRealCount) + tRealCount=m_tDataSize; + + // copy the data + memcpy(pbyBuffer, m_pbyBuffer, tRealCount); + + // now move the data to beginning + skip_bytes(tRealCount); +#if _USE_SHRINKING == 1 + shrink_buffer(); +#endif + return tRealCount; +} + +bool circular_buffer::pop_ulonglong(ull_t* pull) +{ + return (pop_data((byte_t*)pull, sizeof(ull_t)) == sizeof(ull_t)); +} + +bool circular_buffer::pop_ulong(ulong_t* pul) +{ + return (pop_data((byte_t*)pul, sizeof(ulong_t)) == sizeof(ulong_t)); +} + +bool circular_buffer::pop_ushort(ushort_t* pw) +{ + return (pop_data((byte_t*)pw, sizeof(ushort_t)) == sizeof(ushort_t)); +} + +bool circular_buffer::pop_uchar(uchar_t* pby) +{ + return (pop_data((byte_t*)pby, 1) == 1); +} + +long circular_buffer::pop_string(char_t** pszString) +{ + ulong_t ul; + if (!pop_ulong(&ul)) + { + *pszString=NULL; + return -1; + } + + if (ul == 0) + { + *pszString = NULL; + return 0; + } + else + { + // check if there is enough data + if (m_tDataSize < ul) + return -1; + + // alloc buffer for a string + (*pszString)=new char_t[ul]; + if (pop_data((byte_t*)(*pszString), ul) != ul) + { + delete [] (*pszString); + *pszString=NULL; + return -1; + } + else + { + (*pszString)[ul-1]='\0'; // just in case + return ul-1; // without the '\0' + } + } +} + +size_t circular_buffer::find(size_t tStartAt, ulong_t ulFnd) +{ +// printf("searching for %lu from %lu\n", ulFnd, ulStartAt); +// printf("internal structures: buf: 0x%lx, data size: %lu, buf size: %lu\n", m_pbyBuffer, m_tDataSize, m_tSize); + for (size_t i=tStartAt;i m_tDataSize) + m_tDataSize=0; + else + { + memmove(m_pbyBuffer, m_pbyBuffer+tCount, m_tDataSize-tCount); + m_tDataSize-=tCount; + } +} + +void circular_buffer::resize_buffer(size_t tNewSize) +{ + // modify the new length & alloc the new buffer + tNewSize=(tNewSize & ~(_BUFFER_INC-1)) + _BUFFER_INC; + if (tNewSize < m_tSize) + return; + + byte_t *pszBuf=new byte_t[tNewSize]; + + if (m_pbyBuffer && m_tDataSize > 0) + { + // copy the old buffer to the new one + memcpy(pszBuf, m_pbyBuffer, m_tDataSize); + + // destroy the old buffer + delete [] m_pbyBuffer; + } + + // update data + m_pbyBuffer=pszBuf; + m_tSize=tNewSize; +} + +void circular_buffer::shrink_buffer() +{ +#if _USE_SHRINKING == 1 + // check the current size of the data + size_t tNewSize=(m_tDataSize & ~(_BUFFER_INC-1)) + _BUFFER_INC; + if (m_tSize-tNewSize > _BUFFER_DEC) + { + // we must shrink the buffer + byte_t *pszBuf=new byte_t[tNewSize]; + memcpy(pszBuf, m_pbyBuffer, m_tDataSize); + delete [] m_pbyBuffer; + + m_pbyBuffer=pszBuf; + m_tSize=tNewSize; + } +#endif +} + +void circular_buffer::flush(size_t tToLeave) +{ + if (m_tDataSize > tToLeave) + skip_bytes(m_tDataSize-tToLeave); +} + +void circular_buffer::push_bits(ulong_t ulBits, byte_t byCount) +{ + assert(byCount <= 32 && byCount >= 1); // count of bits must be a sane value + assert(m_tBitsAtEndCount <= 7); // the internal bits count must be from the range [0..7]. For 8 bits in a buffer + // there is value of 0. + + do + { + // check if we have to add the bits to the last byte of a buffer + if (m_tBitsAtEndCount != 0) + { + // count of bits to copy into the last byte of the internal buffer + ulong_t ulCopy=(ulong_t)((byCount < 8-m_tBitsAtEndCount) ? byCount : 8-m_tBitsAtEndCount); + + // make some space for the incoming data + m_pbyBuffer[m_tDataSize-1] >>= ulCopy; + + // get the full byte from the in + byte_t uc=(byte_t)(ulBits & 0x000000ff); + + // we are getting from it only ulCopy lowest bits, so shift if a bit + uc <<= 8-ulCopy; + + // and apply + m_pbyBuffer[m_tDataSize-1] |= uc; + + // a bit of corrections + ulBits >>= ulCopy; + byCount-=(byte_t)ulCopy; + m_tBitsAtEndCount+=ulCopy; + if (m_tBitsAtEndCount == 8) + m_tBitsAtEndCount = 0; + } + else + { + // now there is something to add at the beginning of a next byte + // if there are some full bytes to add then simply add it through the + // PushData. + if (byCount >= 8) + { + // push the whole 8 bits as a byte into the buffer. Operation safe only + // on the little endian machines. + ulong_t ulCount=byCount/8; + push_data(((const byte_t*)&ulBits), ulCount); + + // corrections + ulBits >>= ulCount*8; + byCount-=(byte_t)(ulCount*8); + } + else + { + // we are about to add <8 bits of data into the last byte of a buffer which does not exist yet + // get the full byte from the input ulong + byte_t uc=(byte_t)(ulBits & 0x000000ff); + + // shift it a bit + uc <<= 8-byCount; + + // and add as a next byte + push_data(&uc, 1); + +// Dump(); + + // corrections + m_tBitsAtEndCount = byCount; + ulBits = 0; // since there are no data left + byCount = 0; // no data left + } + } + } + while(byCount > 0); +} + +// finished the operation of pushing bits, so we could use normal Push/PopData +/*void circular_buffer::PushBitsFinish() +{ + // check if there is unfinished byte at the end + if (m_tBitsAtEndCount != 0) + { + m_pbyBuffer[m_tDataSize-1] >>= 8-m_tBitsAtEndCount; + m_tBitsAtEndCount=0; + } +}*/ + +// enumerates all the bit-packs that exists in a buffer. If there were any bits operations performed +// on a buffer - they must be finished by the PushBitsFinish. +void circular_buffer::enum_bit_packets(ulong_t ulBitsCount, PFNBITSCALLBACK pfn, void* pParam) +{ + assert(ulBitsCount >= 1 && ulBitsCount <=8); + assert(pfn); + + ushort_t w=0; // internal buffer for the next data from the class's buffer + ulong_t ulBits=0; // count of bits that was left in w + + size_t tIndex=0; // current index in the class's buffer + for (;;) + { + // make sure there is enough data in w so the next operation can succeed + // if there is less data in w than requested + if (ulBits < ulBitsCount) + { + // is there something left to read from the internal buffer + if (tIndex < m_tDataSize) + { + // append some bits into the buffer. + // NOTE: we are sure that there are at least 8 bits space in w + if (tIndex == m_tDataSize && m_tBitsAtEndCount != 0) + { + // there are less than 8 bits left. add only the part that exists + byte_t uc=(byte_t)(m_pbyBuffer[tIndex++] >> (8-m_tBitsAtEndCount)); + w |= (ushort_t)(uc) << ulBits; + } + else + { + w |= (ushort_t)(m_pbyBuffer[tIndex++]) << ulBits; + ulBits+=8; + } + } + else + { + // are there any bits left in the w ? + if (ulBits > 0) + { + // there are some bits left, so we should add a bit or two to make sure nothing is lost +// printf("$$$ Some (%lu) bits left. Current cache=%u\n", ulBits, w); + ulBits=ulBitsCount; + } + else + { + // there are no data left in the internal buffer, so finish the operation +// printf("&&& Leaving with %lu bits left\n", ulBits); + return; + } + } + } + else + { + // call the callback function with the ucData as a param + byte_t uc=(byte_t)(w & 0xff) << (8-ulBitsCount); + uc >>= 8-ulBitsCount; + + (*pfn)(uc, pParam); + + // update variables + ulBits-=ulBitsCount; + w >>= ulBitsCount; + } + } +} + +/*void circular_buffer::dump() +{ + printf("circular_buffer::Dump()\n\tsize of data: %lu\n\tsizeof the buffer: %lu\n\tbits at end: %lu", m_tDataSize, m_tSize, m_tBitsAtEndCount); + for (unsigned long i=0;i