1 /* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: srld.c,v 1.4 2002/02/21 22:24:54 giles Exp $ */
18 /* RunLengthDecode filter */
19 #include "stdio_.h" /* includes std.h */
20 #include "memory_.h"
21 #include "strimpl.h"
22 #include "srlx.h"
23
24 /* ------ RunLengthDecode ------ */
25
26 private_st_RLD_state();
27
28 /* Set defaults */
29 private void
s_RLD_set_defaults(stream_state * st)30 s_RLD_set_defaults(stream_state * st)
31 {
32 stream_RLD_state *const ss = (stream_RLD_state *) st;
33
34 s_RLD_set_defaults_inline(ss);
35 }
36
37 /* Initialize */
38 private int
s_RLD_init(stream_state * st)39 s_RLD_init(stream_state * st)
40 {
41 stream_RLD_state *const ss = (stream_RLD_state *) st;
42
43 return s_RLD_init_inline(ss);
44 }
45
46 /* Refill the buffer */
47 private int
s_RLD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)48 s_RLD_process(stream_state * st, stream_cursor_read * pr,
49 stream_cursor_write * pw, bool last)
50 {
51 stream_RLD_state *const ss = (stream_RLD_state *) st;
52 register const byte *p = pr->ptr;
53 register byte *q = pw->ptr;
54 const byte *rlimit = pr->limit;
55 byte *wlimit = pw->limit;
56 int left;
57 int status = 0;
58
59 top:
60 if ((left = ss->copy_left) > 0) {
61 /*
62 * We suspended because the output buffer was full:;
63 * try again now.
64 */
65 uint avail = wlimit - q;
66 int copy_status = 1;
67
68 if (left > avail)
69 left = avail;
70 if (ss->copy_data >= 0)
71 memset(q + 1, ss->copy_data, left);
72 else {
73 avail = rlimit - p;
74 if (left >= avail) {
75 copy_status = 0;
76 left = avail;
77 }
78 memcpy(q + 1, p + 1, left);
79 p += left;
80 }
81 q += left;
82 if ((ss->copy_left -= left) > 0) {
83 status = copy_status;
84 goto x;
85 }
86 }
87 while (p < rlimit) {
88 int b = *++p;
89
90 if (b < 128) {
91 if (++b > rlimit - p || b > wlimit - q) {
92 ss->copy_left = b;
93 ss->copy_data = -1;
94 goto top;
95 }
96 memcpy(q + 1, p + 1, b);
97 p += b;
98 q += b;
99 } else if (b == 128) { /* end of data */
100 if (ss->EndOfData) {
101 status = EOFC;
102 break;
103 }
104 } else if (p == rlimit) {
105 p--;
106 break;
107 } else if ((b = 257 - b) > wlimit - q) {
108 ss->copy_left = b;
109 ss->copy_data = *++p;
110 goto top;
111 } else {
112 memset(q + 1, *++p, b);
113 q += b;
114 }
115 }
116 x: pr->ptr = p;
117 pw->ptr = q;
118 return status;
119 }
120
121 /* Stream template */
122 const stream_template s_RLD_template = {
123 &st_RLD_state, s_RLD_init, s_RLD_process, 1, 1, NULL,
124 s_RLD_set_defaults
125 };
126