Coverage Report

Created: 2025-06-09 07:07

/src/gdal/frmts/rmf/rmfdem.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  Raster Matrix Format
4
 * Purpose:  Implementation of the ad-hoc compression algorithm used in
5
 *           GIS "Panorama"/"Integratsia".
6
 * Author:   Andrey Kiselev, dron@ak4719.spb.edu
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_conv.h"
15
16
#include "rmfdataset.h"
17
18
#include <limits>
19
20
/*
21
 * The encoded data stream is a series of records.
22
 *
23
 * Encoded record consist from the 1-byte record header followed by the
24
 * encoded data block. Header specifies the number of elements in the data
25
 * block and encoding type. Header format
26
 *
27
 * +---+---+---+---+---+---+---+---+
28
 * |   type    |       count       |
29
 * +---+---+---+---+---+---+---+---+
30
 *   7   6   5   4   3   2   1   0
31
 *
32
 * If count is zero then it means that there are more than 31 elements in this
33
 * record. Read the next byte in the stream and increase its value with 32 to
34
 * get the count. In this case maximum number of elements is 287.
35
 *
36
 * The "type" field specifies encoding type. It can be either difference
37
 * between the previous and the next data value (for the first element the
38
 * previous value is zero) or out-of-range codes.
39
 *
40
 * In case of "out of range" or "zero difference" values there are no more
41
 * elements in record after the header. Otherwise read as much encoded
42
 * elements as count specifies.
43
 */
44
45
typedef GInt32 DEMWorkT;
46
typedef GInt64 DEMDiffT;
47
48
// Encoding types
49
enum RmfTypes
50
{
51
    TYPE_OUT = 0x00,    // Value is out of range
52
    TYPE_ZERO = 0x20,   // Zero difference
53
    TYPE_INT4 = 0x40,   // Difference is 4-bit wide
54
    TYPE_INT8 = 0x60,   // Difference is 8-bit wide
55
    TYPE_INT12 = 0x80,  // Difference is 12-bit wide
56
    TYPE_INT16 = 0xA0,  // Difference is 16-bit wide
57
    TYPE_INT24 = 0xC0,  // Difference is 24-bit wide
58
    TYPE_INT32 = 0xE0   // Difference is 32-bit wide
59
};
60
61
// Encoding ranges
62
GInt32 RANGE_INT4 = 0x00000007L;   // 4-bit
63
GInt32 RANGE_INT8 = 0x0000007FL;   // 8-bit
64
GInt32 RANGE_INT12 = 0x000007FFL;  // 12-bit
65
GInt32 RANGE_INT16 = 0x00007FFFL;  // 16-bit
66
GInt32 RANGE_INT24 = 0x007FFFFFL;  // 24-bit
67
68
// Out of range codes
69
GInt32 OUT_INT4 = 0xFFFFFFF8;
70
GInt32 OUT_INT8 = 0xFFFFFF80;
71
GInt32 OUT_INT12 = 0xFFFFF800;
72
GInt32 OUT_INT16 = 0xFFFF8000;
73
GInt32 OUT_INT24 = 0xFF800000;
74
GInt32 OUT_INT32 = 0x80000000;
75
76
constexpr DEMDiffT DIFF_OUI_OF_RANGE = std::numeric_limits<DEMDiffT>::max();
77
78
// Inversion masks
79
GInt32 INV_INT4 = 0xFFFFFFF0L;
80
GInt32 INV_INT12 = 0xFFFFF000L;
81
GInt32 INV_INT24 = 0xFF000000L;
82
83
// Not sure which behavior we wish for int32 overflow, so just do the
84
// addition as uint32 to workaround -ftrapv
85
CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
86
static GInt32 AddInt32(GInt32 &nTarget, GInt32 nVal)
87
0
{
88
0
    GUInt32 nTargetU = static_cast<GUInt32>(nTarget);
89
0
    GUInt32 nValU = static_cast<GUInt32>(nVal);
90
0
    nTargetU += nValU;
91
0
    memcpy(&nTarget, &nTargetU, 4);
92
0
    return nTarget;
93
0
}
94
95
/************************************************************************/
96
/*                           DEMDecompress()                            */
97
/************************************************************************/
98
99
size_t RMFDataset::DEMDecompress(const GByte *pabyIn, GUInt32 nSizeIn,
100
                                 GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
101
                                 GUInt32)
