Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/base/srle.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
/* RunLengthEncode filter */
18
#include "stdio_.h"   /* includes std.h */
19
#include "memory_.h"
20
#include "strimpl.h"
21
#include "srlx.h"
22
23
/* ------ RunLengthEncode ------ */
24
25
private_st_RLE_state();
26
27
/* Set defaults */
28
static void
29
s_RLE_set_defaults(stream_state * st)
30
241k
{
31
241k
    stream_RLE_state *const ss = (stream_RLE_state *) st;
32
33
241k
    s_RLE_set_defaults_inline(ss);
34
241k
}
35
36
/* Initialize */
37
static int
38
s_RLE_init(stream_state * st)
39
241k
{
40
241k
    stream_RLE_state *const ss = (stream_RLE_state *) st;
41
42
241k
    return s_RLE_init_inline(ss);
43
241k
}
44
45
enum {
46
    /* Initial state - Nothing read (but may be mid run). */
47
    state_0,
48
49
    /* 0 bytes into a run, n0 read. */
50
    state_eq_0,
51
52
    /* 0 bytes into a run, n0 and n1 read. */
53
    state_eq_01,
54
55
    /* n bytes into a literal run, n0 and n1 read. */
56
    state_gt_01,
57
58
    /* n bytes into a literal run, n0,n1,n2 read. */
59
    state_gt_012,
60
61
    /* -n bytes into a repeated run, n0 and n1 read. */
62
    state_lt_01,
63
64
    /* We have reached the end of data, but not written the marker. */
65
    state_eod_unmarked,
66
67
    /* We have reached the end of data, and written the marker. */
68
    state_eod
69
};
70
71
#ifdef DEBUG_RLE
72
static void
73
debug_ate(const byte *p, const byte *plimit,
74
          const byte *q, const byte *qlimit,
75
          int ret)
76
{
77
    if (p != plimit) {
78
        dlprintf("CONSUMED");
79
        while (p != plimit) {
80
            dlprintf1(" %02x", *++p);
81
        }
82
        dlprintf("\n");
83
    }
84
    if (q != qlimit) {
85
        dlprintf("PRODUCED\n");
86
        while (q != qlimit) {
87
            int n = *++q;
88
            if (n == 128) {
89
                dlprintf1(" EOD(%02x)", n);
90
            } else if (n < 128) {
91
                dlprintf2(" %d(%02x)(", n+1, n);
92
                n++;
93
                while (n-- && q != qlimit) {
94
                    dlprintf1(" %02x", *++q);
95
                }
96
                if (n != -1) {
97
                    dlprintf1(" %d missing!", n+1);
98
                }
99
                dlprintf(" )\n");
100
            } else {
101
                dlprintf2(" %d(%02x) - ", 257-n, n);
102
                if (q == qlimit) {
103
                    dlprintf("WTF!");
104
                }
105
                dlprintf1("%02x\n", *++q);
106
            }
107
        }
108
        dlprintf("\n");
109
    }
110
    dlprintf1("RETURNED %d\n", ret);
111
}
112
#else
113
3.88M
#define debug_ate(a,b,c,d,e) do { } while (0)
114
#endif
115
116
/* Process a buffer */
117
static int
118
s_RLE_process(stream_state * st, stream_cursor_read * pr,
119
              stream_cursor_write * pw, bool last)
