1 #include "All.h"
2 #include "UnBitArrayBase.h"
3 #include "APEInfo.h"
4 #include "UnBitArray.h"
5 #ifdef APE_BACKWARDS_COMPATIBILITY
6 	#include "Old/APEDecompressOld.h"
7 	#include "Old/UnBitArrayOld.h"
8 #endif
9 
10 namespace APE
11 {
12 
13 const uint32 POWERS_OF_TWO_MINUS_ONE[33] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,4294967295};
14 
CreateUnBitArray(IAPEDecompress * pAPEDecompress,intn nVersion)15 CUnBitArrayBase * CreateUnBitArray(IAPEDecompress * pAPEDecompress, intn nVersion)
16 {
17     // determine the furthest position we should read in the I/O object
18     intn nFurthestReadByte = GET_IO(pAPEDecompress)->GetSize();
19     if (nFurthestReadByte > 0)
20     {
21        // terminating data
22        nFurthestReadByte -= pAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES);
23 
24        // tag (not worth analyzing the tag since we could be a remote file, etc.)
25        CAPETag * pAPETag = (CAPETag *) pAPEDecompress->GetInfo(APE_INFO_TAG);
26        if ((pAPETag != NULL) && pAPETag->GetAnalyzed())
27            nFurthestReadByte -= pAPETag->GetTagBytes();
28     }
29 
30 #ifdef APE_BACKWARDS_COMPATIBILITY
31 	if (nVersion >= 3900)
32 		return (CUnBitArrayBase * ) new CUnBitArray(GET_IO(pAPEDecompress), nVersion, nFurthestReadByte);
33 	else
34 		return (CUnBitArrayBase * ) new CUnBitArrayOld(pAPEDecompress, nVersion, nFurthestReadByte);
35 #else
36 	// create the appropriate object
37     if (nVersion < 3900)
38     {
39         // we should no longer be trying to decode files this old (this check should be redundant since
40         // the main gate keeper should be CreateIAPEDecompressCore(...)
41         ASSERT(false);
42         return NULL;
43     }
44 
45     return (CUnBitArrayBase * ) new CUnBitArray(GET_IO(pAPEDecompress), nVersion, nFurthestReadByte);
46 #endif
47 }
48 
CUnBitArrayBase(intn nFurthestReadByte)49 CUnBitArrayBase::CUnBitArrayBase(intn nFurthestReadByte)
50 {
51     m_nFurthestReadByte = nFurthestReadByte;
52 }
53 
~CUnBitArrayBase()54 CUnBitArrayBase::~CUnBitArrayBase()
55 {
56 }
57 
AdvanceToByteBoundary()58 void CUnBitArrayBase::AdvanceToByteBoundary()
59 {
60     int nMod = m_nCurrentBitIndex % 8;
61     if (nMod != 0) { m_nCurrentBitIndex += 8 - nMod; }
62 }
63 
EnsureBitsAvailable(uint32 nBits,bool bThrowExceptionOnFailure)64 bool CUnBitArrayBase::EnsureBitsAvailable(uint32 nBits, bool bThrowExceptionOnFailure)
65 {
66 	bool bResult = true;
67 
68 	// get more data if necessary
69 	if ((m_nCurrentBitIndex + nBits) >= (m_nGoodBytes * 8))
70 	{
71 		// fill
72 		FillBitArray();
73 
74 		// if we still don't have enough good bytes, we don't have the bits available
75 		if ((m_nCurrentBitIndex + nBits) >= (m_nGoodBytes * 8))
76 		{
77 			// overread error
78 			ASSERT(false);
79 
80 			// throw exception if specified
81 			if (bThrowExceptionOnFailure)
82 				throw(1);
83 
84 			// data not available
85 			bResult = false;
86 		}
87 	}
88 
89 	return bResult;
90 }
91 
DecodeValueXBits(uint32 nBits)92 uint32 CUnBitArrayBase::DecodeValueXBits(uint32 nBits)
93 {
94     // get more data if necessary
95 	EnsureBitsAvailable(nBits, true);
96 
97     // variable declares
98     uint32 nLeftBits = 32 - (m_nCurrentBitIndex & 31);
99     uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
100     m_nCurrentBitIndex += nBits;
101 
102     // if their isn't an overflow to the right value, get the value and exit
103     if (nLeftBits >= nBits)
104         return (m_pBitArray[nBitArrayIndex] & (POWERS_OF_TWO_MINUS_ONE[nLeftBits])) >> (nLeftBits - nBits);
105 
106     // must get the "split" value from left and right
107     int nRightBits = nBits - nLeftBits;
108 
109     uint32 nLeftValue = ((m_pBitArray[nBitArrayIndex] & POWERS_OF_TWO_MINUS_ONE[nLeftBits]) << nRightBits);
110     uint32 nRightValue = (m_pBitArray[nBitArrayIndex + 1] >> (32 - nRightBits));
111     return (nLeftValue | nRightValue);
112 }
113 
FillAndResetBitArray(intn nFileLocation,intn nNewBitIndex)114 int CUnBitArrayBase::FillAndResetBitArray(intn nFileLocation, intn nNewBitIndex)
115 {
116     // seek if necessary
117     if (nFileLocation != -1)
118     {
119         if (m_pIO->Seek(nFileLocation, FILE_BEGIN) != 0)
120             return ERROR_IO_READ;
121     }
122 
123     // fill
124     m_nCurrentBitIndex = m_nBits; // position at the end of the buffer
125     int nResult = FillBitArray();
126 
127     // set bit index
128     m_nCurrentBitIndex = (uint32) nNewBitIndex;
129 
130     return nResult;
131 }
132 
FillBitArray()133 int CUnBitArrayBase::FillBitArray()
134 {
135     // get the bit array index
136     uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
137 
138     // move the remaining data to the front
139     memmove((void *) (m_pBitArray), (const void *) (m_pBitArray + nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4));
140 
141     // get the number of bytes to read
142     intn nBytesToRead = nBitArrayIndex * 4;
143     if (m_nFurthestReadByte > 0)
144     {
145         intn nFurthestReadBytes = m_nFurthestReadByte - m_pIO->GetPosition();
146         if (nBytesToRead > nFurthestReadBytes)
147             nBytesToRead = nFurthestReadBytes;
148     }
149 
150     // read the new data
151     unsigned int nBytesRead = 0;
152     int nResult = m_pIO->Read((unsigned char *) (m_pBitArray + m_nElements - nBitArrayIndex), (unsigned int) nBytesToRead, &nBytesRead);
153 
154     // zero anything at the tail we didn't fill
155     m_nGoodBytes = ((m_nElements - nBitArrayIndex) * 4) + nBytesRead;
156     if (m_nGoodBytes < m_nBytes)
157         memset(&((unsigned char *) m_pBitArray)[m_nGoodBytes], 0, m_nBytes - m_nGoodBytes);
158 
159     // adjust the m_Bit pointer
160     m_nCurrentBitIndex = m_nCurrentBitIndex & 31;
161 
162     // return
163     return (nResult == 0) ? 0 : ERROR_IO_READ;
164 }
165 
CreateHelper(CIO * pIO,intn nBytes,intn nVersion)166 int CUnBitArrayBase::CreateHelper(CIO * pIO, intn nBytes, intn nVersion)
167 {
168     // check the parameters
169     if ((pIO == NULL) || (nBytes <= 0)) { return ERROR_BAD_PARAMETER; }
170 
171     // save the size
172     m_nElements = uint32(nBytes) / 4;
173     m_nBytes = m_nElements * 4;
174     m_nBits = m_nBytes * 8;
175     m_nGoodBytes = 0;
176 
177     // set the variables
178     m_pIO = pIO;
179     m_nVersion = nVersion;
180     m_nCurrentBitIndex = 0;
181 
182     // create the bitarray (we allocate and empty a little extra as buffer insurance, although it should never be necessary)
183     m_pBitArray = new uint32 [m_nElements + 64];
184     memset(m_pBitArray, 0, (m_nElements + 64) * sizeof(uint32));
185 
186     return (m_pBitArray != NULL) ? 0 : ERROR_INSUFFICIENT_MEMORY;
187 }
188 
189 }