Coverage Report

Created: 2025-06-13 06:29

/src/gdal/third_party/LercLib/BitStuffer2.cpp
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
#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
0
{
161
0
  if (!ppByte || nBytesRemaining < 1)
162
0
    return false;
163
164
0
  Byte numBitsByte = **ppByte;
165
0
  (*ppByte)++;
166
0
  nBytesRemaining--;
167
168
0
  int bits67 = numBitsByte >> 6;
169
0
  int nb = (bits67 == 0) ? 4 : 3 - bits67;
170
171
0
  bool doLut = (numBitsByte & (1 << 5)) ? true : false;    // bit 5
172
0
  numBitsByte &= 31;    // bits 0-4;
173
0
  int numBits = numBitsByte;
174
175
0
  unsigned int numElements = 0;
176
0
  if (!DecodeUInt(ppByte, nBytesRemaining, numElements, nb))
177
0
    return false;
178
0
  if (numElements > maxElementCount)
179
0
    return false;
180
181
0
  if (!doLut)
182
0
  {
183
0
    if (numBits > 0)    // numBits can be 0
184
0
    {
185
0
      if (lerc2Version >= 3)
186
0
      {
187
0
        if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, numBits))
188
0
          return false;
189
0
      }
190
0
      else
191
0
      {
192
0
        if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, numBits))
193
0
          return false;
194
0
      }
195
0
    }
196
0
  }
197
0
  else