102
0
{
103
0
    if (pabyIn == nullptr || pabyOut == nullptr || nSizeOut < nSizeIn ||
104
0
        nSizeIn < 2)
105
0
        return 0;
106
107
0
    GInt32 iPrev = 0;  // The last data value decoded.
108
109
0
    const signed char *pabyTempIn =
110
0
        reinterpret_cast<const signed char *>(pabyIn);
111
0
    GInt32 *paiOut = reinterpret_cast<GInt32 *>(pabyOut);
112
0
    nSizeOut /= sizeof(GInt32);
113
114
0
    while (nSizeIn > 0)
115
0
    {
116
        // Read number of codes in the record and encoding type.
117
0
        GUInt32 nCount = *pabyTempIn & 0x1F;
118
0
        const GUInt32 nType = *pabyTempIn++ & 0xE0;  // The encoding type.
119
0
        nSizeIn--;
120
0
        if (nCount == 0)
121
0
        {
122
0
            if (nSizeIn == 0)
123
0
                break;
124
0
            nCount = 32 + *reinterpret_cast<const GByte *>(pabyTempIn);
125
0
            pabyTempIn++;
126
0
            nSizeIn--;
127
0
        }
128
129
0
        switch (nType)
130
0
        {
131
0
            case TYPE_ZERO:
132
0
                if (nSizeOut < nCount)
133
0
                    break;
134
0
                nSizeOut -= nCount;
135
0
                while (nCount > 0)
136
0
                {
137
0
                    nCount--;
138
0
                    *paiOut++ = iPrev;
139
0
                }
140
0
                break;
141
142
0
            case TYPE_OUT:
143
0
                if (nSizeOut < nCount)
144
0
                    break;
145
0
                nSizeOut -= nCount;
146
0
                while (nCount > 0)
147
0
                {
148
0
                    nCount--;
149
0
                    *paiOut++ = OUT_INT32;
150
0
                }
151
0
                break;
152
153
0
            case TYPE_INT4:
154
0
                if (nSizeIn < (nCount + 1) / 2)
155
0
                    break;
156
0
                if (nSizeOut < nCount)
157
0
                    break;
158
0
                nSizeIn -= nCount / 2;
159
0
                nSizeOut -= nCount;
160
0
                while (nCount > 0)
161
0
                {
162
0
                    nCount--;
163
0
                    GInt32 nCode;
164
0
                    nCode = (*pabyTempIn) & 0x0F;
165
0
                    if (nCode > RANGE_INT4)
166
0
                        nCode |= INV_INT4;
167
0
                    *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
168
0
                                                    : AddInt32(iPrev, nCode);
169
170
0
                    if (nCount == 0)
171
0
                    {
172
0
                        if (nSizeIn)
173
0
                        {
174
0
                            pabyTempIn++;
175
0
                            nSizeIn--;
176
0
                        }
177
0
                        break;
178
0
                    }
179
0
                    nCount--;
180
181
0
                    nCode = ((*pabyTempIn++) >> 4) & 0x0F;
182
0
                    if (nCode > RANGE_INT4)
183
0
                        nCode |= INV_INT4;
184
0
                    *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
185
0
                                                    : AddInt32(iPrev, nCode);
186
0
                }
187
0
                break;
188
189
0
            case TYPE_INT8:
190
0
                if (nSizeIn < nCount)
191
0
                    break;
192
0
                if (nSizeOut < nCount)
193
0
                    break;
194
0
                nSizeIn -= nCount;
195
0
                nSizeOut -= nCount;
196
0
                while (nCount > 0)
197
0
                {
198
0
                    nCount--;
199
0
                    GInt32 nCode;
200
0
                    *paiOut++ = ((nCode = *pabyTempIn++) == OUT_INT8)
201
0
                                    ? OUT_INT32
202
0
                                    : AddInt32(iPrev, nCode);
203
0
                }
204
0
                break;
205
206
0
            case TYPE_INT12:
207
0
                if (nSizeIn < (3 * nCount + 1) / 2)
208
0
                    break;
209
0
                if (nSizeOut < nCount)
210
0
                    break;
211
0
                nSizeIn -= 3 * nCount / 2;
212
0
                nSizeOut -= nCount;
213
214
0
                while (nCount > 0)
215
0
                {
216
0
                    nCount--;
217
0
                    GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn) & 0x0FFF;
218
0
                    pabyTempIn += 1;
219
0
                    if (nCode > RANGE_INT12)
220
0
                        nCode |= INV_INT12;
221
0
                    *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
222
0
                                                     : AddInt32(iPrev, nCode);
223
224
0
                    if (nCount == 0)
225
0
                    {
226
0
                        if (nSizeIn)
227
0
                        {
228
0
                            pabyTempIn++;
229
0
                            nSizeIn--;
230
0
                        }
231
0
                        break;
232
0
                    }
233
0
                    nCount--;
234
235
0
                    nCode = (CPL_LSBSINT16PTR(pabyTempIn) >> 4) & 0x0FFF;
236
0
                    pabyTempIn += 2;
237
0
                    if (nCode > RANGE_INT12)
238
0
                        nCode |= INV_INT12;
239
0
                    *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
240
0
                                                     : AddInt32(iPrev, nCode);
241
0
                }
242
0
                break;
243
244
0
            case TYPE_INT16:
245
0
                if (nSizeIn < 2 * nCount)
246
0
                    break;
247
0
                if (nSizeOut < nCount)
248
0
                    break;
249
0
                nSizeIn -= 2 * nCount;
250
0
                nSizeOut -= nCount;
251
252
0
                while (nCount > 0)
253
0
                {
254
0
                    nCount--;
255
0
                    const GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn);
256
0
                    pabyTempIn += 2;
257
0
                    *paiOut++ = (nCode == OUT_INT16) ? OUT_INT32
258
0
                                                     : AddInt32(iPrev, nCode);
259
0
                }
260
0
                break;
261
262
0
            case TYPE_INT24:
263
0
                if (nSizeIn < 3 * nCount)
264
0
                    break;
265
0
                if (nSizeOut < nCount)
266
0
                    break;
267
0
                nSizeIn -= 3 * nCount;
268
0
                nSizeOut -= nCount;
269
270
0
                while (nCount > 0)
271
0
                {
272
0
                    nCount--;
273
0
                    GInt32 nCode =
274
0
                        (*reinterpret_cast<const GByte *>(pabyTempIn)) |
275
0
                        ((*reinterpret_cast<const GByte *>(pabyTempIn + 1))
276
0
                         << 8) |
277
0
                        ((*reinterpret_cast<const GByte *>(pabyTempIn + 2))
278
0
                         << 16);
279
0
                    pabyTempIn += 3;
280
0
                    if (nCode > RANGE_INT24)
281
0
                        nCode |= INV_INT24;
282
0
                    *paiOut++ = (nCode == OUT_INT24) ? OUT_INT32
283
0
                                                     : AddInt32(iPrev, nCode);
284
0
                }
285
0
                break;
286
287
0
            case TYPE_INT32:
288
0
                if (nSizeIn < 4 * nCount)
289
0
                    break;
290
0
                if (nSizeOut < nCount)
291
0
                    break;
292
0
                nSizeIn -= 4 * nCount;
293
0
                nSizeOut -= nCount;
294
295
0
                while (nCount > 0)
296
0
                {
297
0
                    nCount--;
298
0
                    GInt32 nCode = CPL_LSBSINT32PTR(pabyTempIn);
299
0
                    pabyTempIn += 4;
300
0
                    *paiOut++ = (nCode == OUT_INT32) ? OUT_INT32
301
0
                                                     : AddInt32(iPrev, nCode);
302
0
                }
303
0
                break;
304
0
        }
