xref: /haiku/src/add-ons/media/plugins/ape_reader/MAClib/UnBitArrayBase.cpp (revision 23c0ae0362174e8dbdc88d14e03618815dde145e)
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