Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/spdiff.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Pixel differencing filters */
18
#include "stdio_.h"   /* should be std.h, but needs NULL */
19
#include "memory_.h"
20
#include "strimpl.h"
21
#include "spdiffx.h"
22
#include "gserrors.h"
23
24
/* ------ PixelDifferenceEncode/Decode ------ */
25
26
private_st_PDiff_state();
27
28
/* Define values for case dispatch. */
29
15
#define cBits1 0
30
15
#define cBits2 5
31
15
#define cBits4 10
32
15.2k
#define cBits8 15
33
15
#define cBits16 20
34
30
#define cEncode 0
35
15.2k
#define cDecode 25
36
37
/* Set defaults */
38
static void
39
s_PDiff_set_defaults(stream_state * st)
40
15
{
41
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
42
43
15
    s_PDiff_set_defaults_inline(ss);
44
15
}
45
46
/* Common (re)initialization. */
47
static int
48
s_PDiff_reinit(stream_state * st)
49
15
{
50
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
51
52
15
    ss->row_left = 0;
53
15
    return 0;
54
15
}
55
56
/* Initialize PixelDifferenceEncode filter. */
57
static int
58
s_PDiffE_init(stream_state * st)
59
15
{
60
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
61
15
    int bits_per_row =
62
15
        ss->Colors * ss->BitsPerComponent * ss->Columns;
63
15
    static const byte cb_values[] = {
64
15
        0, cBits1, cBits2, 0, cBits4, 0, 0, 0, cBits8,
65
15
        0, 0, 0, 0, 0, 0, 0, cBits16
66
15
    };
67
68
15
    if (ss->Colors > s_PDiff_max_Colors)
69
0
        return_error(gs_error_rangecheck);
70
71
15
    if (ss->BitsPerComponent > s_PDiff_max_BPC)
72
0
        return_error(gs_error_rangecheck);
73
74
15
    ss->row_count = (bits_per_row + 7) >> 3;
75
15
    ss->end_mask = (1 << (-bits_per_row & 7)) - 1;
76
15
    ss->case_index =
77
15
        cb_values[ss->BitsPerComponent] +
78
15
        (ss->Colors > 4 ? 0 : ss->Colors) + cEncode;
79
15
    return s_PDiff_reinit(st);
80
15
}
81
82
/* Initialize PixelDifferenceDecode filter. */
83
static int
84
s_PDiffD_init(stream_state * st)
85
15
{
86
15
    int code = 0;
87
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
88
89
15
    code = s_PDiffE_init(st);
90
15
    ss->case_index += cDecode - cEncode;
91
15
    return code;
92
15
}
93
94
/* Process a buffer.  Note that this handles both Encode and Decode. */
95
static int
96
s_PDiff_process(stream_state * st, stream_cursor_read * pr,
97
                stream_cursor_write * pw, bool last)