305
0
    }
306
307
0
    return reinterpret_cast<GByte *>(paiOut) - pabyOut;
308
0
}
309
310
/************************************************************************/
311
/*                            DEMWriteCode()                            */
312
/************************************************************************/
313
314
static CPLErr DEMWriteRecord(const DEMDiffT *paiRecord, RmfTypes eRecordType,
315
                             GUInt32 nRecordSize, GInt32 nSizeOut,
316
                             GByte *&pabyCurrent)
317
0
{
318
0
    const GUInt32 nMaxCountInHeader = 31;
319
0
    GInt32 iCode;
320
0
    GInt32 iPrevCode;
321
322
0
    if (nRecordSize <= nMaxCountInHeader)
323
0
    {
324
0
        nSizeOut -= 1;
325
0
        if (nSizeOut <= 0)
326
0
        {
327
0
            return CE_Failure;
328
0
        }
329
330
0
        *pabyCurrent++ = static_cast<GByte>(eRecordType | nRecordSize);
331
0
    }
332
0
    else
333
0
    {
334
0
        nSizeOut -= 2;
335
0
        if (nSizeOut <= 0)
336
0
        {
337
0
            return CE_Failure;
338
0
        }
339
340
0
        *pabyCurrent++ = static_cast<GByte>(eRecordType);
341
0
        *pabyCurrent++ = static_cast<GByte>(nRecordSize - 32);
342
0
    }
343
344
0
    switch (eRecordType)
345
0
    {
346
0
        case TYPE_INT4:
347
0
            nSizeOut -= ((nRecordSize + 1) / 2);
348
0
            if (nSizeOut <= 0)
349
0
            {
350
0
                return CE_Failure;
351
0
            }
352
353
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
354
0
            {
355
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
356
0
                {
357
0
                    iCode = OUT_INT4;
358
0
                }
359
0
                else
360
0
                {
361
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
362
0
                }
363
0
                *pabyCurrent = static_cast<GByte>(iCode & 0x0F);
364
365
0
                ++n;
366
0
                if (n == nRecordSize)
367
0
                {
368
0
                    pabyCurrent++;
369
0
                    break;
370
0
                }
371
372
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
373
0
                {
374
0
                    iCode = OUT_INT4;
375
0
                }
376
0
                else
377
0
                {
378
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
379
0
                }
380
0
                *pabyCurrent++ |= static_cast<GByte>((iCode & 0x0F) << 4);
381
0
            }
382
0
            break;
383
384
0
        case TYPE_INT8:
385
0
            nSizeOut -= nRecordSize;
386
0
            if (nSizeOut <= 0)
387
0
            {
388
0
                return CE_Failure;
389
0
            }
390
391
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
392
0
            {
393
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
394
0
                {
395
0
                    *pabyCurrent++ = static_cast<GByte>(OUT_INT8);
396
0
                }
397
0
                else
398
0
                {
399
0
                    *pabyCurrent++ = static_cast<GByte>(paiRecord[n]);
400
0
                }
401
0
            }
402
0
            break;
403
404
0
        case TYPE_INT12:
405
0
            nSizeOut -= ((nRecordSize * 3 + 1) / 2);
406
0
            if (nSizeOut <= 0)
407
0
            {
408
0
                return CE_Failure;
409
0
            }
410
411
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
412
0
            {
413
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
414
0
                {
415
0
                    iCode = OUT_INT12;
416
0
                }
417
0
                else
418
0
                {
419
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
420
0
                }
421
422
0
                iPrevCode = iCode;
423
0
                *pabyCurrent++ = static_cast<GByte>(iCode & 0x00FF);
424
425
0
                ++n;
426
0
                if (n == nRecordSize)
427
0
                {
428
0
                    *pabyCurrent++ =
429
0
                        static_cast<GByte>((iPrevCode & 0x0F00) >> 8);
430
0
                    break;
431
0
                }
432
433
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
434
0
                {
435
0
                    iCode = OUT_INT12;
436
0
                }
437
0
                else
438
0
                {
439
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
440
0
                }
441
0
                iCode = (((iPrevCode & 0x0F00) >> 8) | ((iCode & 0x0FFF) << 4));
442
443
0
                CPL_LSBPTR32(&iCode);
444
0
                memcpy(pabyCurrent, &iCode, 2);
445
0
                pabyCurrent += 2;
446
0
            }
447
0
            break;
448
449
0
        case TYPE_INT16:
450
0
            nSizeOut -= (nRecordSize * 2);
451
0
            if (nSizeOut <= 0)
452
0
            {
453
0
                return CE_Failure;
454
0
            }
455
456
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
457
0
            {
458
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
459
0
                {
460
0
                    iCode = OUT_INT16;
461
0
                }
462
0
                else
463
0
                {
464
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
465
0
                }
466
0
                CPL_LSBPTR32(&iCode);
467
0
                memcpy(pabyCurrent, &iCode, 2);
468
0
                pabyCurrent += 2;
469
0
            }
470
0
            break;
471
472
0
        case TYPE_INT24:
473
0
            nSizeOut -= (nRecordSize * 3);
474
0
            if (nSizeOut <= 0)
475
0
            {
476
0
                return CE_Failure;
477
0
            }
478
479
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
480
0
            {
481
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
482
0
                {
483
0
                    iCode = OUT_INT24;
484
0
                }
485
0
                else
486
0
                {
487
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
488
0
                }
489
0
                CPL_LSBPTR32(&iCode);
490
0
                memcpy(pabyCurrent, &iCode, 3);
491
0
                pabyCurrent += 3;
492
0
            }
493
0
            break;
494
495
0
        case TYPE_INT32:
496
0
            nSizeOut -= (nRecordSize * 4);
497
0
            if (nSizeOut <= 0)
498
0
            {
499
0
                return CE_Failure;
500
0
            }
501
502
0
            for (GUInt32 n = 0; n != nRecordSize; ++n)
503
0
            {
504
0
                if (paiRecord[n] == DIFF_OUI_OF_RANGE)
505
0
                {
506
0
                    iCode = OUT_INT32;
507
0
                }
508
0
                else
509
0
                {
510
0
                    iCode = static_cast<GInt32>(paiRecord[n]);
511
0
                }
512
0
                CPL_LSBPTR32(&iCode);
513
0
                memcpy(pabyCurrent, &iCode, 4);
514
0
                pabyCurrent += 4;
515
0
            }
516
0
            break;
517
518
0
        case TYPE_ZERO:
519
0
        case TYPE_OUT:
520
0
            break;
521
522
0
        default:
523
0
            return CE_Failure;
524
0
    }
525
526
0
    return CE_None;
527
0
}
528
529
/************************************************************************/
530
/*                             DEMDeltaType()                           */
531
/************************************************************************/
532
533
static RmfTypes DEMDeltaType(DEMDiffT delta)
534
0
{
535
0
    if (delta <= RANGE_INT12)
536
0
    {
537
0
        if (delta <= RANGE_INT4)
538
0
        {
539
0
            if (delta == 0)
540
0
            {
541
0
                return TYPE_ZERO;
542
0
            }
543
0
            else
544
0
            {
545
0
                return TYPE_INT4;
546
0
            }
547
0
        }
548
0
        else
549
0
        {
550
0
            if (delta <= RANGE_INT8)
551
0
            {
552
0
                return TYPE_INT8;
553
0
            }
554
0
            else
555
0
            {
556
0
                return TYPE_INT12;
557
0
            }
558
0
        }
559
0
    }
560
0
    else
561
0
    {
562
0
        if (delta <= RANGE_INT24)
563
0
        {
564
0
            if (delta <= RANGE_INT16)
565
0
            {
566
0
                return TYPE_INT16;
567
0
            }
568
0
            else
569
0
            {
570
0
                return TYPE_INT24;
571
0
            }
572
0
        }
573
0
        else
574
0
        {
575
0
            return TYPE_INT32;
576
0
        }
577
0
    }
578
0
}
579
580
/************************************************************************/
581
/*                             DEMCompress()                            */
582
/************************************************************************/
583
584
size_t RMFDataset::DEMCompress(const GByte *pabyIn, GUInt32 nSizeIn,
585
                               GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
586
                               GUInt32, const RMFDataset *poDS)