198
0
  {
199
0
    if (numBits == 0)  // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum
200
0
      return false;
201
0
    if (nBytesRemaining < 1)
202
0
      return false;
203
204
0
    Byte nLutByte = **ppByte;
205
0
    (*ppByte)++;
206
0
    nBytesRemaining--;
207
208
0
    int nLut = nLutByte - 1;
209
210
    // unstuff lut w/o the 0
211
0
    if (lerc2Version >= 3)
212
0
    {
213
0
      if (!BitUnStuff(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
214
0
        return false;
215
0
    }
216
0
    else
217
0
    {
218
0
      if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
219
0
        return false;
220
0
    }
221
222
0
    int nBitsLut = 0;
223
0
    while (nLut >> nBitsLut)
224
0
      nBitsLut++;
225
0
    if (nBitsLut == 0)
226
0
      return false;
227
228
0
    if (lerc2Version >= 3)
229
0
    {
230
      // unstuff indexes
231
0
      if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
232
0
        return false;
233
234
      // replace indexes by values
235
0
#if defined(__GNUC__)
236
0
#pragma GCC diagnostic push
237
0
#pragma GCC diagnostic ignored "-Wnull-dereference"
238
0
#endif
239
0
      m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
240
0
#if defined(__GNUC__)
241
0
#pragma GCC diagnostic pop
242
0
#endif
243
0
      for (unsigned int i = 0; i < numElements; i++)
244
0
      {
245
0
#ifdef GDAL_COMPILATION
246
0
        if (dataVec[i] >= m_tmpLutVec.size())
247
0
          return false;
248
0
#endif
249
0
        dataVec[i] = m_tmpLutVec[dataVec[i]];
250
0
      }
251
0
    }
252
0
    else
253
0
    {
254
      // unstuff indexes
255
0
      if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
256
0
        return false;
257
258
      // replace indexes by values
259
0
#if defined(__GNUC__)
260
0
#pragma GCC diagnostic push
261
0
#pragma GCC diagnostic ignored "-Wnull-dereference"
262
0
#endif
263
0
      m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
264
0
#if defined(__GNUC__)
265
0
#pragma GCC diagnostic pop
266
0
#endif
267
0
      for (unsigned int i = 0; i < numElements; i++)
268
0
      {
269
0
        if (dataVec[i] >= m_tmpLutVec.size())
270
0
          return false;
271
272
0
        dataVec[i] = m_tmpLutVec[dataVec[i]];
273
0
      }
274
0
    }
275
0
  }
276
277
0
  return true;
278
0
}
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
0
{
375
0
  if (numElements == 0 || numBits >= 32)
376
0
    return false;
377
0
  unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
378
0
  unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
379
0
  size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
380
0
  size_t numUInts = (size_t)numUIntsLL;
381
0
  unsigned int ntbnn = NumTailBytesNotNeeded(numElements, numBits);
382
0
  if (numBytes != numBytesLL || nBytesRemaining + ntbnn < numBytes)
383
0
    return false;
384
385
0
  try
386
0
  {
387
0
    dataVec.resize(numElements, 0);    // init with 0
388
0
    m_tmpBitStuffVec.resize(numUInts);
389
0
  }
390
0
  catch( const std::exception& )
391
0
  {
392
0
    return false;
393
0
  }
394
395
0
  m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
396
397
0
  unsigned int nBytesToCopy = (numElements * numBits + 7) / 8;
398
0
  memcpy(&m_tmpBitStuffVec[0], *ppByte, nBytesToCopy);
399
400
0
  unsigned int* pLastULong = &m_tmpBitStuffVec[numUInts - 1];
401
0
  while (ntbnn)
402
0
  {
403
0
    -- ntbnn;
404
0
    *pLastULong <<= 8;
405
0
  }
406
407
0
  unsigned int* srcPtr = &m_tmpBitStuffVec[0];
408
0
  unsigned int* dstPtr = &dataVec[0];
409
0
  int bitPos = 0;
410
411
0
  for (unsigned int i = 0; i < numElements; i++)
412
0
  {
413
0
    if (32 - bitPos >= numBits)
414
0
    {
415
0
      unsigned int val;
416
0
      memcpy(&val, srcPtr, sizeof(unsigned int));
417
0
      unsigned int n = val << bitPos;
418
0
      *dstPtr++ = n >> (32 - numBits);
419
0
      bitPos += numBits;
420
421
0
      if (bitPos == 32)    // shift >= 32 is undefined
422
0
      {
423
0
        bitPos = 0;
424
0
        srcPtr++;
425
0
      }
426
0
    }
427
0
    else
428
0
    {
429
0
      unsigned int val;
430
0
      memcpy(&val, srcPtr, sizeof(unsigned int));
431
0
      srcPtr++;
432
0
      unsigned int n = val << bitPos;
433
0
      *dstPtr = n >> (32 - numBits);
434
0
      bitPos -= (32 - numBits);
435
0
      memcpy(&val, srcPtr, sizeof(unsigned int));
436
0
      *dstPtr++ |= val >> (32 - bitPos);
437
0
    }
438
0
  }
439
440
0
  *ppByte += nBytesToCopy;
441
0
  nBytesRemaining -= nBytesToCopy;
442
443
0
  return true;
444
0
}
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
0
{
501
0
  if (numElements == 0 || numBits >= 32)
502
0
    return false;
503
0
  unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
504
0
  unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
505
0
  size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
506
0
  if (numBytes != numBytesLL)
507
0
    return false;
508
0
  size_t numUInts = (size_t)numUIntsLL;
509
510
  // copy the bytes from the incoming byte stream
511
0
  const size_t numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
512
513
0
  if (nBytesRemaining < numBytesUsed)
514
0
    return false;
515
516
0
  try
517
0
  {
518
0
    dataVec.resize(numElements);
519
0
  }
520
0
  catch( const std::exception& )
521
0
  {
522
0
    return false;
523
0
  }
524
525
0
  try
526
0
  {
527
0
    m_tmpBitStuffVec.resize(numUInts);
528
0
  }
529
0
  catch( const std::exception& )
530
0
  {
531
0
    return false;
532
0
  }
533
534
0
  m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
535
536
0
  memcpy(&m_tmpBitStuffVec[0], *ppByte, numBytesUsed);
537
538
  // do the un-stuffing
539
0
  unsigned int* srcPtr = &m_tmpBitStuffVec[0];
540
0
  unsigned int* dstPtr = &dataVec[0];
541
0
  int bitPos = 0;
542
0
  int nb = 32 - numBits;
543
544
0
  for (unsigned int i = 0; i < numElements; i++)
545
0
  {
546
0
    if (nb - bitPos >= 0)
547
0
    {
548
0
      *dstPtr++ = ((*srcPtr) << (nb - bitPos)) >> nb;
549
0
      bitPos += numBits;
550
0
      if (bitPos == 32)    // shift >= 32 is undefined
551
0
      {
552
0
        srcPtr++;
553
0
        bitPos = 0;
554
0
      }
555
0
    }
556
0
    else
557
0
    {
558
0
      *dstPtr = (*srcPtr++) >> bitPos;
559
0
      *dstPtr++ |= ((*srcPtr) << (64 - numBits - bitPos)) >> nb;
560
0
      bitPos -= nb;
561
0
    }
562
0
  }
563
564
0
  *ppByte += numBytesUsed;
565
0
  nBytesRemaining -= numBytesUsed;
566
0
  return true;
567
0
}
568
569
// -------------------------------------------------------------------------- ;
570