98
51
{
99
51
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
100
51
    const byte *p = pr->ptr;
101
51
    byte *q = pw->ptr;
102
51
    int count;
103
51
    int status = 0;
104
51
    uint s0 = ss->prev[0];
105
51
    byte t = 0;     /* avoid spurious compiler warnings */
106
51
    int  ti;
107
51
    const byte end_mask = ss->end_mask;
108
51
    int colors = ss->Colors;
109
51
    int nb = (colors * ss->BitsPerComponent) >> 3;
110
51
    int final;
111
51
    int ndone, ci;
112
113
15.2k
row:
114
15.2k
    if (ss->row_left == 0) {
115
15.2k
        ss->row_left = ss->row_count;
116
15.2k
        s0 = 0;
117
15.2k
        memset(&ss->prev[1], 0, sizeof(uint) * (s_PDiff_max_Colors - 1));
118
15.2k
    }
119
15.2k
    {
120
15.2k
        int rcount = pr->limit - p;
121
15.2k
        int wcount = pw->limit - q;
122
123
15.2k
        if (ss->row_left < rcount)
124
15.2k
            rcount = ss->row_left;
125
15.2k
        count = (wcount < rcount ? (status = 1, wcount) : rcount);
126
15.2k
    }
127
15.2k
    final = (last && !status ? 1 : nb);
128
15.2k
    ss->row_left -= count;
129
130
    /*
131
     * Encoding and decoding are fundamentally different.
132
     * Encoding computes E[i] = D[i] - D[i-1];
133
     * decoding computes D[i] = E[i] + D[i-1].
134
     * Nevertheless, the loop structures are similar enough that
135
     * we put the code for both functions in the same place.
136
     *
137
     * We only optimize Colors = 1, 3, and 4, which correspond to the common
138
     * color spaces.  (In some cases, it's still simpler to provide a
139
     * separate loop for Colors = 2.)
140
     */
141
142
15.2k
#define LOOP_BY(n, body)\
143
31.4k
  for (; count >= n; count -= n) p += n, q += n, body
144
145
15.2k
    switch (ss->case_index) {
146
147
            /* 1 bit per component */
148
149
0
#define ENCODE1_LOOP(ee)\
150
0
  LOOP_BY(1, (t = *p, *q = ee, s0 = t)); break
151
152
0
#define ENCODE_ALIGNED_LOOP(ee)\
153
0
  BEGIN\
154
0
    ss->prev[0] = s0;\
155
0
    for (; count >= final; count -= ndone) {\
156
0
        ndone = min(count, nb);\
157
0
        for (ci = 0; ci < ndone; ++ci)\
158
0
            t = *++p, *++q = ee, ss->prev[ci] = t;\
159
0
    }\
160
0
    s0 = ss->prev[0];\
161
0
  END
162
163
0
#define ENCODE_UNALIGNED_LOOP(shift, cshift, de)\
164
0
  BEGIN\
165
0
    for (; count >= final; count -= ndone) {\
166
0
        ndone = min(count, nb);\
167
0
        for (ci = 1; ci <= ndone; ++ci) {\
168
0
            ++p;\
169
0
            t = (s0 << (cshift)) | (ss->prev[ci] >> (shift));\
170
0
            *++q = de;\
171
0
            s0 = ss->prev[ci];\
172
0
            ss->prev[ci] = *p;\
173
0
        }\
174
0
    }\
175
0
  END
176
177
0
        case cEncode + cBits1 + 0:
178
0
        case cEncode + cBits1 + 2:
179
0
            if (colors < 8) { /* 2,5,6,7 */
180
0
                int cshift = 8 - colors;
181
182
0
                ENCODE1_LOOP(t ^ ((s0 << cshift) | (t >> colors)));
183
0
            } else if (colors & 7) {
184
0
                int shift = colors & 7;
185
0
                int cshift = 8 - shift;
186
187
0
                ENCODE_UNALIGNED_LOOP(shift, cshift, *p ^ t);
188
0
            } else {
189
0
                ENCODE_ALIGNED_LOOP(t ^ ss->prev[ci]);
190
0
            }
191
0
            break;
192
193
0
        case cEncode + cBits1 + 1:
194
0
            ENCODE1_LOOP(t ^ ((s0 << 7) | (t >> 1)));
195
0
        case cEncode + cBits1 + 3:
196
0
            ENCODE1_LOOP(t ^ ((s0 << 5) | (t >> 3)));
197
0
        case cEncode + cBits1 + 4:
198
0
            ENCODE1_LOOP(t ^ ((s0 << 4) | (t >> 4)));
199
200
0
#define DECODE1_LOOP(te, de)\
201
0
  LOOP_BY(1, (t = te, s0 = *q = de)); break
202
203
0
#define DECODE_ALIGNED_LOOP(de)\
204
0
  BEGIN\
205
0
    ss->prev[0] = s0;\
206
0
    for (; count >= final; count -= ndone) {\
207
0
        ndone = min(count, nb);\
208
0
        for (ci = 0; ci < ndone; ++ci)\
209
0
            t = *++p, ss->prev[ci] = *++q = de;\
210
0
    }\
211
0
    s0 = ss->prev[0];\
212
0
  END
213
214
0
#define DECODE_UNALIGNED_LOOP(shift, cshift, de)\
215
0
  BEGIN\
216
0
    for (; count >= final; count -= ndone) {\
217
0
        ndone = min(count, nb);\
218
0
        for (ci = 1; ci <= ndone; ++ci) {\
219
0
            ++p, ++q;\
220
0
            t = (s0 << (cshift)) | (ss->prev[ci] >> (shift));\
221
0
            s0 = ss->prev[ci];\
222
0
            ss->prev[ci] = *q = de;\
223
0
        }\
224
0
    }\
225
0
  END
226
227
0
        case cDecode + cBits1 + 0:
228
0
            if (colors < 8) { /* 5,6,7 */
229
0
                int cshift = 8 - colors;
230
231
0
                DECODE1_LOOP(*p ^ (s0 << cshift), t ^ (t >> colors));
232
0
            } else if (colors & 7) {
233
0
                int shift = colors & 7;
234
0
                int cshift = 8 - shift;
235
236
0
                DECODE_UNALIGNED_LOOP(shift, cshift, *p ^ t);
237
0
            } else {
238
0
                DECODE_ALIGNED_LOOP(t ^ ss->prev[ci]);
239
0
            }
240
0
            break;
241
242
0
        case cDecode + cBits1 + 1:
243
0
            DECODE1_LOOP(*p ^ (s0 << 7),
244
0
                         (t ^= t >> 1, t ^= t >> 2, t ^ (t >> 4)));
245
0
        case cDecode + cBits1 + 2:
246
0
            DECODE1_LOOP(*p ^ (s0 << 6),
247
0
                         (t ^= (t >> 2), t ^ (t >> 4)));
248
0
        case cDecode + cBits1 + 3:
249
0
            DECODE1_LOOP(*p ^ (s0 << 5),
250
0
                         t ^ (t >> 3) ^ (t >> 6));
251
0
        case cDecode + cBits1 + 4:
252
0
            DECODE1_LOOP(*p ^ (s0 << 4),
253
0
                         t ^ (t >> 4));
254
255
            /* 2 bits per component */
256
257
0
#define ADD4X2(a, b) ( (((a) & (b) & 0x55) << 1) ^ (a) ^ (b) )
258
/* The following computation looks very implausible, but it is correct. */
259
0
#define SUB4X2(a, b) ( ((~(a) & (b) & 0x55) << 1) ^ (a) ^ (b) )
260
261
0
        case cEncode + cBits2 + 0:
262
0
            if (colors & 7) {
263
0
                int shift = (colors & 3) << 1;
264
0
                int cshift = 8 - shift;
265
266
0
                ENCODE_UNALIGNED_LOOP(shift, cshift, SUB4X2(*p, t));
267
0
            } else {
268
0
                ENCODE_ALIGNED_LOOP(SUB4X2(t, ss->prev[ci]));
269
0
            }
270
0
            break;
271
272
0
        case cEncode + cBits2 + 1:
273
0
            ENCODE1_LOOP((s0 = (s0 << 6) | (t >> 2), SUB4X2(t, s0)));
274
0
        case cEncode + cBits2 + 2:
275
0
            ENCODE1_LOOP((s0 = (s0 << 4) | (t >> 4), SUB4X2(t, s0)));
276
0
        case cEncode + cBits2 + 3:
277
0
            ENCODE1_LOOP((s0 = (s0 << 2) | (t >> 6), SUB4X2(t, s0)));
278
0
        case cEncode + cBits2 + 4:
279
0
            ENCODE1_LOOP(SUB4X2(t, s0));
280
281
0
        case cDecode + cBits2 + 0:
282
0
            if (colors & 7) {
283
0
                int shift = (colors & 3) << 1;
284
0
                int cshift = 8 - shift;
285
286
0
                DECODE_UNALIGNED_LOOP(shift, cshift, ADD4X2(*p, t));
287
0
            } else {
288
0
                DECODE_ALIGNED_LOOP(ADD4X2(t, ss->prev[ci]));
289
0
            }
290
0
            break;
291
292
0
        case cDecode + cBits2 + 1:
293
0
            DECODE1_LOOP(*p + (s0 << 6),
294
0
                         (t = ADD4X2(t >> 2, t), ADD4X2(t >> 4, t)));
295
0
        case cDecode + cBits2 + 2:
296
0
            DECODE1_LOOP(*p, (t = ADD4X2(t, s0 << 4), ADD4X2(t >> 4, t)));
297
0
        case cDecode + cBits2 + 3:
298
0
            DECODE1_LOOP(*p, (t = ADD4X2(t, s0 << 2), ADD4X2(t >> 6, t)));
299
0
        case cDecode + cBits2 + 4:
300
0
            DECODE1_LOOP(*p, ADD4X2(t, s0));
301
302
0
#undef ADD4X2
303
0
#undef SUB4X2
304
305
            /* 4 bits per component */
306
307
0
#define ADD2X4(a, b) ( (((a) + (b)) & 0xf) + ((a) & 0xf0) + ((b) & 0xf0) )
308
0
#define ADD2X4R4(a) ( (((a) + ((a) >> 4)) & 0xf) + ((a) & 0xf0) )
309
0
#define SUB2X4(a, b) ( (((a) - (b)) & 0xf) + ((a) & 0xf0) - ((b) & 0xf0) )
310
0
#define SUB2X4R4(a) ( (((a) - ((a) >> 4)) & 0xf) + ((a) & 0xf0) )
311
312
0
        case cEncode + cBits4 + 0:
313
0
        case cEncode + cBits4 + 2:
314
0
    enc4:
315
0
            if (colors & 1) {
316
0
                ENCODE_UNALIGNED_LOOP(4, 4, SUB2X4(*p, t));
317
0
            } else {
318
0
                ENCODE_ALIGNED_LOOP(SUB2X4(t, ss->prev[ci]));
319
0
            }
320
0
            break;
321
322
0
        case cEncode + cBits4 + 1:
323
0
            ENCODE1_LOOP(((t - (s0 << 4)) & 0xf0) | ((t - (t >> 4)) & 0xf));
324
325
0
        case cEncode + cBits4 + 3: {
326
0
            uint s1 = ss->prev[1];
327
328
0
            LOOP_BY(1,
329
0
                    (t = *p,
330
0
                     *q = ((t - (s0 << 4)) & 0xf0) | ((t - (s1 >> 4)) & 0xf),
331
0
                     s0 = s1, s1 = t));
332
0
            ss->prev[1] = s1;
333
0
        } break;
334
335
0
        case cEncode + cBits4 + 4: {
336
0
            uint s1 = ss->prev[1];
337
338
0
            LOOP_BY(2,
339
0
                    (t = p[-1], q[-1] = SUB2X4(t, s0), s0 = t,
340
0
                     t = *p, *q = SUB2X4(t, s1), s1 = t));
341
0
            ss->prev[1] = s1;
342
0
            goto enc4;    /* handle leftover bytes */
343
0
        }
344
345
0
        case cDecode + cBits4 + 0:
346
0
        case cDecode + cBits4 + 2:
347
0
    dec4:
348
0
            if (colors & 1) {
349
0
                DECODE_UNALIGNED_LOOP(4, 4, ADD2X4(*p, t));
350
0
            } else {
351
0
                DECODE_ALIGNED_LOOP(ADD2X4(t, ss->prev[ci]));
352
0
            }
353
0
            break;
354
355
0
        case cDecode + cBits4 + 1:
356
0
            DECODE1_LOOP(*p + (s0 << 4), ADD2X4R4(t));
357
358
0
        case cDecode + cBits4 + 3: {
359
0
            uint s1 = ss->prev[1];
360
361
0
            LOOP_BY(1, (t = (s0 << 4) + (s1 >> 4),
362
0
                        s0 = s1, s1 = *q = ADD2X4(*p, t)));
363
0
            ss->prev[1] = s1;
364
0
        } break;
365
366
0
        case cDecode + cBits4 + 4: {
367
0
            uint s1 = ss->prev[1];
368
369
0
            LOOP_BY(2,
370
0
                    (t = p[-1], s0 = q[-1] = ADD2X4(s0, t),
371
0
                     t = *p, s1 = *q = ADD2X4(s1, t)));
372
0
            ss->prev[1] = s1;
373
0
            goto dec4;    /* handle leftover bytes */
374
0
        }
375
376
0
#undef ADD2X4
377
0
#undef ADD2X4R4
378
0
#undef SUB2X4
379
0
#undef SUB2X4R4
380
381
            /* 8 bits per component */
382
383
0
#define ENCODE8(s, d) (q[d] = p[d] - s, s = p[d])
384
0
#define DECODE8(s, d) q[d] = s += p[d]
385
386
0
        case cEncode + cBits8 + 0:
387
0
        case cEncode + cBits8 + 2:
388
0
            ss->prev[0] = s0;
389
0
            for (; count >= colors; count -= colors)
390
0
                for (ci = 0; ci < colors; ++ci) {
391
0
                    *++q = *++p - ss->prev[ci];
392
0
                    ss->prev[ci] = *p;
393
0
                }
394
0
            s0 = ss->prev[0];
395
0
    enc8:   /* Handle leftover bytes. */
396
0
            if (last && !status)
397
0
                for (ci = 0; ci < count; ++ci)
398
0
                    *++q = *++p - ss->prev[ci],
399
0
                        ss->prev[ci] = *p;
400
0
            break;
401
402
0
        case cDecode + cBits8 + 0:
403
0
        case cDecode + cBits8 + 2:
404
0
            ss->prev[0] = s0;
405
0
            for (; count >= colors; count -= colors)
406
0
                for (ci = 0; ci < colors; ++ci)
407
0
                    *++q = ss->prev[ci] += *++p;
408
0
            s0 = ss->prev[0];
409
0
    dec8:   /* Handle leftover bytes. */
410
0
            if (last && !status)
411
0
                for (ci = 0; ci < count; ++ci)
412
0
                    *++q = ss->prev[ci] += *++p;
413
0
            break;
414
415
0
        case cEncode + cBits8 + 1:
416
0
            LOOP_BY(1, ENCODE8(s0, 0));
417
0
            break;
418
419
15.2k
        case cDecode + cBits8 + 1:
420
15.2k
            LOOP_BY(1, DECODE8(s0, 0));
421
15.2k
            break;
422
423
0
        case cEncode + cBits8 + 3: {
424
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
425
426
0
            LOOP_BY(3, (ENCODE8(s0, -2), ENCODE8(s1, -1),
427
0
                        ENCODE8(s2, 0)));
428
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
429
0
            goto enc8;
430
0
        }
431
432
0
        case cDecode + cBits8 + 3: {
433
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
434
435
0
            LOOP_BY(3, (DECODE8(s0, -2), DECODE8(s1, -1),
436
0
                        DECODE8(s2, 0)));
437
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
438
0
            goto dec8;
439
0
        } break;
440
441
0
        case cEncode + cBits8 + 4: {
442
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
443
444
0
            LOOP_BY(4, (ENCODE8(s0, -3), ENCODE8(s1, -2),
445
0
                        ENCODE8(s2, -1), ENCODE8(s3, 0)));
446
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
447
0
            goto enc8;
448
0
        } break;
449
450
0
        case cDecode + cBits8 + 4: {
451
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
452
453
0
            LOOP_BY(4, (DECODE8(s0, -3), DECODE8(s1, -2),
454
0
                        DECODE8(s2, -1), DECODE8(s3, 0)));
455
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
456
0
            goto dec8;
457
0
        } break;
458
459
0
#undef ENCODE8
460
0
#undef DECODE8
461
462
            /* 16 bits per component */
463
464
0
#define ENCODE16(s, d) (ti = ((p[d-1] << 8) + p[d]), s = ti - s,\
465
0
            q[d-1] = s >> 8, q[d] = s & 0xff, s = ti)
466
0
#define DECODE16(s, d) (s = 0xffff & (s + ((p[d-1] << 8) + p[d])), \
467
0
            q[d-1] = s >> 8, q[d] = s & 0xff)
