Coverage Report

Created: 2026-08-11 08:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/third_party/LercLib/BitStuffer2.cpp
Line
Count
Source
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 <algorithm>
25
#include <cassert>
26
#include "Defines.h"
27
#include "BitStuffer2.h"
28
29
using namespace std;
30
USING_NAMESPACE_LERC
31
32
// -------------------------------------------------------------------------- ;
33
34
// if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
35
36
bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec, int lerc2Version) const
37
0
{
38
0
  if (!ppByte || dataVec.empty())
39
0
    return false;
40
41
0
  unsigned int maxElem = *max_element(dataVec.begin(), dataVec.end());
42
0
  int numBits = 0;
43
0
  while ((numBits < 32) && (maxElem >> numBits))
44
0
    numBits++;
45
46
0
  if (numBits >= 32)
47
0
    return false;
48
49
0
  Byte numBitsByte = (Byte)numBits;
50
0
  unsigned int numElements = (unsigned int)dataVec.size();
51
0
  unsigned int numUInts = (numElements * numBits + 31) / 32;
52
53
  // use the upper 2 bits to encode the type used for numElements: Byte, ushort, or uint
54
0
  int n = NumBytesUInt(numElements);
55
0
  int bits67 = (n == 4) ? 0 : 3 - n;
56
0
  numBitsByte |= bits67 << 6;
57
58
  // bit5 = 0 means simple mode
59
60
0
  **ppByte = numBitsByte;
61
0
  (*ppByte)++;
62
63
0
  if (!EncodeUInt(ppByte, numElements, n))
64
0
    return false;
65
66
0
  if (numUInts > 0)    // numBits can be 0, then we only write the header
67
0
  {
68
0
    if (lerc2Version >= 3)
69
0
      BitStuff(ppByte, dataVec, numBits);
70
0
    else
71
0
      BitStuff_Before_Lerc2v3(ppByte, dataVec, numBits);
72
0
  }
73
74
0
  return true;
75
0
}
76
77
// -------------------------------------------------------------------------- ;
78
79
bool BitStuffer2::EncodeLut(Byte** ppByte, const vector<pair<unsigned int, unsigned int> >& sortedDataVec, int lerc2Version) const
80
0
{
81
0
  if (!ppByte || sortedDataVec.empty())
82
0
    return false;
83
84
0
  if (sortedDataVec[0].first != 0)    // corresponds to min
85
0
    return false;
86
87
  // collect the different values for the lut
88
0
  unsigned int numElem = (unsigned int)sortedDataVec.size();
89
0
  unsigned int indexLut = 0;
90
91
0
  m_tmpLutVec.resize(0);    // omit the 0 throughout that corresponds to min
92
0
  m_tmpIndexVec.assign(numElem, 0);
93
94
0
  for (unsigned int i = 1; i < numElem; i++)
95
0
  {
96
0
    unsigned int prev = sortedDataVec[i - 1].first;
97
0
    m_tmpIndexVec[sortedDataVec[i - 1].second] = indexLut;
98
99
0
    if (sortedDataVec[i].first != prev)
100
0
    {
101
0
      m_tmpLutVec.push_back(sortedDataVec[i].first);
102
0
      indexLut++;
103
0
    }
104
0
  }
105
0
  m_tmpIndexVec[sortedDataVec[numElem - 1].second] = indexLut;    // don't forget the last one
106
107
  // write first 2 data elements same as simple, but bit5 set to 1
108
0
  unsigned int maxElem = m_tmpLutVec.back();
109
0
  int numBits = 0;
110
0
  while ((numBits < 32) && (maxElem >> numBits))
111
0
    numBits++;
112
113
0
  if (numBits >= 32)
114
0
    return false;
115
116
0
  Byte numBitsByte = (Byte)numBits;
117
118
  // use the upper 2 bits to encode the type used for numElem: byte, ushort, or uint
119
0
  int n = NumBytesUInt(numElem);
120
0
  int bits67 = (n == 4) ? 0 : 3 - n;
121
0
  numBitsByte |= bits67 << 6;
122
123
0
  numBitsByte |= (1 << 5);    // bit 5 = 1 means lut mode
124
125
0
  **ppByte = numBitsByte;
126
0
  (*ppByte)++;
127
128
0
  if (!EncodeUInt(ppByte, numElem, n))    // numElements = numIndexes to lut
129
0
    return false;
130
131
0
  unsigned int nLut = (unsigned int)m_tmpLutVec.size();
132
0
  if (nLut < 1 || nLut >= 255)
133
0
    return false;
134
135
0
  **ppByte = (Byte)nLut + 1;    // size of lut, incl the 0
136
0
  (*ppByte)++;
137
138
0
  if (lerc2Version >= 3)
139
0
    BitStuff(ppByte, m_tmpLutVec, numBits);    // lut
140
0
  else
141
0
    BitStuff_Before_Lerc2v3(ppByte, m_tmpLutVec, numBits);
142
143
0
  int nBitsLut = 0;
144
0
  while (nLut >> nBitsLut)    // indexes are in [0 .. nLut]
145
0
    nBitsLut++;
146
147
0
  if (lerc2Version >= 3)
148
0
    BitStuff(ppByte, m_tmpIndexVec, nBitsLut);    // indexes
149
0
  else
150
0
    BitStuff_Before_Lerc2v3(ppByte, m_tmpIndexVec, nBitsLut);
151
152
0
  return true;
153
0
}
154
155
// -------------------------------------------------------------------------- ;
156
157
// if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
158
159
bool BitStuffer2::Decode(const Byte** ppByte, size_t& nBytesRemaining, vector<unsigned int>& dataVec, size_t maxElementCount, int lerc2Version) const
160
5.85k
{
161
5.85k
  if (!ppByte || nBytesRemaining < 1)
162
1
    return false;
163
164
5.85k
  Byte numBitsByte = **ppByte;
165
5.85k
  (*ppByte)++;
166
5.85k
  nBytesRemaining--;
167
168
5.85k
  int bits67 = numBitsByte >> 6;
169
5.85k
  int nb = (bits67 == 0) ? 4 : 3 - bits67;
170
171
5.85k
  bool doLut = (numBitsByte & (1 << 5)) ? true : false;    // bit 5
172
5.85k
  numBitsByte &= 31;    // bits 0-4;
173
5.85k
  int numBits = numBitsByte;
174
175
5.85k
  unsigned int numElements = 0;
176
5.85k
  if (!DecodeUInt(ppByte, nBytesRemaining, numElements, nb))
177
48
    return false;
178
5.80k
  if (numElements > maxElementCount)
179
95
    return false;
180
181
5.71k
  if (!doLut)
182
4.63k
  {
183
4.63k
    if (numBits > 0)    // numBits can be 0
184
4.53k
    {
185
4.53k
      if (lerc2Version >= 3)
186
4.49k
      {
187
4.49k
        if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, numBits))
188
66
          return false;
189
4.49k
      }
190
46
      else
191
46
      {
192
46
        if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, numBits))
