Coverage Report

Created: 2025-06-13 06:29

/src/gdal/third_party/LercLib/RLE.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 "Defines.h"
25
#include "RLE.h"
26
#include <cstring>
27
28
USING_NAMESPACE_LERC
29
30
// -------------------------------------------------------------------------- ;
31
32
size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
33
0
{
34
0
  if (arr == nullptr || numBytes == 0)
35
0
    return 0;
36
37
0
  const Byte* ptr = arr;
38
0
  size_t sum = 0;
39
0
  size_t cntOdd = 0;
40
0
  size_t cntEven = 0;
41
0
  size_t cntTotal = 0;
42
0
  bool bOdd = true;
43
44
0
  while (cntTotal < numBytes - 1)
45
0
  {
46
0
    if (*ptr != *(ptr + 1))
47
0
    {
48
0
      if (bOdd)
49
0
      {
50
0
        cntOdd++;
51
0
      }
52
0
      else    // switch to odd mode
53
0
      {
54
0
        sum += 2 + 1;
55
0
        bOdd = true;
56
0
        cntOdd = 0;
57
0
        cntEven = 0;
58
0
      }
59
0
    }
60
0
    else
61
0
    {
62
0
      if (!bOdd)
63
0
      {
64
0
        cntEven++;
65
0
      }
66
0
      else
67
0
      {
68
        // count if we have enough equal bytes so it is worth switching to even
69
0
        bool foundEnough = false;
70
0
        if (cntTotal + m_minNumEven < numBytes)
71
0
        {
72
0
          int i = 1;
73
0
          while (i < m_minNumEven && ptr[i] == ptr[0]) i++;
74
0
          foundEnough = i < m_minNumEven ? false : true;
75
0
        }
76
77
0
        if (!foundEnough)    // stay in odd mode
78
0
        {
79
0
          cntOdd++;
80
0
        }
81
0
        else    // switch to even mode
82
0
        {
83
0
          if (cntOdd > 0)
84
0
            sum += 2 + cntOdd;
85
0
          bOdd = false;
86
0
          cntOdd = 0;
87
0
          cntEven = 0;
88
0
          cntEven++;
89
0
        }
90
0
      }
91
0
    }
92
0
    ptr++;
93
0
    cntTotal++;
94
95
0
    if (cntOdd == 32767)    // prevent short counters from overflow
96
0
    {
97
0
      sum += 2 + 32767;
98
0
      cntOdd = 0;
99
0
    }
100
0
    if (cntEven == 32767)
101
0
    {
102
0
      sum += 2 + 1;
103
0
      cntEven = 0;
104
0
    }
105
0
  }
106
107
  // don't forget the last byte
108
0
  if (bOdd)
109
0
  {
110
0
    cntOdd++;
111
0
    sum += 2 + cntOdd;
112
0
  }
113
0
  else
114
0
  {
115
0
    sum += 2 + 1;
116
0
  }
117
118
0
  return sum + 2;    // EOF short
119
0
}
120
121
// -------------------------------------------------------------------------- ;
122
123
bool RLE::compress(const Byte* arr, size_t numBytes,
124
                   Byte** arrRLE, size_t& numBytesRLE, bool verify) const
