1 /*
2 Copyright 2015 Esri
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 A local copy of the license and additional notices are located with the
17 source distribution at:
18
19 http://github.com/Esri/lerc/
20
21 Contributors: Thomas Maurer
22 */
23
24 #include <cstring>
25 #include "BitStuffer.h"
26
27 using namespace std;
28 using namespace LercNS;
29
30 // -------------------------------------------------------------------------- ;
31
read(Byte ** ppByte,vector<unsigned int> & dataVec) const32 bool BitStuffer::read(Byte** ppByte, vector<unsigned int>& dataVec) const
33 {
34 if (!ppByte)
35 return false;
36
37 Byte numBitsByte = **ppByte;
38 (*ppByte)++;
39
40 int bits67 = numBitsByte >> 6;
41 int n = (bits67 == 0) ? 4 : 3 - bits67;
42
43 numBitsByte &= 63; // bits 0-5;
44
45 unsigned int numElements = 0;
46 if (!readUInt(ppByte, numElements, n))
47 return false;
48
49 if (numBitsByte >= 32)
50 return false;
51
52 int numBits = numBitsByte;
53 unsigned int numUInts = (numElements * numBits + 31) / 32;
54 dataVec.resize(numElements, 0); // init with 0
55
56 if (numUInts > 0) // numBits can be 0
57 {
58 m_tmpBitStuffVec.resize(numUInts);
59 m_tmpBitStuffVec[numUInts - 1] = 0; // set last uint to 0
60
61 unsigned int nBytesToCopy = (numElements * numBits + 7) / 8;
62 memcpy(&m_tmpBitStuffVec[0], *ppByte, nBytesToCopy);
63
64 unsigned int* arr = &m_tmpBitStuffVec[0];
65 unsigned int* srcPtr = arr;
66 for (unsigned int i = 0; i < numUInts; i++)
67 {
68 SWAP_4(*srcPtr);
69 srcPtr++;
70 }
71
72 unsigned int* pLastULong = &m_tmpBitStuffVec[numUInts - 1];
73 unsigned int n = numTailBytesNotNeeded(numElements, numBits);
74 while (n--)
75 *pLastULong <<= 8;
76
77 // do the un-stuffing
78 srcPtr = arr;
79 unsigned int* dstPtr = &dataVec[0];
80 int bitPos = 0;
81
82 for (unsigned int i = 0; i < numElements; i++)
83 {
84 if (32 - bitPos >= numBits)
85 {
86 unsigned int val;
87 memcpy(&val, srcPtr, sizeof(unsigned int));
88 unsigned int n = val << bitPos;
89 *dstPtr++ = n >> (32 - numBits);
90
91 bitPos += numBits;
92 if (bitPos == 32) // shift >= 32 is undefined
93 {
94 bitPos = 0;
95 srcPtr++;
96 }
97 }
98 else
99 {
100 unsigned int val;
101 memcpy(&val, srcPtr, sizeof(unsigned int));
102 srcPtr++;
103 unsigned int n = val << bitPos;
104 *dstPtr = n >> (32 - numBits);
105 bitPos -= (32 - numBits);
106 memcpy(&val, srcPtr, sizeof(unsigned int));
107 *dstPtr++ |= val >> (32 - bitPos);
108 }
109 }
110
111 *ppByte += nBytesToCopy;
112 }
113
114 return true;
115 }
116
117 // -------------------------------------------------------------------------- ;
118 // -------------------------------------------------------------------------- ;
119
readUInt(Byte ** ppByte,unsigned int & k,int numBytes)120 bool BitStuffer::readUInt(Byte** ppByte, unsigned int& k, int numBytes)
121 {
122 Byte* ptr = *ppByte;
123
124 if (numBytes == 1)
125 {
126 k = *ptr;
127 }
128 else if (numBytes == 2)
129 {
130 unsigned short s;
131 memcpy(&s, ptr, sizeof(unsigned short));
132 SWAP_2(s);
133 k = s;
134 }
135 else if (numBytes == 4)
136 {
137 memcpy(&k, ptr, sizeof(unsigned int));
138 SWAP_4(k);
139 }
140 else
141 return false;
142
143 *ppByte = ptr + numBytes;
144 return true;
145 }
146
147 // -------------------------------------------------------------------------- ;
148
numTailBytesNotNeeded(unsigned int numElem,int numBits)149 unsigned int BitStuffer::numTailBytesNotNeeded(unsigned int numElem, int numBits)
150 {
151 int numBitsTail = (numElem * numBits) & 31;
152 int numBytesTail = (numBitsTail + 7) >> 3;
153 return (numBytesTail > 0) ? 4 - numBytesTail : 0;
154 }
155
156 // -------------------------------------------------------------------------- ;
157
158