468
469
0
        case cEncode + cBits16 + 0:
470
0
        case cEncode + cBits16 + 2:
471
0
            ss->prev[0] = s0;
472
0
            for (; count >= colors*2; count -= colors*2)
473
0
                for (ci = 0; ci < colors; ++ci) {
474
0
                    uint k;
475
0
                    ti =  (int)*++p << 8;
476
0
                    ti += (int)*++p;
477
0
                    k = ti - ss->prev[ci];
478
0
                    *++q = k >> 8;
479
0
                    *++q = k & 0xff;
480
0
                    ss->prev[ci] = ti;
481
0
                }
482
0
            s0 = ss->prev[0];
483
0
    enc16:   /* Handle leftover bytes. */
484
0
            if (last && !status)
485
0
                for (ci = 0; ci < count; ++ci)
486
0
                    *++q = *++p - ss->prev[ci],
487
0
                        ss->prev[ci] = *p;
488
0
            break;
489
490
0
        case cDecode + cBits16 + 0:
491
0
        case cDecode + cBits16 + 2:
492
0
            ss->prev[0] = s0;
493
0
            for (; count >= colors*2; count -= colors*2)
494
0
                for (ci = 0; ci < colors; ++ci) {
495
0
                    ti = (int)*++p << 8;
496
0
                    ss->prev[ci] += ti + *++p;
497
0
                    *++q = ss->prev[ci] >> 8;
498
0
                    *++q = ss->prev[ci] & 0xff;
499
0
                }
