Line data Source code
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 542772 : static GInt32 AddInt32(GInt32 &nTarget, GInt32 nVal)
87 : {
88 542772 : GUInt32 nTargetU = static_cast<GUInt32>(nTarget);
89 542772 : GUInt32 nValU = static_cast<GUInt32>(nVal);
90 542772 : nTargetU += nValU;
91 542772 : memcpy(&nTarget, &nTargetU, 4);
92 542772 : return nTarget;
93 : }
94 :
95 : /************************************************************************/
96 : /* DEMDecompress() */
97 : /************************************************************************/
98 :
99 18 : size_t RMFDataset::DEMDecompress(const GByte *pabyIn, GUInt32 nSizeIn,
100 : GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
101 : GUInt32)
102 : {
103 18 : if (pabyIn == nullptr || pabyOut == nullptr || nSizeOut < nSizeIn ||
104 : nSizeIn < 2)
105 0 : return 0;
106 :
107 18 : GInt32 iPrev = 0; // The last data value decoded.
108 :
109 18 : const signed char *pabyTempIn =
110 : reinterpret_cast<const signed char *>(pabyIn);
111 18 : GInt32 *paiOut = reinterpret_cast<GInt32 *>(pabyOut);
112 18 : nSizeOut /= sizeof(GInt32);
113 :
114 61662 : while (nSizeIn > 0)
115 : {
116 : // Read number of codes in the record and encoding type.
117 61644 : GUInt32 nCount = *pabyTempIn & 0x1F;
118 61644 : const GUInt32 nType = *pabyTempIn++ & 0xE0; // The encoding type.
119 61644 : nSizeIn--;
120 61644 : if (nCount == 0)
121 : {
122 1668 : if (nSizeIn == 0)
123 0 : break;
124 1668 : nCount = 32 + *reinterpret_cast<const GByte *>(pabyTempIn);
125 1668 : pabyTempIn++;
126 1668 : nSizeIn--;
127 : }
128 :
129 61644 : switch (nType)
130 : {
131 17994 : case TYPE_ZERO:
132 17994 : if (nSizeOut < nCount)
133 0 : break;
134 17994 : nSizeOut -= nCount;
135 98978 : while (nCount > 0)
136 : {
137 80984 : nCount--;
138 80984 : *paiOut++ = iPrev;
139 : }
140 17994 : break;
141 :
142 1564 : case TYPE_OUT:
143 1564 : if (nSizeOut < nCount)
144 0 : break;
145 1564 : nSizeOut -= nCount;
146 26086 : while (nCount > 0)
147 : {
148 24522 : nCount--;
149 24522 : *paiOut++ = OUT_INT32;
150 : }
151 1564 : break;
152 :
153 1874 : case TYPE_INT4:
154 1874 : if (nSizeIn < (nCount + 1) / 2)
155 0 : break;
156 1874 : if (nSizeOut < nCount)
157 0 : break;
158 1874 : nSizeIn -= nCount / 2;
159 1874 : nSizeOut -= nCount;
160 4902 : while (nCount > 0)
161 : {
162 4014 : nCount--;
163 : GInt32 nCode;
164 4014 : nCode = (*pabyTempIn) & 0x0F;
165 4014 : if (nCode > RANGE_INT4)
166 1752 : nCode |= INV_INT4;
167 4014 : *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
168 3994 : : AddInt32(iPrev, nCode);
169 :
170 4014 : if (nCount == 0)
171 : {
172 986 : if (nSizeIn)
173 : {
174 986 : pabyTempIn++;
175 986 : nSizeIn--;
176 : }
177 986 : break;
178 : }
179 3028 : nCount--;
180 :
181 3028 : nCode = ((*pabyTempIn++) >> 4) & 0x0F;
182 3028 : if (nCode > RANGE_INT4)
183 1222 : nCode |= INV_INT4;
184 6036 : *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
185 3008 : : AddInt32(iPrev, nCode);
186 : }
187 1874 : break;
188 :
189 5924 : case TYPE_INT8:
190 5924 : if (nSizeIn < nCount)
191 0 : break;
192 5924 : if (nSizeOut < nCount)
193 0 : break;
194 5924 : nSizeIn -= nCount;
195 5924 : nSizeOut -= nCount;
196 50708 : while (nCount > 0)
197 : {
198 44784 : nCount--;
199 : GInt32 nCode;
200 44784 : *paiOut++ = ((nCode = *pabyTempIn++) == OUT_INT8)
201 44784 : ? OUT_INT32
202 44766 : : AddInt32(iPrev, nCode);
203 : }
204 5924 : break;
205 :
206 15482 : case TYPE_INT12:
207 15482 : if (nSizeIn < (3 * nCount + 1) / 2)
208 0 : break;
209 15482 : if (nSizeOut < nCount)
210 0 : break;
211 15482 : nSizeIn -= 3 * nCount / 2;
212 15482 : nSizeOut -= nCount;
213 :
214 78758 : while (nCount > 0)
215 : {
216 71274 : nCount--;
217 71274 : GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn) & 0x0FFF;
218 71274 : pabyTempIn += 1;
219 71274 : if (nCode > RANGE_INT12)
220 39394 : nCode |= INV_INT12;
221 71274 : *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
222 70578 : : AddInt32(iPrev, nCode);
223 :
224 71274 : if (nCount == 0)
225 : {
226 7998 : if (nSizeIn)
227 : {
228 7998 : pabyTempIn++;
229 7998 : nSizeIn--;
230 : }
231 7998 : break;
232 : }
233 63276 : nCount--;
234 :
235 63276 : nCode = (CPL_LSBSINT16PTR(pabyTempIn) >> 4) & 0x0FFF;
236 63276 : pabyTempIn += 2;
237 63276 : if (nCode > RANGE_INT12)
238 35672 : nCode |= INV_INT12;
239 125870 : *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
240 62594 : : AddInt32(iPrev, nCode);
241 : }
242 15482 : break;
243 :
244 17958 : case TYPE_INT16:
245 17958 : if (nSizeIn < 2 * nCount)
246 0 : break;
247 17958 : if (nSizeOut < nCount)
248 0 : break;
249 17958 : nSizeIn -= 2 * nCount;
250 17958 : nSizeOut -= nCount;
251 :
252 263522 : while (nCount > 0)
253 : {
254 245564 : nCount--;
255 245564 : const GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn);
256 245564 : pabyTempIn += 2;
257 485978 : *paiOut++ = (nCode == OUT_INT16) ? OUT_INT32
258 240414 : : AddInt32(iPrev, nCode);
259 : }
260 17958 : break;
261 :
262 676 : case TYPE_INT24:
263 676 : if (nSizeIn < 3 * nCount)
264 0 : break;
265 676 : if (nSizeOut < nCount)
266 0 : break;
267 676 : nSizeIn -= 3 * nCount;
268 676 : nSizeOut -= nCount;
269 :
270 70290 : while (nCount > 0)
271 : {
272 69614 : nCount--;
273 69614 : GInt32 nCode =
274 69614 : (*reinterpret_cast<const GByte *>(pabyTempIn)) |
275 69614 : ((*reinterpret_cast<const GByte *>(pabyTempIn + 1))
276 69614 : << 8) |
277 69614 : ((*reinterpret_cast<const GByte *>(pabyTempIn + 2))
278 69614 : << 16);
279 69614 : pabyTempIn += 3;
280 69614 : if (nCode > RANGE_INT24)
281 31998 : nCode |= INV_INT24;
282 137972 : *paiOut++ = (nCode == OUT_INT24) ? OUT_INT32
283 68358 : : AddInt32(iPrev, nCode);
284 : }
285 676 : break;
286 :
287 172 : case TYPE_INT32:
288 172 : if (nSizeIn < 4 * nCount)
289 0 : break;
290 172 : if (nSizeOut < nCount)
291 0 : break;
292 172 : nSizeIn -= 4 * nCount;
293 172 : nSizeOut -= nCount;
294 :
295 49232 : while (nCount > 0)
296 : {
297 49060 : nCount--;
298 49060 : GInt32 nCode = CPL_LSBSINT32PTR(pabyTempIn);
299 49060 : pabyTempIn += 4;
300 98120 : *paiOut++ = (nCode == OUT_INT32) ? OUT_INT32
301 49060 : : AddInt32(iPrev, nCode);
302 : }
303 172 : break;
304 : }
305 : }
306 :
307 18 : return reinterpret_cast<GByte *>(paiOut) - pabyOut;
308 : }
309 :
310 : /************************************************************************/
311 : /* DEMWriteCode() */
312 : /************************************************************************/
313 :
314 1212 : static CPLErr DEMWriteRecord(const DEMDiffT *paiRecord, RmfTypes eRecordType,
315 : GUInt32 nRecordSize, GInt32 nSizeOut,
316 : GByte *&pabyCurrent)
317 : {
318 1212 : const GUInt32 nMaxCountInHeader = 31;
319 : GInt32 iCode;
320 : GInt32 iPrevCode;
321 :
322 1212 : if (nRecordSize <= nMaxCountInHeader)
323 : {
324 481 : nSizeOut -= 1;
325 481 : if (nSizeOut <= 0)
326 : {
327 0 : return CE_Failure;
328 : }
329 :
330 481 : *pabyCurrent++ = static_cast<GByte>(eRecordType | nRecordSize);
331 : }
332 : else
333 : {
334 731 : nSizeOut -= 2;
335 731 : if (nSizeOut <= 0)
336 : {
337 0 : return CE_Failure;
338 : }
339 :
340 731 : *pabyCurrent++ = static_cast<GByte>(eRecordType);
341 731 : *pabyCurrent++ = static_cast<GByte>(nRecordSize - 32);
342 : }
343 :
344 1212 : switch (eRecordType)
345 : {
346 46 : case TYPE_INT4:
347 46 : nSizeOut -= ((nRecordSize + 1) / 2);
348 46 : if (nSizeOut <= 0)
349 : {
350 0 : return CE_Failure;
351 : }
352 :
353 84 : for (GUInt32 n = 0; n != nRecordSize; ++n)
354 : {
355 68 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
356 : {
357 0 : iCode = OUT_INT4;
358 : }
359 : else
360 : {
361 68 : iCode = static_cast<GInt32>(paiRecord[n]);
362 : }
363 68 : *pabyCurrent = static_cast<GByte>(iCode & 0x0F);
364 :
365 68 : ++n;
366 68 : if (n == nRecordSize)
367 : {
368 30 : pabyCurrent++;
369 30 : break;
370 : }
371 :
372 38 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
373 : {
374 0 : iCode = OUT_INT4;
375 : }
376 : else
377 : {
378 38 : iCode = static_cast<GInt32>(paiRecord[n]);
379 : }
380 38 : *pabyCurrent++ |= static_cast<GByte>((iCode & 0x0F) << 4);
381 : }
382 46 : break;
383 :
384 100 : case TYPE_INT8:
385 100 : nSizeOut -= nRecordSize;
386 100 : if (nSizeOut <= 0)
387 : {
388 0 : return CE_Failure;
389 : }
390 :
391 8708 : for (GUInt32 n = 0; n != nRecordSize; ++n)
392 : {
393 8608 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
394 : {
395 9 : *pabyCurrent++ = static_cast<GByte>(OUT_INT8);
396 : }
397 : else
398 : {
399 8599 : *pabyCurrent++ = static_cast<GByte>(paiRecord[n]);
400 : }
401 : }
402 100 : break;
403 :
404 278 : case TYPE_INT12:
405 278 : nSizeOut -= ((nRecordSize * 3 + 1) / 2);
406 278 : if (nSizeOut <= 0)
407 : {
408 0 : return CE_Failure;
409 : }
410 :
411 6851 : for (GUInt32 n = 0; n != nRecordSize; ++n)
412 : {
413 6744 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
414 : {
415 348 : iCode = OUT_INT12;
416 : }
417 : else
418 : {
419 6396 : iCode = static_cast<GInt32>(paiRecord[n]);
420 : }
421 :
422 6744 : iPrevCode = iCode;
423 6744 : *pabyCurrent++ = static_cast<GByte>(iCode & 0x00FF);
424 :
425 6744 : ++n;
426 6744 : if (n == nRecordSize)
427 : {
428 171 : *pabyCurrent++ =
429 171 : static_cast<GByte>((iPrevCode & 0x0F00) >> 8);
430 171 : break;
431 : }
432 :
433 6573 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
434 : {
435 341 : iCode = OUT_INT12;
436 : }
437 : else
438 : {
439 6232 : iCode = static_cast<GInt32>(paiRecord[n]);
440 : }
441 6573 : iCode = (((iPrevCode & 0x0F00) >> 8) | ((iCode & 0x0FFF) << 4));
442 :
443 6573 : CPL_LSBPTR32(&iCode);
444 6573 : memcpy(pabyCurrent, &iCode, 2);
445 6573 : pabyCurrent += 2;
446 : }
447 278 : break;
448 :
449 395 : case TYPE_INT16:
450 395 : nSizeOut -= (nRecordSize * 2);
451 395 : if (nSizeOut <= 0)
452 : {
453 0 : return CE_Failure;
454 : }
455 :
456 103286 : for (GUInt32 n = 0; n != nRecordSize; ++n)
457 : {
458 102891 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
459 : {
460 2575 : iCode = OUT_INT16;
461 : }
462 : else
463 : {
464 100316 : iCode = static_cast<GInt32>(paiRecord[n]);
465 : }
466 102891 : CPL_LSBPTR32(&iCode);
467 102891 : memcpy(pabyCurrent, &iCode, 2);
468 102891 : pabyCurrent += 2;
469 : }
470 395 : break;
471 :
472 137 : case TYPE_INT24:
473 137 : nSizeOut -= (nRecordSize * 3);
474 137 : if (nSizeOut <= 0)
475 : {
476 0 : return CE_Failure;
477 : }
478 :
479 34743 : for (GUInt32 n = 0; n != nRecordSize; ++n)
480 : {
481 34606 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
482 : {
483 628 : iCode = OUT_INT24;
484 : }
485 : else
486 : {
487 33978 : iCode = static_cast<GInt32>(paiRecord[n]);
488 : }
489 34606 : CPL_LSBPTR32(&iCode);
490 34606 : memcpy(pabyCurrent, &iCode, 3);
491 34606 : pabyCurrent += 3;
492 : }
493 137 : break;
494 :
495 86 : case TYPE_INT32:
496 86 : nSizeOut -= (nRecordSize * 4);
497 86 : if (nSizeOut <= 0)
498 : {
499 0 : return CE_Failure;
500 : }
501 :
502 24616 : for (GUInt32 n = 0; n != nRecordSize; ++n)
503 : {
504 24530 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
505 : {
506 0 : iCode = OUT_INT32;
507 : }
508 : else
509 : {
510 24530 : iCode = static_cast<GInt32>(paiRecord[n]);
511 : }
512 24530 : CPL_LSBPTR32(&iCode);
513 24530 : memcpy(pabyCurrent, &iCode, 4);
514 24530 : pabyCurrent += 4;
515 : }
516 86 : break;
517 :
518 170 : case TYPE_ZERO:
519 : case TYPE_OUT:
520 170 : break;
521 :
522 0 : default:
523 0 : return CE_Failure;
524 : }
525 :
526 1212 : return CE_None;
527 : }
528 :
529 : /************************************************************************/
530 : /* DEMDeltaType() */
531 : /************************************************************************/
532 :
533 189311 : static RmfTypes DEMDeltaType(DEMDiffT delta)
534 : {
535 189311 : if (delta <= RANGE_INT12)
536 : {
537 141083 : if (delta <= RANGE_INT4)
538 : {
539 61786 : if (delta == 0)
540 : {
541 49823 : return TYPE_ZERO;
542 : }
543 : else
544 : {
545 11963 : return TYPE_INT4;
546 : }
547 : }
548 : else
549 : {
550 79297 : if (delta <= RANGE_INT8)
551 : {
552 23225 : return TYPE_INT8;
553 : }
554 : else
555 : {
556 56072 : return TYPE_INT12;
557 : }
558 : }
559 : }
560 : else
561 : {
562 48228 : if (delta <= RANGE_INT24)
563 : {
564 33338 : if (delta <= RANGE_INT16)
565 : {
566 24341 : return TYPE_INT16;
567 : }
568 : else
569 : {
570 8997 : return TYPE_INT24;
571 : }
572 : }
573 : else
574 : {
575 14890 : return TYPE_INT32;
576 : }
577 : }
578 : }
579 :
580 : /************************************************************************/
581 : /* DEMCompress() */
582 : /************************************************************************/
583 :
584 5 : size_t RMFDataset::DEMCompress(const GByte *pabyIn, GUInt32 nSizeIn,
585 : GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
586 : GUInt32, const RMFDataset *poDS)
587 : {
588 5 : if (pabyIn == nullptr || pabyOut == nullptr || nSizeIn < sizeof(DEMWorkT))
589 0 : return 0;
590 :
591 5 : const GUInt32 anDeltaTypeSize[8] = {0, 0, 4, 8, 12, 16, 24, 32};
592 5 : const GUInt32 nMaxRecordSize = 255 + 32;
593 :
594 5 : DEMWorkT iMin(std::numeric_limits<DEMWorkT>::min() + 1);
595 5 : if (poDS != nullptr &&
596 5 : poDS->sHeader.adfElevMinMax[0] < poDS->sHeader.adfElevMinMax[1])
597 : {
598 0 : iMin = static_cast<DEMWorkT>(poDS->sHeader.adfElevMinMax[0]);
599 : }
600 5 : GUInt32 nLessCount = 0;
601 5 : GUInt32 nRecordSize = 0;
602 5 : RmfTypes eRecordType = TYPE_OUT;
603 5 : DEMDiffT aiRecord[nMaxRecordSize] = {0};
604 5 : DEMWorkT aiPrev[nMaxRecordSize] = {0};
605 :
606 5 : GByte *pabyCurrent = pabyOut;
607 5 : DEMWorkT iPrev = 0;
608 :
609 5 : nSizeIn = nSizeIn / sizeof(DEMWorkT);
610 :
611 5 : const DEMWorkT *paiIn = reinterpret_cast<const DEMWorkT *>(pabyIn);
612 5 : const DEMWorkT *paiInEnd = paiIn + nSizeIn;
613 :
614 : while (true)
615 : {
616 197413 : GUInt32 nRecordElementSize = 0;
617 :
618 197413 : if (paiIn >= paiInEnd)
619 : {
620 10 : if (nRecordSize == 0)
621 : {
622 5 : return pabyCurrent - pabyOut;
623 : }
624 :
625 5 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
626 : nSizeOut, pabyCurrent))
627 : {
628 0 : return 0;
629 : }
630 5 : nRecordSize = 0;
631 5 : continue;
632 : }
633 :
634 197403 : DEMWorkT iCurr = *(paiIn++);
635 : RmfTypes eCurrType;
636 :
637 197403 : if (iCurr < iMin)
638 : {
639 8092 : eCurrType = TYPE_OUT;
640 8092 : aiRecord[nRecordSize] = DIFF_OUI_OF_RANGE;
641 8092 : aiPrev[nRecordSize] = iPrev;
642 : }
643 : else
644 : {
645 189311 : DEMDiffT delta =
646 189311 : static_cast<DEMDiffT>(iCurr) - static_cast<DEMDiffT>(iPrev);
647 :
648 189311 : aiRecord[nRecordSize] = delta;
649 189311 : aiPrev[nRecordSize] = iCurr;
650 :
651 189311 : if (delta < 0)
652 79880 : delta = -delta;
653 :
654 189311 : eCurrType = DEMDeltaType(delta);
655 189311 : iPrev = iCurr;
656 : }
657 197403 : nRecordSize++;
658 :
659 197403 : if (nRecordSize == 1)
660 : {
661 1212 : eRecordType = eCurrType;
662 : // nRecordElementSize = anDeltaTypeSize[eCurrType >> 5];
663 1212 : continue;
664 : }
665 :
666 196191 : if (nRecordSize == nMaxRecordSize)
667 : {
668 602 : nLessCount = 0;
669 602 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
670 : nSizeOut, pabyCurrent))
671 : {
672 0 : return 0;
673 : }
674 602 : iPrev = aiPrev[nRecordSize - 1];
675 602 : nRecordSize = 0;
676 602 : continue;
677 : }
678 :
679 195589 : if (eCurrType == eRecordType)
680 : {
681 59166 : nLessCount = 0;
682 59166 : continue;
683 : }
684 :
685 136423 : if ((eCurrType > eRecordType) || (eCurrType | eRecordType) == TYPE_ZERO)
686 : {
687 605 : --paiIn;
688 605 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
689 : nRecordSize - 1, nSizeOut,
690 : pabyCurrent))
691 : {
692 0 : return 0;
693 : }
694 605 : iPrev = aiPrev[nRecordSize - 2];
695 605 : nRecordSize = 0;
696 605 : nLessCount = 0;
697 605 : continue;
698 : }
699 :
700 135818 : nLessCount++;
701 :
702 135818 : GUInt32 nDeltaSize(anDeltaTypeSize[eCurrType >> 5]);
703 135818 : if (nRecordElementSize < nDeltaSize ||
704 45035 : (nRecordElementSize - nDeltaSize) * nLessCount < 16)
705 : {
706 135818 : continue;
707 : }
708 :
709 0 : paiIn -= nLessCount;
710 0 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
711 : nRecordSize - nLessCount, nSizeOut,
712 : pabyCurrent))
713 : {
714 0 : return 0;
715 : }
716 0 : iPrev = aiPrev[nRecordSize - nLessCount - 1];
717 0 : nRecordSize = 0;
718 0 : nLessCount = 0;
719 197408 : }
720 :
721 : return 0;
722 : }
|