/src/ghostpdl/base/srld.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 | | /* RunLengthDecode filter */ |
18 | | #include "stdio_.h" /* includes std.h */ |
19 | | #include "memory_.h" |
20 | | #include "strimpl.h" |
21 | | #include "srlx.h" |
22 | | |
23 | | /* ------ RunLengthDecode ------ */ |
24 | | |
25 | | private_st_RLD_state(); |
26 | | |
27 | | /* Set defaults */ |
28 | | static void |
29 | | s_RLD_set_defaults(stream_state * st) |
30 | 4 | { |
31 | 4 | stream_RLD_state *const ss = (stream_RLD_state *) st; |
32 | | |
33 | 4 | s_RLD_set_defaults_inline(ss); |
34 | 4 | } |
35 | | |
36 | | /* Initialize */ |
37 | | static int |
38 | | s_RLD_init(stream_state * st) |
39 | 4 | { |
40 | 4 | stream_RLD_state *const ss = (stream_RLD_state *) st; |
41 | | |
42 | 4 | return s_RLD_init_inline(ss); |
43 | 4 | } |
44 | | |
45 | | /* Refill the buffer */ |
46 | | static int |
47 | | s_RLD_process(stream_state * st, stream_cursor_read * pr, |
48 | | stream_cursor_write * pw, bool last) |
49 | 29 | { |
50 | 29 | stream_RLD_state *const ss = (stream_RLD_state *) st; |
51 | 29 | register const byte *p = pr->ptr; |
52 | 29 | register byte *q = pw->ptr; |
53 | 29 | const byte *rlimit = pr->limit; |
54 | 29 | byte *wlimit = pw->limit; |
55 | 29 | int left; |
56 | 29 | int status = 0; |
57 | | |
58 | 54 | top: |
59 | 54 | if ((left = ss->copy_left) > 0) { |
60 | | /* |
61 | | * We suspended because the output buffer was full:; |
62 | | * try again now. |
63 | | */ |
64 | 46 | uint avail = wlimit - q; |
65 | 46 | int copy_status = 1; |
66 | | |
67 | 46 | if (left > avail) |
68 | 16 | left = avail; |
69 | 46 | if (ss->copy_data >= 0) |
70 | 10 | memset(q + 1, ss->copy_data, left); |
71 | 36 | else { |
72 | 36 | avail = rlimit - p; |
73 | 36 | if (left >= avail) { |
74 | 9 | copy_status = 0; |
75 | 9 | left = avail; |
76 | 9 | } |
77 | 36 | memcpy(q + 1, p + 1, left); |
78 | 36 | p += left; |
79 | 36 | } |
80 | 46 | q += left; |
81 | 46 | if ((ss->copy_left -= left) > 0) { |
82 | 25 | status = copy_status; |
83 | 25 | goto x; |
84 | 25 | } |
85 | 46 | } |
86 | 2.02k | while (p < rlimit) { |
87 | 2.02k | int b = *++p; |
88 | | |
89 | 2.02k | if (b < 128) { |
90 | 1.65k | if (++b > rlimit - p || b > wlimit - q) { |
91 | 19 | ss->copy_left = b; |
92 | 19 | ss->copy_data = -1; |
93 | 19 | goto top; |
94 | 19 | } |
95 | 1.63k | memcpy(q + 1, p + 1, b); |
96 | 1.63k | p += b; |
97 | 1.63k | q += b; |
98 | 1.63k | } else if (b == 128) { /* end of data */ |
99 | 0 | if (ss->EndOfData) { |
100 | 0 | status = EOFC; |
101 | 0 | break; |
102 | 0 | } |
103 | 370 | } else if (p == rlimit) { |
104 | 0 | p--; |
105 | 0 | break; |
106 | 370 | } else if ((b = 257 - b) > wlimit - q) { |
107 | 6 | ss->copy_left = b; |
108 | 6 | ss->copy_data = *++p; |
109 | 6 | goto top; |
110 | 364 | } else { |
111 | 364 | memset(q + 1, *++p, b); |
112 | 364 | q += b; |
113 | 364 | } |
114 | 2.02k | } |
115 | 29 | x: pr->ptr = p; |
116 | 29 | pw->ptr = q; |
117 | 29 | return status; |
118 | 29 | } |
119 | | |
120 | | /* Stream template */ |
121 | | const stream_template s_RLD_template = { |
122 | | &st_RLD_state, s_RLD_init, s_RLD_process, 1, 1, NULL, |
123 | | s_RLD_set_defaults |
124 | | }; |