193
0
          return false;
194
46
      }
195
4.53k
    }
196
4.63k
  }
197
1.07k
  else
198
1.07k
  {
199
1.07k
    if (numBits == 0)  // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum
200
1
      return false;
201
1.07k
    if (nBytesRemaining < 1)
202
0
      return false;
203
204
1.07k
    Byte nLutByte = **ppByte;
205
1.07k
    (*ppByte)++;
206
1.07k
    nBytesRemaining--;
207
208
1.07k
    int nLut = nLutByte - 1;
209
210
    // unstuff lut w/o the 0
211
1.07k
    if (lerc2Version >= 3)
212
995
    {
213
995
      if (!BitUnStuff(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
214
33
        return false;
215
995
    }
216
77
    else
217
77
    {
218
77
      if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
219
1
        return false;
220
77
    }
221
222
1.03k
    int nBitsLut = 0;
223
4.66k
    while (nLut >> nBitsLut)
224
3.62k
      nBitsLut++;
225
1.03k
    if (nBitsLut == 0)
226
0
      return false;
227
228
1.03k
    if (lerc2Version >= 3)
229
962
    {
230
      // unstuff indexes
231
962
      if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
232
23
        return false;
233
234
      // replace indexes by values
235
939
#if defined(__GNUC__)
236
939
#pragma GCC diagnostic push
237
939
#pragma GCC diagnostic ignored "-Wnull-dereference"
238
939
#endif
239
939
      m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
240
939
#if defined(__GNUC__)
241
939
#pragma GCC diagnostic pop
242
939
#endif
243
60.1k
      for (unsigned int i = 0; i < numElements; i++)
244
59.2k
      {
245
59.2k
#ifdef GDAL_COMPILATION
246
59.2k
        if (dataVec[i] >= m_tmpLutVec.size())
247
37
          return false;
248
59.1k
#endif
249
59.1k
        dataVec[i] = m_tmpLutVec[dataVec[i]];
250
59.1k
      }
251
939
    }
252
76
    else
253
76
    {
254
      // unstuff indexes
255
76
      if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
256
1
        return false;
257
258
      // replace indexes by values
259
75
#if defined(__GNUC__)
260
75
#pragma GCC diagnostic push
261
75
#pragma GCC diagnostic ignored "-Wnull-dereference"
262
75
#endif
263
75
      m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
264
75
#if defined(__GNUC__)
265
75
#pragma GCC diagnostic pop
266
75
#endif
267
17.4k
      for (unsigned int i = 0; i < numElements; i++)
268
17.4k
      {
269
17.4k
        if (dataVec[i] >= m_tmpLutVec.size())
270
10
          return false;
271
272
17.4k
        dataVec[i] = m_tmpLutVec[dataVec[i]];
273
17.4k
      }
274
75
    }
275
1.03k
  }
276
277
5.54k
  return true;
278
5.71k
}
279
280
// -------------------------------------------------------------------------- ;
281
282
unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<pair<unsigned int, unsigned int> >& sortedDataVec, bool& doLut)
283
0
{
284
0
  unsigned int maxElem = sortedDataVec.back().first;
285
0
  unsigned int numElem = (unsigned int)sortedDataVec.size();
286
287
0
  int numBits = 0;
288
0
  while ((numBits < 32) && (maxElem >> numBits))
289
0
    numBits++;
290
0
  unsigned int numBytes = 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3);
