/src/gdal/third_party/LercLib/BitStuffer2.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef BITSTUFFER2_H |
25 | | #define BITSTUFFER2_H |
26 | | |
27 | | #include <vector> |
28 | | #include <cstring> |
29 | | #include <utility> |
30 | | #include "Defines.h" |
31 | | |
32 | | NAMESPACE_LERC_START |
33 | | |
34 | | /** Bit stuffer, for writing unsigned int arrays compressed lossless |
35 | | * |
36 | | */ |
37 | | |
38 | | class BitStuffer2 |
39 | | { |
40 | | public: |
41 | 0 | BitStuffer2() {} |
42 | 0 | ~BitStuffer2() {} |
43 | | |
44 | | // dst buffer is already allocated. byte ptr is moved like a file pointer. |
45 | | bool EncodeSimple(Byte** ppByte, const std::vector<unsigned int>& dataVec, int lerc2Version) const; |
46 | | bool EncodeLut(Byte** ppByte, const std::vector<std::pair<unsigned int, unsigned int> >& sortedDataVec, int lerc2Version) const; |
47 | | bool Decode(const Byte** ppByte, size_t& nBytesRemaining, std::vector<unsigned int>& dataVec, size_t maxElementCount, int lerc2Version) const; |
48 | | |
49 | | static unsigned int ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem); |
50 | | static unsigned int ComputeNumBytesNeededLut(const std::vector<std::pair<unsigned int, unsigned int> >& sortedDataVec, bool& doLut); |
51 | | |
52 | | private: |
53 | | mutable std::vector<unsigned int> m_tmpLutVec, m_tmpIndexVec, m_tmpBitStuffVec; |
54 | | |
55 | | static void BitStuff_Before_Lerc2v3(Byte** ppByte, const std::vector<unsigned int>& dataVec, int numBits); |
56 | | bool BitUnStuff_Before_Lerc2v3(const Byte** ppByte, size_t& nBytesRemaining, std::vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const; |
57 | | void BitStuff(Byte** ppByte, const std::vector<unsigned int>& dataVec, int numBits) const; |
58 | | bool BitUnStuff(const Byte** ppByte, size_t& nBytesRemaining, std::vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const; |
59 | | |
60 | | static bool EncodeUInt(Byte** ppByte, unsigned int k, int numBytes); // numBytes = 1, 2, or 4 |
61 | | static bool DecodeUInt(const Byte** ppByte, size_t& nBytesRemaining, unsigned int& k, int numBytes); |
62 | 0 | static int NumBytesUInt(unsigned int k) { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; } |
63 | | static unsigned int NumTailBytesNotNeeded(unsigned int numElem, int numBits); |
64 | | }; |
65 | | |
66 | | // -------------------------------------------------------------------------- ; |
67 | | |
68 | | inline unsigned int BitStuffer2::ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem) |
69 | 0 | { |
70 | 0 | int numBits = 0; |
71 | 0 | while ((numBits < 32) && (maxElem >> numBits)) |
72 | 0 | numBits++; |
73 | 0 | return 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3); |
74 | 0 | } |
75 | | |
76 | | // -------------------------------------------------------------------------- ; |
77 | | |
78 | | inline bool BitStuffer2::EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) |
79 | 0 | { |
80 | 0 | Byte* ptr = *ppByte; |
81 | |
|
82 | 0 | if (numBytes == 1) |
83 | 0 | *ptr = (Byte)k; |
84 | 0 | else if (numBytes == 2) |
85 | 0 | { |
86 | 0 | unsigned short kShort = (unsigned short)k; |
87 | 0 | memcpy(ptr, &kShort, sizeof(unsigned short)); |
88 | 0 | } |
89 | 0 | else if (numBytes == 4) |
90 | 0 | memcpy(ptr, &k, sizeof(unsigned int)); |
91 | 0 | else |
92 | 0 | return false; |
93 | | |
94 | 0 | *ppByte += numBytes; |
95 | 0 | return true; |
96 | 0 | } |
97 | | |
98 | | // -------------------------------------------------------------------------- ; |
99 | | |
100 | | inline bool BitStuffer2::DecodeUInt(const Byte** ppByte, size_t& nBytesRemaining, unsigned int& k, int numBytes) |
101 | 0 | { |
102 | 0 | if (nBytesRemaining < (size_t)numBytes) |
103 | 0 | return false; |
104 | | |
105 | 0 | const Byte* ptr = *ppByte; |
106 | |
|
107 | 0 | if (numBytes == 1) |
108 | 0 | k = *ptr; |
109 | 0 | else if (numBytes == 2) |
110 | 0 | { |
111 | 0 | unsigned short s; |
112 | 0 | memcpy(&s, ptr, sizeof(unsigned short)); |
113 | 0 | k = s; |
114 | 0 | } |
115 | 0 | else if (numBytes == 4) |
116 | 0 | memcpy(&k, ptr, sizeof(unsigned int)); |
117 | 0 | else |
118 | 0 | return false; |
119 | | |
120 | 0 | *ppByte += numBytes; |
121 | 0 | nBytesRemaining -= numBytes; |
122 | 0 | return true; |
123 | 0 | } |
124 | | |
125 | | // -------------------------------------------------------------------------- ; |
126 | | |
127 | | inline unsigned int BitStuffer2::NumTailBytesNotNeeded(unsigned int numElem, int numBits) |
128 | 0 | { |
129 | 0 | int numBitsTail = ((unsigned long long)numElem * numBits) & 31; |
130 | 0 | int numBytesTail = (numBitsTail + 7) >> 3; |
131 | 0 | return (numBytesTail > 0) ? 4 - numBytesTail : 0; |
132 | 0 | } |
133 | | |
134 | | // -------------------------------------------------------------------------- ; |
135 | | |
136 | | NAMESPACE_LERC_END |
137 | | #endif |