#include "All.h"
#include "UnBitArrayBase.h"
#include "APEInfo.h"
#include "UnBitArray.h"
#undef BACKWARDS_COMPATIBILITY
#ifdef BACKWARDS_COMPATIBILITY
#include "Old/APEDecompressOld.h"
#include "Old/UnBitArrayOld.h"
#endif
const uint32 POWERS_OF_TWO_MINUS_ONE[33] = {0u,1u,3u,7u,15u,31u,63u,127u,255u,
511u,1023u,2047u,4095u,8191u,16383u,32767u,65535u,131071u,262143u,524287u,
1048575u,2097151u,4194303u,8388607u,16777215u,33554431u,67108863u,
134217727u,268435455u,536870911u,1073741823u,2147483647u,4294967295u};
CUnBitArrayBase*
CreateUnBitArray(IAPEDecompress* pAPEDecompress, int nVersion)
{
#ifdef BACKWARDS_COMPATIBILITY
if (nVersion >= 3900)
return static_cast<CUnBitArrayBase*>
(new CUnBitArray(GET_IO(pAPEDecompress), nVersion));
else
return static_cast<CUnBitArrayBase*>
(new CUnBitArrayOld(pAPEDecompress, nVersion));
#else
return static_cast<CUnBitArrayBase*>
(new CUnBitArray(GET_IO(pAPEDecompress), nVersion));
#endif
}
void
CUnBitArrayBase::AdvanceToByteBoundary()
{
int nMod = m_nCurrentBitIndex % 8;
if (nMod != 0)
m_nCurrentBitIndex += 8 - nMod;
}
uint32
CUnBitArrayBase::DecodeValueXBits(uint32 nBits)
{
if ((m_nCurrentBitIndex + nBits) >= m_nBits)
FillBitArray();
uint32 nLeftBits = 32 - (m_nCurrentBitIndex & 31);
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
m_nCurrentBitIndex += nBits;
if (nLeftBits >= nBits)
return (m_pBitArray[nBitArrayIndex]
& (POWERS_OF_TWO_MINUS_ONE[nLeftBits])) >> (nLeftBits - nBits);
int nRightBits = nBits - nLeftBits;
uint32 nLeftValue = ((m_pBitArray[nBitArrayIndex]
& POWERS_OF_TWO_MINUS_ONE[nLeftBits]) << nRightBits);
uint32 nRightValue = (m_pBitArray[nBitArrayIndex + 1] >> (32 - nRightBits));
return (nLeftValue | nRightValue);
}
int
CUnBitArrayBase::FillAndResetBitArray(int nFileLocation, int nNewBitIndex)
{
m_nCurrentBitIndex = nNewBitIndex;
if (nFileLocation != -1 && m_pIO->Seek(nFileLocation, FILE_BEGIN) != 0)
return ERROR_IO_READ;
unsigned int nBytesRead = 0;
if (m_pIO->Read((unsigned char*)m_pBitArray, m_nBytes,
&nBytesRead) != 0)
return ERROR_IO_READ;
return 0;
}
int
CUnBitArrayBase::FillBitArray()
{
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
memmove((void *) (m_pBitArray), static_cast<const void*>(m_pBitArray
+ nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4));
int nBytesToRead = nBitArrayIndex * 4;
unsigned int nBytesRead = 0;
int nRetVal = m_pIO->Read((unsigned char*)(m_pBitArray + m_nElements
- nBitArrayIndex), nBytesToRead, &nBytesRead);
m_nCurrentBitIndex = m_nCurrentBitIndex & 31;
return (nRetVal == 0) ? 0 : ERROR_IO_READ;
}
int
CUnBitArrayBase::CreateHelper(CIO * pIO, int nBytes, int nVersion)
{
if ((pIO == NULL) || (nBytes <= 0))
return ERROR_BAD_PARAMETER;
m_nElements = nBytes / 4;
m_nBytes = m_nElements * 4;
m_nBits = m_nBytes * 8;
m_pIO = pIO;
m_nVersion = nVersion;
m_nCurrentBitIndex = 0;
m_pBitArray = new uint32[m_nElements];
return (m_pBitArray != NULL) ? 0 : ERROR_INSUFFICIENT_MEMORY;
}