587
0
{
588
0
    if (pabyIn == nullptr || pabyOut == nullptr || nSizeIn < sizeof(DEMWorkT))
589
0
        return 0;
590
591
0
    const GUInt32 anDeltaTypeSize[8] = {0, 0, 4, 8, 12, 16, 24, 32};
592
0
    const GUInt32 nMaxRecordSize = 255 + 32;
593
594
0
    DEMWorkT iMin(std::numeric_limits<DEMWorkT>::min() + 1);
595
0
    if (poDS != nullptr &&
596
0
        poDS->sHeader.adfElevMinMax[0] < poDS->sHeader.adfElevMinMax[1])
597
0
    {
598
0
        iMin = static_cast<DEMWorkT>(poDS->sHeader.adfElevMinMax[0]);
599
0
    }
600
0
    GUInt32 nLessCount = 0;
601
0
    GUInt32 nRecordSize = 0;
602
0
    RmfTypes eRecordType = TYPE_OUT;
603
0
    DEMDiffT aiRecord[nMaxRecordSize] = {0};
604
0
    DEMWorkT aiPrev[nMaxRecordSize] = {0};
605
606
0
    GByte *pabyCurrent = pabyOut;
607
0
    DEMWorkT iPrev = 0;
608
609
0
    nSizeIn = nSizeIn / sizeof(DEMWorkT);
610
611
0
    const DEMWorkT *paiIn = reinterpret_cast<const DEMWorkT *>(pabyIn);
612
0
    const DEMWorkT *paiInEnd = paiIn + nSizeIn;
613
614
0
    while (true)
615
0
    {
616
0
        GUInt32 nRecordElementSize = 0;
617
618
0
        if (paiIn >= paiInEnd)
619
0
        {
620
0
            if (nRecordSize == 0)
621
0
            {
622
0
                return pabyCurrent - pabyOut;
623
0
            }
624
625
0
            if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
626
0
                                          nSizeOut, pabyCurrent))
627
0
            {
628
0
                return 0;
629
0
            }
630
0
            nRecordSize = 0;
631
0
            continue;
632
0
        }
