#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 (new CUnBitArray(GET_IO(pAPEDecompress), nVersion)); else return static_cast (new CUnBitArrayOld(pAPEDecompress, nVersion)); #else return static_cast (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) { // get more data if necessary if ((m_nCurrentBitIndex + nBits) >= m_nBits) FillBitArray(); // variable declares uint32 nLeftBits = 32 - (m_nCurrentBitIndex & 31); uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5; m_nCurrentBitIndex += nBits; // if there isn't an overflow to the right value, get the value and exit if (nLeftBits >= nBits) return (m_pBitArray[nBitArrayIndex] & (POWERS_OF_TWO_MINUS_ONE[nLeftBits])) >> (nLeftBits - nBits); // must get the "split" value from left and right 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) { // reset the bit index m_nCurrentBitIndex = nNewBitIndex; // seek if necessary if (nFileLocation != -1 && m_pIO->Seek(nFileLocation, FILE_BEGIN) != 0) return ERROR_IO_READ; // read the new data into the bit array 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() { // get the bit array index uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5; // move the remaining data to the front memmove((void *) (m_pBitArray), static_cast(m_pBitArray + nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4)); // read the new data int nBytesToRead = nBitArrayIndex * 4; unsigned int nBytesRead = 0; int nRetVal = m_pIO->Read((unsigned char*)(m_pBitArray + m_nElements - nBitArrayIndex), nBytesToRead, &nBytesRead); // adjust the m_Bit pointer m_nCurrentBitIndex = m_nCurrentBitIndex & 31; // return return (nRetVal == 0) ? 0 : ERROR_IO_READ; } int CUnBitArrayBase::CreateHelper(CIO * pIO, int nBytes, int nVersion) { // check the parameters if ((pIO == NULL) || (nBytes <= 0)) return ERROR_BAD_PARAMETER; // save the size m_nElements = nBytes / 4; m_nBytes = m_nElements * 4; m_nBits = m_nBytes * 8; // set the variables m_pIO = pIO; m_nVersion = nVersion; m_nCurrentBitIndex = 0; // create the bitarray m_pBitArray = new uint32[m_nElements]; return (m_pBitArray != NULL) ? 0 : ERROR_INSUFFICIENT_MEMORY; }