500
0
            s0 = ss->prev[0];
501
0
    dec16:   /* Ignore leftover bytes. */
502
0
            break;
503
504
0
        case cEncode + cBits16 + 1:
505
0
           LOOP_BY(2, ENCODE16(s0, 0));
506
0
           break;
507
508
0
        case cDecode + cBits16 + 1:
509
0
           LOOP_BY(2, DECODE16(s0, 0));
510
0
           break;
511
512
0
        case cEncode + cBits16 + 3: {
513
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
514
515
0
            LOOP_BY(6, (ENCODE16(s0, -4), ENCODE16(s1, -2),
516
0
                        ENCODE16(s2, 0)));
517
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
518
0
            goto enc16;
519
0
        }
520
521
0
        case cDecode + cBits16 + 3: {
522
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
523
524
0
            LOOP_BY(6, (DECODE16(s0, -4), DECODE16(s1, -2),
525
0
                        DECODE16(s2, 0)));
526
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
527
0
            goto dec16;
528
0
        } break;
529
530
0
        case cEncode + cBits16 + 4: {
531
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
532
533
0
            LOOP_BY(8, (ENCODE16(s0, -6), ENCODE16(s1, -4),
534
0
                        ENCODE16(s2, -2), ENCODE16(s3, 0)));
535
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
536
0
            goto enc16;
537
0
        } break;