120
3.88M
{
121
3.88M
    stream_RLE_state *const ss = (stream_RLE_state *) st;
122
3.88M
    register const byte *p = pr->ptr;
123
3.88M
    register byte *q = pw->ptr;
124
3.88M
    const byte *plimit = pr->limit;
125
3.88M
    byte *wlimit = pw->limit;
126
3.88M
    ulong rleft = ss->record_left;
127
3.88M
    int run_len = ss->run_len, ret = 0;
128
3.88M
    byte n0 = ss->n0;
129
3.88M
    byte n1 = ss->n1;
130
3.88M
    byte n2 = ss->n2;
131
3.88M
    const byte *rlimit = p + rleft;
132
#ifdef DEBUG_RLE
133
    const byte *pinit = p;
134
    const byte *qinit = q;
135
    static int entry = -1;
136
137
    entry++;
138
    dlprintf7("ENTERED(%d): avail_in=%d avail_out=%d run_len=%d n0=%02x n1=%02x n2=%02x\n",
139
              entry, plimit-p, wlimit-q, run_len, n0, n1, n2);
140
#endif
141
142
3.88M
    switch (ss->state) {
143
0
    default:
144
0
        dlprintf("Inconsistent state in s_RLE_process!\n");
145
        /* fall through */
146
2.71M
    case state_0:
147
123M
        while (p != plimit) {
148
121M
            if (run_len == 0) {
149
                /* About to start a new run */
150
812k
                n0 = *++p;
151
1.08M
    case state_eq_0:
152
3.90M
run_len_0_n0_read:
153
3.90M
                if (p == rlimit || (p == plimit && last)) {
154
                    /* flush the record here, and restart */
155
181
                    if (wlimit - q < 2){
156
71
                        ss->state = state_eq_0;
157
                        /* no_output_room_n0_read */
158
71
                        goto no_output_room;
159
71
                    }
160
110
                    *++q = 0; /* Single literal */
161
110
                    *++q = n0;
162
110
                    rlimit = p + ss->record_size;
163
110
                    continue;
164
181
                }
165
3.89M
                if (p == plimit) {
166
267k
                    ss->state = state_eq_0;
167
                    /* no_more_data_n0_read */
168
267k
                    goto no_more_data;
169
267k
                }
170
3.63M
                n1 = *++p;
171
3.63M
    case state_eq_01:
172
3.63M
                if (p == rlimit || (p == plimit && last)) {
173
                    /* flush the record here, and restart */
174
82.2k
                    if (wlimit - q < 3 - (n0 == n1)) {
175
588
                        ss->state = state_eq_01;
176
                        /* no_output_room_n0n1_read */
177
588
                        goto no_output_room;
178
588
                    }
179
81.7k
                    if (n0 == n1) {
180
25
                        *++q = 0xff; /* Repeat 2 */
181
25
                        *++q = n0;
182
81.6k
                    } else {
183
81.6k
                        *++q = 1; /* Two literals */
184
81.6k
                        *++q = n0;
185
81.6k
                        *++q = n1;
186
81.6k
                    }
187
81.7k
                    run_len = 0;
188
81.7k
                    rlimit = p + ss->record_size;
189
81.7k
                    continue;
190
82.2k
                }
191
3.54M
                if (n0 == n1) {
192
                    /* Start of a repeated run */
193
317k
                    run_len = -2;
194
3.23M
                } else {
195
                    /* A literal run of at least 1. */
196
3.23M
                    run_len = 1;
197
3.23M
                    ss->literals[0] = n0;
198
3.23M
                    n0 = n1;
199
3.23M
                }
200
3.54M
                if (p == plimit) {
201
105k
                    ss->state = state_0;
202
105k
                    goto no_more_data;
203
105k
                }
204
120M
            } else if (run_len > 0) {
205
                /* We are in the middle of a run of literals */
206
94.2M
                n1 = *++p;
207
95.1M
    case state_gt_01:
208
95.1M
                if (p == rlimit || run_len == 126 ||
209
95.1M
                    (n0 == n1 && p == plimit && last)) {
210
                    /* flush the record here, and restart */
211
                    /* <len> <queue> n0 n1 */
212
586k
                        if (wlimit - q < run_len+3) {
213
90.7k
                            ss->state = state_gt_01;
214
                            /* no_output_room_gt_n0n1_read */
215
90.7k
                            goto no_output_room;
216
90.7k
                        }
217
496k
                    *++q = run_len+1;
218
496k
                    memcpy(q+1, ss->literals, run_len);
219
496k
                    q += run_len;
220
496k
                    *++q = n0;
221
496k
                    *++q = n1;
222
496k
                    run_len = 0;
223
496k
                    if (p == rlimit)
224
0
                        rlimit = p + ss->record_size;
225
496k
                    continue;
226
586k
                }
227
94.5M
                if (n0 == n1) {
228
5.16M
                    if (p == plimit) {
229
895k
                        ss->state = state_gt_01;
230
                        /* no_more_data_n0n1_read */
231
895k
                        goto no_more_data;
232
895k
                    }
233
4.27M
                    n2 = *++p;
234
4.27M
    case state_gt_012:
235
4.27M
                    if (p == rlimit || run_len == 125) {
236
                        /* flush the record here, and restart */
237
                        /* <len> <queue> n0 n1 n2 */
238
6.79k
                        if (wlimit - q < run_len+4) {
239
1.13k
                            ss->state = state_gt_012;
240
                            /* no_output_room_n0n1n2_read */
241
1.13k
                            goto no_output_room;
242
1.13k
                        }
243
5.65k
                        *++q = run_len+2;
244
5.65k
                        memcpy(q+1, ss->literals, run_len);
245
5.65k
                        q += run_len;
246
5.65k
                        *++q = n0;
247
5.65k
                        *++q = n1;
248
5.65k
                        *++q = n2;
249
5.65k
                        run_len = 0;
250
5.65k
                        if (p == rlimit)
251
0
                            rlimit = p + ss->record_size;
252
5.65k
                        continue;
253
6.79k
                    }
254
4.26M
                    if (n0 != n2) {
255
                        /* Stick with a literal run */
256
1.62M
                        ss->literals[run_len++] = n0;
257
1.62M
                        ss->literals[run_len++] = n1;
258
1.62M
                        n0 = n2;
259
2.63M
                    } else {
260
                        /* Flush current run, start a repeated run */
261
                        /* <len> <queue> */
262
2.63M
                        if (wlimit - q < run_len+1) {
263
43.7k
                            ss->state = state_gt_012;
264
                            /* no_output_room_n0n1n2_read */
265
43.7k
                            goto no_output_room;
266
43.7k
                        }
267
2.59M
                        *++q = run_len-1;
268
2.59M
                        memcpy(q+1, ss->literals, run_len);
269
2.59M
                        q += run_len;
270
2.59M
                        run_len = -3; /* Repeated run of length 3 */
271
2.59M
                    }
272
89.3M
                } else {
273
                    /* Continue literal run */
274
89.3M
                    ss->literals[run_len++] = n0;
275
89.3M
                    n0 = n1;
276
89.3M
                }
277
94.5M
            } else {
278
                /* We are in the middle of a repeated run */
279
                /* <n0 repeated -run_len times> */
280
26.0M
                n1 = *++p;
281
26.0M
                if (n0 == n1)
282
23.2M
                    run_len--; /* Repeated run got longer */
283
26.0M
    case state_lt_01:
284
26.0M
                if (n0 != n1 || p == rlimit || run_len == -128) {
285
                    /* flush the record here, and restart */
286
2.90M
                    if (wlimit - q < 2) {
287
13.9k
                        ss->state = state_lt_01;
288
                        /* no_output_room_lt_n0n1_read */
289
13.9k
                        goto no_output_room;
290
13.9k
                    }
291
2.88M
                    *++q = 257+run_len; /* Repeated run */
292
2.88M
                    *++q = n0;
293
2.88M
                    run_len = 0;
294
2.88M
                    if (p == rlimit)
295
0
                        rlimit = p + ss->record_size;
296
2.88M
                    if (n0 != n1) {
297
2.81M
                        n0 = n1;
298
2.81M
                        goto run_len_0_n0_read;
299
2.81M
                    }
300
2.88M
                }
301
26.0M
            }
302
121M
        }
303
        /* n1 is never valid here */
304
305
2.46M
        if (last) {
306
90.8k
            if (run_len == 0) {
307
                /* EOD */
308
81.9k
                if (wlimit - q < 1) {
309
249
                    ss->state = state_0;
310
249
                    goto no_output_room;
311
249
                }
312
81.9k
            } else if (run_len > 0) {
313
                /* Flush literal run + EOD */
314
1.79k
                if (wlimit - q < run_len+2) {
315
1.66k
                    ss->state = state_0;
316
1.66k
                    goto no_output_room;
317
1.66k
                }
318
130
                *++q = run_len;
319
130
                memcpy(q+1, ss->literals, run_len);
320
130
                q += run_len;
321
130
                *++q = n0;
322
7.16k
            } else if (run_len < 0) {
323
                /* Flush repeated run + EOD */
324
7.16k
                if (wlimit - q < 3) {
325
1.09k
                    ss->state = state_0;
326
1.09k
                    goto no_output_room;
327
1.09k
                }
328
6.07k
                *++q = 257+run_len; /* Repeated run */
329
6.07k
                *++q = n0;
330
6.07k
            }
331
87.8k
    case state_eod_unmarked:
332
87.8k
            if (!ss->omitEOD) {
333
87.8k
                if (wlimit - q < 1) {
334
20
                    ss->state = state_eod_unmarked;
335
20
                    goto no_output_room;
336
20
                }
337
87.8k
                *++q = 128; /* EOD */
338
87.8k
            }
339
87.8k
    case state_eod:
340
87.8k
            ss->run_len = 0;
341
87.8k
            ss->state = state_0;
342
87.8k
            pr->ptr = p;
343
87.8k
            pw->ptr = q;
344
87.8k
            ss->record_left = rlimit - p;
345
87.8k
            debug_ate(pinit, p, qinit, q, EOFC);
346
87.8k
            return EOFC;
347
87.8k
        }
348
3.88M
    }
349
350
    /* Normal exit */
351
2.37M
    ss->run_len = run_len;
352
2.37M
    ss->state = state_0;
353
2.37M
    ss->n0 = n0;
354
2.37M
    ss->n1 = n1;
355
2.37M
    pr->ptr = p;
356
2.37M
    pw->ptr = q;
357
2.37M
    ss->record_left = rlimit - p;
358
2.37M
    debug_ate(pinit, p, qinit, q, 0);
359
2.37M
    return 0;
360
361
153k
no_output_room:
362
153k
    ret = 1;
363
1.42M
no_more_data:
364
1.42M
    ss->n0 = n0;
365
1.42M
    ss->n1 = n1;
366
1.42M
    ss->n2 = n2;
367
1.42M
    ss->run_len = run_len;
368
1.42M
    pr->ptr = p;
369
1.42M
    pw->ptr = q;
370
1.42M
    ss->record_left = rlimit - p;
371
1.42M
    debug_ate(pinit, p, qinit, q, ret);
372
1.42M
    return ret;
373
153k
}
374
375
/* Stream template */
376
const stream_template s_RLE_template = {
377
    &st_RLE_state, s_RLE_init, s_RLE_process, 1, 129, NULL,
378
    s_RLE_set_defaults, s_RLE_init
379
};