633
634
0
        DEMWorkT iCurr = *(paiIn++);
635
0
        RmfTypes eCurrType;
636
637
0
        if (iCurr < iMin)
638
0
        {
639
0
            eCurrType = TYPE_OUT;
640
0
            aiRecord[nRecordSize] = DIFF_OUI_OF_RANGE;
641
0
            aiPrev[nRecordSize] = iPrev;
642
0
        }
643
0
        else
644
0
        {
645
0
            DEMDiffT delta =
646
0
                static_cast<DEMDiffT>(iCurr) - static_cast<DEMDiffT>(iPrev);
647
648
0
            aiRecord[nRecordSize] = delta;
649
0
            aiPrev[nRecordSize] = iCurr;
650
651
0
            if (delta < 0)
652
0
                delta = -delta;
653
654
0
            eCurrType = DEMDeltaType(delta);
655
0
            iPrev = iCurr;
656
0
        }
657
0
        nRecordSize++;
658
659
0
        if (nRecordSize == 1)
660
0
        {
661
0
            eRecordType = eCurrType;
662
            // nRecordElementSize = anDeltaTypeSize[eCurrType >> 5];
663
0
            continue;
664
0
        }
665
666
0
        if (nRecordSize == nMaxRecordSize)
667
0
        {
668
0
            nLessCount = 0;
669
0
            if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
670
0
                                          nSizeOut, pabyCurrent))
