xref: /plan9/sys/src/cmd/gs/src/srld.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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