Coverage Report

Created: 2025-06-24 07:01

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