671
0
            {
672
0
                return 0;
673
0
            }
674
0
            iPrev = aiPrev[nRecordSize - 1];
675
0
            nRecordSize = 0;
676
0
            continue;
677
0
        }
678
679
0
        if (eCurrType == eRecordType)
680
0
        {
681
0
            nLessCount = 0;
682
0
            continue;
683
0
        }
684
685
0
        if ((eCurrType > eRecordType) || (eCurrType | eRecordType) == TYPE_ZERO)
686
0
        {
687
0
            --paiIn;
688
0
            if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
689
0
                                          nRecordSize - 1, nSizeOut,
690
0
                                          pabyCurrent))
691
0
            {
692
0
                return 0;
693
0
            }
694
0
            iPrev = aiPrev[nRecordSize - 2];
695
0
            nRecordSize = 0;
696
0
            nLessCount = 0;
697
0
            continue;
698
0
        }
699
700
0
        nLessCount++;
701
702
0
        GUInt32 nDeltaSize(anDeltaTypeSize[eCurrType >> 5]);
703
0
        if (nRecordElementSize < nDeltaSize ||
704
0
            (nRecordElementSize - nDeltaSize) * nLessCount < 16)
705
0
        {
706
0
            continue;
707
0
        }
708
709
0
        paiIn -= nLessCount;
710
0
        if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
711
0
                                      nRecordSize - nLessCount, nSizeOut,
712
0
                                      pabyCurrent))
713
0
        {
714
0
            return 0;
715
0
        }
716
0
        iPrev = aiPrev[nRecordSize - nLessCount - 1];
717
0
        nRecordSize = 0;
718
0
        nLessCount = 0;
719
0
    }
720
721
0
    return 0;
722
0
}