1 /* Copyright (C) 2001-2012 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., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, 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
s_RLD_set_defaults(stream_state * st)29 s_RLD_set_defaults(stream_state * st)
30 {
31 stream_RLD_state *const ss = (stream_RLD_state *) st;
32
33 s_RLD_set_defaults_inline(ss);
34 }
35
36 /* Initialize */
37 static int
s_RLD_init(stream_state * st)38 s_RLD_init(stream_state * st)
39 {
40 stream_RLD_state *const ss = (stream_RLD_state *) st;
41
42 return s_RLD_init_inline(ss);
43 }
44
45 /* Refill the buffer */
46 static int
s_RLD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)47 s_RLD_process(stream_state * st, stream_cursor_read * pr,
48 stream_cursor_write * pw, bool last)
49 {
50 stream_RLD_state *const ss = (stream_RLD_state *) st;
51 register const byte *p = pr->ptr;
52 register byte *q = pw->ptr;
53 const byte *rlimit = pr->limit;
54 byte *wlimit = pw->limit;
55 int left;
56 int status = 0;
57
58 top:
59 if ((left = ss->copy_left) > 0) {
60 /*
61 * We suspended because the output buffer was full:;
62 * try again now.
63 */
64 uint avail = wlimit - q;
65 int copy_status = 1;
66
67 if (left > avail)
68 left = avail;
69 if (ss->copy_data >= 0)
70 memset(q + 1, ss->copy_data, left);
71 else {
72 avail = rlimit - p;
73 if (left >= avail) {
74 copy_status = 0;
75 left = avail;
76 }
77 memcpy(q + 1, p + 1, left);
78 p += left;
79 }
80 q += left;
81 if ((ss->copy_left -= left) > 0) {
82 status = copy_status;
83 goto x;
84 }
85 }
86 while (p < rlimit) {
87 int b = *++p;
88
89 if (b < 128) {
90 if (++b > rlimit - p || b > wlimit - q) {
91 ss->copy_left = b;
92 ss->copy_data = -1;
93 goto top;
94 }
95 memcpy(q + 1, p + 1, b);
96 p += b;
97 q += b;
98 } else if (b == 128) { /* end of data */
99 if (ss->EndOfData) {
100 status = EOFC;
101 break;
102 }
103 } else if (p == rlimit) {
104 p--;
105 break;
106 } else if ((b = 257 - b) > wlimit - q) {
107 ss->copy_left = b;
108 ss->copy_data = *++p;
109 goto top;
110 } else {
111 memset(q + 1, *++p, b);
112 q += b;
113 }
114 }
115 x: pr->ptr = p;
116 pw->ptr = q;
117 return status;
118 }
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 };
125