125
0
{
126
0
  if (arr == nullptr || numBytes == 0)
127
0
    return false;
128
129
0
  numBytesRLE = computeNumBytesRLE(arr, numBytes);
130
131
0
  *arrRLE = new Byte[numBytesRLE];
132
0
  if (!*arrRLE)
133
0
    return false;
134
135
0
  const Byte* srcPtr = arr;
136
0
  Byte* cntPtr = *arrRLE;
137
0
  Byte* dstPtr = cntPtr + 2;
138
  //size_t sum = 0;
139
0
  size_t cntOdd = 0;
140
0
  size_t cntEven = 0;
141
0
  size_t cntTotal = 0;
142
0
  bool bOdd = true;
143
144
0
  while (cntTotal < numBytes - 1)
145
0
  {
146
0
    if (*srcPtr != *(srcPtr + 1))
147
0
    {
148
0
      *dstPtr++ = *srcPtr;
149
0
      if (bOdd)
150
0
      {
151
0
        cntOdd++;
152
0
      }
153
0
      else    // switch to odd mode
154
0
      {
155
0
        cntEven++;
156
0
        writeCount(-(short)cntEven, &cntPtr, &dstPtr);    // - sign for even cnts
157
        //sum += 2 + 1;
158
0
        bOdd = true;
159
0
        cntOdd = 0;
160
0
        cntEven = 0;
161
0
      }
162
0
    }
163
0
    else
164
0
    {
165
0
      if (!bOdd)
166
0
      {
167
0
        cntEven++;
168
0
      }
169
0
      else
170
0
      {
171
        // count if we have enough equal bytes so it is worth switching to even
172
0
        bool foundEnough = false;
173
0
        if (cntTotal + m_minNumEven < numBytes)
174
0
        {
175
0
          int i = 1;
176
0
          while (i < m_minNumEven && srcPtr[i] == srcPtr[0]) i++;
177
0
          foundEnough = i < m_minNumEven ? false : true;
178
0
        }
179
180
0
        if (!foundEnough)    // stay in odd mode
181
0
        {
182
0
          *dstPtr++ = *srcPtr;
183
0
          cntOdd++;
184
0
        }
185
0
        else    // switch to even mode
186
0
        {
187
0
          if (cntOdd > 0)
188
0
          {
189
0
            writeCount((short)cntOdd, &cntPtr, &dstPtr);    // + sign for odd cnts
190
            //sum += 2 + cntOdd;
191
0
          }
192
0
          bOdd = false;
193
0
          cntOdd = 0;
194
0
          cntEven = 0;
195
0
          cntEven++;
196
0
        }
197
0
      }
198
0
    }
199
200
0
    if (cntOdd == 32767)    // prevent short counters from overflow
201
0
    {
202
0
      writeCount((short)cntOdd, &cntPtr, &dstPtr);
203
      //sum += 2 + 32767;
204
0
      cntOdd = 0;
205
0
    }
206
0
    if (cntEven == 32767)
207
0
    {
208
0
      *dstPtr++ = *srcPtr;
209
0
      writeCount(-(short)cntEven, &cntPtr, &dstPtr);
210
      //sum += 2 + 1;
211
0
      cntEven = 0;
212
0
    }
213
214
0
    srcPtr++;
215
0
    cntTotal++;
216
0
  }
217
218
  // don't forget the last byte
219
0
  *dstPtr++ = *srcPtr;
220
0
  if (bOdd)
221
0
  {
222
0
    cntOdd++;
223
0
    writeCount((short)cntOdd, &cntPtr, &dstPtr);
224
    //sum += 2 + cntOdd;
225
0
  }
226
0
  else
227
0
  {
228
0
    cntEven++;
229
0
    writeCount(-(short)cntEven, &cntPtr, &dstPtr);
230
    //sum += 2 + 1;
231
0
  }
232
233
0
  writeCount(-32768, &cntPtr, &dstPtr);    // write end of stream symbol
234
  //sum += 2;
235
236
0
  if (verify)
237
0
  {
238
0
    Byte* arr2 = nullptr;
239
0
    size_t numBytes2 = 0;
240
0
    if (!decompress(*arrRLE, numBytesRLE, &arr2, numBytes2) || numBytes2 != numBytes)
241
0
    {
242
0
      delete[] arr2;
243
0
      return false;
244
0
    }
245
0
    int nCheck = memcmp(arr, arr2, numBytes);
246
0
    delete[] arr2;
247
0
    if (nCheck != 0)
248
0
      return false;
249
0
  }
250
251
0
  return true;
252
0
}
253
254
// -------------------------------------------------------------------------- ;
255
256
bool RLE::decompress(const Byte* arrRLE, size_t nBytesRemainingIn, Byte** arr, size_t& numBytes)
257
0
{
258
0
  if (!arrRLE || nBytesRemainingIn < 2)
259
0
    return false;
260
261
  // first count the encoded bytes
262
0
  const Byte* srcPtr = arrRLE;
263
0
  size_t nBytesRemaining = nBytesRemainingIn - 2;
264
0
  size_t sum = 0;
265
266
0
  short cnt = readCount(&srcPtr);
267
0
  while (cnt != -32768)
268
0
  {
269
0
    sum += cnt < 0 ? -cnt : cnt;
270
0
    size_t n = cnt > 0 ? cnt : 1;
271
272
0
    if (nBytesRemaining < n + 2)
273
0
      return false;
274
275
0
    srcPtr += n;
276
0
    cnt = readCount(&srcPtr);
277
278
0
    nBytesRemaining -= n + 2;
279
0
  }
280
281
0
  numBytes = sum;
282
283
0
  if (numBytes == 0)
284
0
  {
285
0
    *arr = nullptr;
286
0
    return false;
287
0
  }
288
289
0
  *arr = new Byte[numBytes];
290
0
  if (!*arr)
291
0
    return false;
292
293
0
  return decompress(arrRLE, nBytesRemainingIn, *arr, numBytes);
294
0
}
295
296
// -------------------------------------------------------------------------- ;
297
298
bool RLE::decompress(const Byte* arrRLE, size_t nBytesRemaining, Byte* arr, size_t arrSize)
299
0
{
300
0
  if (!arrRLE || !arr || nBytesRemaining < 2)
301
0
    return false;
302
303
0
  const Byte* srcPtr = arrRLE;
304
0
  size_t arrIdx = 0;
305
0
  nBytesRemaining -= 2;
306
307
0
  short cnt = readCount(&srcPtr);
308
0
  while (cnt != -32768)
309
0
  {
310
0
    int i = (cnt <= 0) ? -cnt : cnt;
311
0
    size_t m = (cnt <= 0) ? 1 : (size_t)i;  // <= not < to fail gracefully in case of corrupted blob for old version <= 2 which had no checksum
312
313
0
    if (nBytesRemaining < m + 2 || arrIdx + i > arrSize)
314
0
      return false;
315
316
0
    if (cnt > 0)
317
0
    {
318
0
      while (i--) arr[arrIdx++] = *srcPtr++;
319
0
    }
320
0
    else
321
0
    {
322
0
      Byte b = *srcPtr++;
323
0
      while (i--) arr[arrIdx++] = b;
324
0
    }
325
326
0
    nBytesRemaining -= m + 2;
327
0
    cnt = readCount(&srcPtr);
328
0
  }
329
330
0
  return true;
331
0
}
332
333
// -------------------------------------------------------------------------- ;
334
335
void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst)
336
0
{
337
0
  SWAP_2(cnt);    // write short's in little endian byte order, always
338
#ifdef CSA_BUILD
339
  (*ppCnt)[0] = static_cast<Byte>(cnt);
340
  (*ppCnt)[1] = static_cast<Byte>(cnt >> 8);
341
#else
342
0
  memcpy(*ppCnt, &cnt, sizeof(short));
343
0
#endif
344
0
  *ppCnt = *ppDst;
345
0
  *ppDst += 2;
346
0
}
347
348
// -------------------------------------------------------------------------- ;
349
350
short RLE::readCount(const Byte** ppCnt)
351
0
{
352
0
  short cnt;
353
0
  memcpy(&cnt, *ppCnt, sizeof(short));
354
0
  SWAP_2(cnt);
355
0
  *ppCnt += 2;
356
0
  return cnt;
357
0
}
358
359
// -------------------------------------------------------------------------- ;
360