538
539
0
        case cDecode + cBits16 + 4: {
540
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
541
542
0
            LOOP_BY(8, (DECODE16(s0, -6), DECODE16(s1, -4),
543
0
                        DECODE16(s2, -2), DECODE16(s3, 0)));
544
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
545
0
            goto dec16;
546
0
        } break;
547
548
15.2k
#undef ENCODE16
549
15.2k
#undef DECODE16
550
551
15.2k
    }
552
15.2k
#undef LOOP_BY
553
15.2k
#undef ENCODE1_LOOP
554
15.2k
#undef DECODE1_LOOP
555
15.2k
    ss->row_left += count;  /* leftover bytes are possible */
556
15.2k
    if (ss->row_left == 0) {
557
15.2k
        if (end_mask != 0)
558
0
            *q = (*q & ~end_mask) | (*p & end_mask);
559
15.2k
        if (p < pr->limit && q < pw->limit)
560
15.2k
            goto row;
561
15.2k
    }
562
51
    ss->prev[0] = s0;
563
51
    pr->ptr = p;
564
51
    pw->ptr = q;
565
51
    return status;
566
15.2k
}
567
568
/* Stream templates */
569
const stream_template s_PDiffE_template = {
570
    &st_PDiff_state, s_PDiffE_init, s_PDiff_process, 1, 1, NULL,
571
    s_PDiff_set_defaults, s_PDiff_reinit
572
};
573
const stream_template s_PDiffD_template = {
574
    &st_PDiff_state, s_PDiffD_init, s_PDiff_process, 1, 1, NULL,
575
    s_PDiff_set_defaults, s_PDiff_reinit
576
};