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