291
292
  // go through and count how often the value changes
293
0
  int nLut = 0;
294
0
  for (unsigned int i = 1; i < numElem; i++)
295
0
    if (sortedDataVec[i].first != sortedDataVec[i - 1].first)
296
0
      nLut++;
297
298
0
  int nBitsLut = 0;
299
0
  while (nLut >> nBitsLut)
300
0
    nBitsLut++;
301
302
0
  unsigned int numBitsTotalLut = nLut * numBits;    // num bits w/o the 0
303
0
  unsigned int numBytesLut = 1 + NumBytesUInt(numElem) + 1 + ((numBitsTotalLut + 7) >> 3) + ((numElem * nBitsLut + 7) >> 3);
304
305
0
  doLut = numBytesLut < numBytes;
306
0
  return min(numBytesLut, numBytes);
307
0
}
308
309
// -------------------------------------------------------------------------- ;
310
// -------------------------------------------------------------------------- ;
311
312
void BitStuffer2::BitStuff_Before_Lerc2v3(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits)
313
0
{
314
0
  unsigned int numElements = (unsigned int)dataVec.size();
315
0
  unsigned int numUInts = (numElements * numBits + 31) / 32;
316
0
  unsigned int numBytes = numUInts * sizeof(unsigned int);
317
0
  unsigned int* arr = (unsigned int*)(*ppByte);
318
319
0
  memset(arr, 0, numBytes);
320
321
  // do the stuffing
322
0
  const unsigned int* srcPtr = &dataVec[0];
323
0
  unsigned int* dstPtr = arr;
324
0
  int bitPos = 0;
325
326
0
  for (unsigned int i = 0; i < numElements; i++)
327
0
  {
328
0
    if (32 - bitPos >= numBits)
329
0
    {
330
0
      unsigned int dstValue;
331
0
      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
332
0
      dstValue |= (*srcPtr++) << (32 - bitPos - numBits);
333
0
      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
334
0
      bitPos += numBits;
335
0
      if (bitPos == 32)    // shift >= 32 is undefined
336
0
      {
337
0
        bitPos = 0;
338
0
        dstPtr++;
339
0
      }
340
0
    }
341
0
    else
342
0
    {
343
0
      unsigned int dstValue;
344
0
      int n = numBits - (32 - bitPos);
345
0
      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
346
0
      dstValue |= (*srcPtr) >> n;
347
0
      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
348
0
      dstPtr++;
349
0
      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
350
0
      dstValue |= (*srcPtr++) << (32 - n);
351
0
      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
352
0
      bitPos = n;
353
0
    }
354
0
  }
355
356
  // save the 0-3 bytes not used in the last UInt
357
0
  unsigned int numBytesNotNeeded = NumTailBytesNotNeeded(numElements, numBits);
358
0
  unsigned int n = numBytesNotNeeded;
359
0
  for (; n; --n)
360
0
  {
361
0
    unsigned int dstValue;
362
0
    memcpy(&dstValue, dstPtr, sizeof(unsigned int));
363
0
    dstValue >>= 8;
364
0
    memcpy(dstPtr, &dstValue, sizeof(unsigned int));
365
0
  }
366
367
0
  *ppByte += numBytes - numBytesNotNeeded;
368
0
}
369
370
// -------------------------------------------------------------------------- ;
371
372
bool BitStuffer2::BitUnStuff_Before_Lerc2v3(const Byte** ppByte, size_t& nBytesRemaining,
373
    vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const
374
199
{
375
199
  if (numElements == 0 || numBits >= 32)
376
1
    return false;
377
198
  unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
378
198
  unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
379
198
  size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
380
198
  size_t numUInts = (size_t)numUIntsLL;
381
198
  unsigned int ntbnn = NumTailBytesNotNeeded(numElements, numBits);
382
198
  if (numBytes != numBytesLL || nBytesRemaining + ntbnn < numBytes)
383
1
    return false;
384
385
197
  try
386
197
  {
387
197
    dataVec.resize(numElements, 0);    // init with 0
388
197
    m_tmpBitStuffVec.resize(numUInts);
389
197
  }
390
197
  catch( const std::exception& )
391
197
  {
392
0
    return false;
393
0
  }
394
395
197
  m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
396
397
197
  unsigned int nBytesToCopy = (numElements * numBits + 7) / 8;
398
197
  memcpy(&m_tmpBitStuffVec[0], *ppByte, nBytesToCopy);
399
400
197
  unsigned int* pLastULong = &m_tmpBitStuffVec[numUInts - 1];
401
310
  while (ntbnn)
402
113
  {
403
113
    -- ntbnn;
404
113
    *pLastULong <<= 8;
405
113
  }
406
407
197
  unsigned int* srcPtr = &m_tmpBitStuffVec[0];
408
197
  unsigned int* dstPtr = &dataVec[0];
409
197
  int bitPos = 0;
410
411
31.7k
  for (unsigned int i = 0; i < numElements; i++)
412
31.5k
  {
413
31.5k
    if (32 - bitPos >= numBits)
414
28.3k
    {
415
28.3k
      unsigned int val;
416
28.3k
      memcpy(&val, srcPtr, sizeof(unsigned int));
417
28.3k
      unsigned int n = val << bitPos;
418
28.3k
      *dstPtr++ = n >> (32 - numBits);
419
28.3k
      bitPos += numBits;
420
421
28.3k
      if (bitPos == 32)    // shift >= 32 is undefined
422
2.31k
      {
423
2.31k
        bitPos = 0;
424
2.31k
        srcPtr++;
425
2.31k
      }
426
28.3k
    }
427
3.20k
    else
428
3.20k
    {
429
3.20k
      unsigned int val;
430
3.20k
      memcpy(&val, srcPtr, sizeof(unsigned int));
431
3.20k
      srcPtr++;
432
3.20k
      unsigned int n = val << bitPos;
433
3.20k
      *dstPtr = n >> (32 - numBits);
434
3.20k
      bitPos -= (32 - numBits);
435
3.20k
      memcpy(&val, srcPtr, sizeof(unsigned int));
436
3.20k
      *dstPtr++ |= val >> (32 - bitPos);
437
3.20k
    }
438
31.5k
  }
439
440
197
  *ppByte += nBytesToCopy;
441
197
  nBytesRemaining -= nBytesToCopy;
442
443
197
  return true;
444
197
}
445
446
// -------------------------------------------------------------------------- ;
447
448
// starting with version Lerc2v3: integer >> into local uint buffer, plus final memcpy
449
450
void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits) const
451
0
{
452
0
  unsigned int numElements = (unsigned int)dataVec.size();
453
0
  unsigned int numUInts = (numElements * numBits + 31) / 32;
454
0
  unsigned int numBytes = numUInts * sizeof(unsigned int);
455
456
0
  m_tmpBitStuffVec.resize(numUInts);
457
0
  unsigned int* dstPtr = &m_tmpBitStuffVec[0];
458
459
0
  memset(dstPtr, 0, numBytes);
460
461
  // do the stuffing
462
0
  const unsigned int* srcPtr = &dataVec[0];
463
0
  int bitPos = 0;
464
0
  assert(numBits <= 32); // to avoid coverity warning about large shift a bit later, when doing (*srcPtr++) >> (32 - bitPos)
465
466
0
  for (unsigned int i = 0; i < numElements; i++)
467
0
  {
468
0
    if (32 - bitPos >= numBits)
469
0
    {
470
0
      *dstPtr |= (*srcPtr++) << bitPos;
471
0
      bitPos += numBits;
472
0
      if (bitPos == 32)    // shift >= 32 is undefined
473
0
      {
474
0
        dstPtr++;
475
0
        bitPos = 0;
476
0
      }
477
0
    }
478
0
    else
479
0
    {
480
0
      *dstPtr++ |= (*srcPtr) << bitPos;
481
0
      *dstPtr |= (*srcPtr++) >> (32 - bitPos);
482
0
      bitPos += numBits - 32;
483
0
    }
484
0
  }
485
486
  // copy the bytes to the outgoing byte stream
487
0
  size_t numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
488
#ifdef CSA_BUILD
489
  assert( numElements );
490
#endif
491
0
  memcpy(*ppByte, m_tmpBitStuffVec.data(), numBytesUsed);
492
493
0
  *ppByte += numBytesUsed;
494
0
}
495
496
// -------------------------------------------------------------------------- ;
497
498
bool BitStuffer2::BitUnStuff(const Byte** ppByte, size_t& nBytesRemaining, vector<unsigned int>& dataVec,
499
  unsigned int numElements, int numBits) const
