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
15 const 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
21 CUnBitArrayBase*
CreateUnBitArray(IAPEDecompress * pAPEDecompress,int nVersion)22 CreateUnBitArray(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
38 void
AdvanceToByteBoundary()39 CUnBitArrayBase::AdvanceToByteBoundary()
40 {
41 int nMod = m_nCurrentBitIndex % 8;
42 if (nMod != 0)
43 m_nCurrentBitIndex += 8 - nMod;
44 }
45
46
47 uint32
DecodeValueXBits(uint32 nBits)48 CUnBitArrayBase::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
73 int
FillAndResetBitArray(int nFileLocation,int nNewBitIndex)74 CUnBitArrayBase::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
92 int
FillBitArray()93 CUnBitArrayBase::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
116 int
CreateHelper(CIO * pIO,int nBytes,int nVersion)117 CUnBitArrayBase::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