1#include "All.h"
2#include "UnBitArrayBase.h"
3#include "APEInfo.h"
4#include "UnBitArray.h"
5
6
7#undef	BACKWARDS_COMPATIBILITY
8
9#ifdef BACKWARDS_COMPATIBILITY
10	#include "Old/APEDecompressOld.h"
11	#include "Old/UnBitArrayOld.h"
12#endif
13
14
15const uint32 POWERS_OF_TWO_MINUS_ONE[33] = {0u,1u,3u,7u,15u,31u,63u,127u,255u,
16	511u,1023u,2047u,4095u,8191u,16383u,32767u,65535u,131071u,262143u,524287u,
17	1048575u,2097151u,4194303u,8388607u,16777215u,33554431u,67108863u,
18	134217727u,268435455u,536870911u,1073741823u,2147483647u,4294967295u};
19
20
21CUnBitArrayBase*
22CreateUnBitArray(IAPEDecompress* pAPEDecompress, int nVersion)
23{
24#ifdef BACKWARDS_COMPATIBILITY
25	if (nVersion >= 3900)
26		return static_cast<CUnBitArrayBase*>
27			(new CUnBitArray(GET_IO(pAPEDecompress), nVersion));
28	else
29		return static_cast<CUnBitArrayBase*>
30			(new CUnBitArrayOld(pAPEDecompress, nVersion));
31#else
32	return static_cast<CUnBitArrayBase*>
33		(new CUnBitArray(GET_IO(pAPEDecompress), nVersion));
34#endif
35}
36
37
38void
39CUnBitArrayBase::AdvanceToByteBoundary()
40{
41	int nMod = m_nCurrentBitIndex % 8;
42	if (nMod != 0)
43		m_nCurrentBitIndex += 8 - nMod;
44}
45
46
47uint32
48CUnBitArrayBase::DecodeValueXBits(uint32 nBits)
49{
50	// get more data if necessary
51	if ((m_nCurrentBitIndex + nBits) >= m_nBits)
52		FillBitArray();
53
54	// variable declares
55	uint32 nLeftBits = 32 - (m_nCurrentBitIndex & 31);
56	uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
57	m_nCurrentBitIndex += nBits;
58
59	// if there isn't an overflow to the right value, get the value and exit
60	if (nLeftBits >= nBits)
61		return (m_pBitArray[nBitArrayIndex]
62			& (POWERS_OF_TWO_MINUS_ONE[nLeftBits])) >> (nLeftBits - nBits);
63
64	// must get the "split" value from left and right
65	int nRightBits = nBits - nLeftBits;
66	uint32 nLeftValue = ((m_pBitArray[nBitArrayIndex]
67		& POWERS_OF_TWO_MINUS_ONE[nLeftBits]) << nRightBits);
68	uint32 nRightValue = (m_pBitArray[nBitArrayIndex + 1] >> (32 - nRightBits));
69	return (nLeftValue | nRightValue);
70}
71
72
73int
74CUnBitArrayBase::FillAndResetBitArray(int nFileLocation, int nNewBitIndex)
75{
76	// reset the bit index
77	m_nCurrentBitIndex = nNewBitIndex;
78
79	// seek if necessary
80	if (nFileLocation != -1 && m_pIO->Seek(nFileLocation, FILE_BEGIN) != 0)
81		return ERROR_IO_READ;
82
83    // read the new data into the bit array
84	unsigned int nBytesRead = 0;
85	if (m_pIO->Read((unsigned char*)m_pBitArray, m_nBytes,
86		&nBytesRead) != 0)
87		return ERROR_IO_READ;
88    return 0;
89}
90
91
92int
93CUnBitArrayBase::FillBitArray()
94{
95	// get the bit array index
96	uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
97
98	// move the remaining data to the front
99	memmove((void *) (m_pBitArray),	static_cast<const void*>(m_pBitArray
100		+ nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4));
101
102	// read the new data
103	int nBytesToRead = nBitArrayIndex * 4;
104	unsigned int nBytesRead = 0;
105	int nRetVal = m_pIO->Read((unsigned char*)(m_pBitArray + m_nElements
106		- nBitArrayIndex), nBytesToRead, &nBytesRead);
107
108	// adjust the m_Bit pointer
109	m_nCurrentBitIndex = m_nCurrentBitIndex & 31;
110
111	// return
112	return (nRetVal == 0) ? 0 : ERROR_IO_READ;
113}
114
115
116int
117CUnBitArrayBase::CreateHelper(CIO * pIO, int nBytes, int nVersion)
118{
119	// check the parameters
120	if ((pIO == NULL) || (nBytes <= 0))
121		return ERROR_BAD_PARAMETER;
122
123	// save the size
124	m_nElements = nBytes / 4;
125	m_nBytes = m_nElements * 4;
126	m_nBits = m_nBytes * 8;
127
128	// set the variables
129	m_pIO = pIO;
130	m_nVersion = nVersion;
131	m_nCurrentBitIndex = 0;
132
133	// create the bitarray
134	m_pBitArray = new uint32[m_nElements];
135
136	return (m_pBitArray != NULL) ? 0 : ERROR_INSUFFICIENT_MEMORY;
137}
138