500
6.44k
{
501
6.44k
  if (numElements == 0 || numBits >= 32)
502
45
    return false;
503
6.40k
  unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
504
6.40k
  unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
505
6.40k
  size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
506
6.40k
  if (numBytes != numBytesLL)
507
0
    return false;
508
6.40k
  size_t numUInts = (size_t)numUIntsLL;
509
510
  // copy the bytes from the incoming byte stream
511
6.40k
  const size_t numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
512
513
6.40k
  if (nBytesRemaining < numBytesUsed)
514
77
    return false;
515
516
6.32k
  try
517
6.32k
  {
518
6.32k
    dataVec.resize(numElements);
519
6.32k
  }
520
6.32k
  catch( const std::exception& )
521
6.32k
  {
522
0
    return false;
523
0
  }
524
525
6.32k
  try
526
6.32k
  {
527
6.32k
    m_tmpBitStuffVec.resize(numUInts);
528
6.32k
  }
529
6.32k
  catch( const std::exception& )
530
6.32k
  {
531
0
    return false;
532
0
  }
533
534
6.32k
  m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
535
536
6.32k
  memcpy(&m_tmpBitStuffVec[0], *ppByte, numBytesUsed);
537
538
  // do the un-stuffing
539
6.32k
  unsigned int* srcPtr = &m_tmpBitStuffVec[0];
540
6.32k
  unsigned int* dstPtr = &dataVec[0];
541
6.32k
  int bitPos = 0;
542
6.32k
  int nb = 32 - numBits;
543
544
712k
  for (unsigned int i = 0; i < numElements; i++)
545
706k
  {
546
706k
    if (nb - bitPos >= 0)
547
688k
    {
548
688k
      *dstPtr++ = ((*srcPtr) << (nb - bitPos)) >> nb;
549
688k
      bitPos += numBits;
550
688k
      if (bitPos == 32)    // shift >= 32 is undefined
551
72.0k
      {
552
72.0k
        srcPtr++;
553
72.0k
        bitPos = 0;
554
72.0k
      }
555
688k
    }
556
18.0k
    else
557
18.0k
    {
558
18.0k
      *dstPtr = (*srcPtr++) >> bitPos;
559
18.0k
      *dstPtr++ |= ((*srcPtr) << (64 - numBits - bitPos)) >> nb;
560
18.0k
      bitPos -= nb;
561
18.0k
    }
562
706k
  }
563
564
6.32k
  *ppByte += numBytesUsed;
565
6.32k
  nBytesRemaining -= numBytesUsed;
566
6.32k
  return true;
567
6.32k
}
568
569
// -------------------------------------------------------------------------- ;
570