1 : /* -*- mode: C -*-
2 : *
3 : * File: pdf-stm-f-rl.c
4 : * Date: Sun Jul 15 22:01:18 2007
5 : *
6 : * GNU PDF Library - RunLength encoder/decoder
7 : *
8 : */
9 :
10 : /* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. */
11 :
12 : /* This program is free software: you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation, either version 3 of the License, or
15 : * (at your option) any later version.
16 : *
17 : * This program is distributed in the hope that it will be useful,
18 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : * GNU General Public License for more details.
21 : *
22 : * You should have received a copy of the GNU General Public License
23 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include <config.h>
27 :
28 : #include <string.h>
29 : #include <stdio.h>
30 :
31 : #include <pdf-alloc.h>
32 : #include <pdf-stm-f-rl.h>
33 :
34 :
35 : static int encode_rl_char (pdf_stm_f_rl_t st, pdf_buffer_t out);
36 : static int decode_rl_char (pdf_stm_f_rl_t st, pdf_buffer_t out);
37 : static int copy_next_bytes (pdf_stm_f_rl_t st, pdf_buffer_t in,
38 : pdf_buffer_t out);
39 :
40 :
41 : pdf_status_t
42 : pdf_stm_f_rlenc_init (pdf_hash_t params, void **state)
43 2 : {
44 : pdf_status_t ret;
45 : pdf_stm_f_rl_t filter_state;
46 :
47 2 : filter_state = pdf_alloc (sizeof (struct pdf_stm_f_rl_s));
48 :
49 2 : if (state == NULL)
50 : {
51 0 : ret = PDF_EBADDATA;
52 : }
53 2 : else if (filter_state == NULL)
54 : {
55 0 : ret = PDF_ENOMEM;
56 : }
57 : else
58 : {
59 : /* Initialize fields */
60 2 : filter_state->curchar = 0;
61 2 : filter_state->rlchar = 0;
62 2 : filter_state->run_p = PDF_FALSE;
63 2 : filter_state->rl = -1;
64 2 : filter_state->dec_p = PDF_FALSE;;
65 2 : filter_state->dec_count = 0;
66 2 : filter_state->enc_p = PDF_STM_F_RL_NONE;
67 :
68 2 : *state = (void *) filter_state;
69 2 : ret = PDF_OK;
70 : }
71 :
72 2 : return ret;
73 : }
74 :
75 :
76 : pdf_status_t
77 : pdf_stm_f_rldec_init (pdf_hash_t params, void **state)
78 1 : {
79 1 : return pdf_stm_f_rlenc_init (params,state);
80 : }
81 :
82 :
83 : pdf_status_t
84 : pdf_stm_f_rlenc_apply (pdf_hash_t params, void * state, pdf_buffer_t in,
85 : pdf_buffer_t out, pdf_bool_t finish_p)
86 112 : {
87 : pdf_stm_f_rl_t st;
88 :
89 112 : st = (pdf_stm_f_rl_t) state;
90 :
91 279 : while (!pdf_buffer_eob_p (in))
92 : {
93 64 : st->curchar = in->data[in->rp];
94 :
95 : /* we're not encoding any character yet */
96 64 : if (!st->run_p)
97 : {
98 10 : st->rlchar = st->curchar;
99 10 : st->run_p = PDF_TRUE;
100 10 : st->rl++;
101 10 : in->rp++;
102 : }
103 : /* we're encoding some character now */
104 90 : else if (st->curchar == st->rlchar && st->rl < 127)
105 : {
106 36 : st->rl++;
107 36 : in->rp++;
108 : }
109 : /*
110 : * the rl code is too long or the rl char is different,
111 : * so we write what we encoded so far.
112 : */
113 : else
114 : {
115 18 : if (encode_rl_char (st, out) < 0)
116 : {
117 9 : return PDF_ENOUTPUT;
118 : }
119 9 : st->rl=-1;
120 9 : st->run_p = PDF_FALSE;
121 : }
122 : }
123 :
124 : /*
125 : * we may have finished with some history, we save it if needed,
126 : * then we add the EOD.
127 : */
128 103 : if (finish_p)
129 : {
130 3 : if (st->run_p)
131 : {
132 2 : if (encode_rl_char (st, out) < 0)
133 : {
134 : /* Should not be reached */
135 1 : return PDF_ENOUTPUT;
136 : }
137 1 : st->rl=-1;
138 1 : st->run_p = PDF_FALSE;
139 : }
140 2 : if (pdf_buffer_full_p (out))
141 : {
142 : /* Should not be reached */
143 1 : return PDF_ENOUTPUT;
144 : }
145 : /* Insert EOD marker */
146 1 : out->data[out->wp++] = 128;
147 1 : return PDF_EEOF;
148 : }
149 :
150 100 : return PDF_ENINPUT;
151 : }
152 :
153 :
154 : pdf_status_t
155 : pdf_stm_f_rlenc_dealloc_state (void *state)
156 1 : {
157 1 : pdf_dealloc (state);
158 1 : return PDF_OK;
159 : }
160 :
161 : pdf_status_t
162 : pdf_stm_f_rldec_apply (pdf_hash_t params, void *state, pdf_buffer_t in,
163 : pdf_buffer_t out, pdf_bool_t finish_p)
164 57 : {
165 : pdf_stm_f_rl_t st;
166 : pdf_status_t copied;
167 :
168 57 : st = (pdf_stm_f_rl_t) state;
169 :
170 134 : while (!pdf_buffer_eob_p (in))
171 : {
172 56 : st->curchar = in->data[in->rp];
173 :
174 : /* we're not decoding any character yet */
175 56 : if (!st->run_p)
176 : {
177 10 : st->rlchar = st->curchar;
178 10 : st->run_p = PDF_TRUE;
179 10 : in->rp++;
180 : }
181 : /* copy the following 1 to 128 bytes literally */
182 46 : else if (st->rlchar < 128)
183 : {
184 2 : copied = copy_next_bytes (st, in, out);
185 : if (copied < 0)
186 : {
187 : return PDF_ENOUTPUT;
188 : }
189 2 : else if (copied > 0)
190 : {
191 0 : return PDF_ENINPUT;
192 : }
193 2 : st->run_p = PDF_FALSE;
194 : }
195 : /* copy the next char 257 - length (2 to 128) times */
196 44 : else if (st->rlchar > 128)
197 : {
198 44 : if (decode_rl_char (st, out) < 0)
199 : {
200 36 : return PDF_ENOUTPUT;
201 : }
202 8 : st->run_p = PDF_FALSE;
203 8 : in->rp++;
204 : }
205 : /* EOD mark */
206 : else
207 : {
208 0 : st->run_p = PDF_FALSE;
209 0 : return PDF_EEOF;
210 : }
211 : }
212 :
213 21 : return PDF_ENINPUT;
214 : }
215 :
216 : pdf_status_t
217 : pdf_stm_f_rldec_dealloc_state (void *state)
218 1 : {
219 1 : pdf_dealloc (state);
220 1 : return PDF_OK;
221 : }
222 :
223 : /* Private functions */
224 :
225 : static int
226 : encode_rl_char (pdf_stm_f_rl_t st, pdf_buffer_t out)
227 20 : {
228 20 : if (st->enc_p == PDF_STM_F_RL_NONE)
229 : {
230 10 : if (pdf_buffer_full_p (out))
231 : {
232 0 : return -1;
233 : }
234 10 : out->data[out->wp++] = (st->rl == 0) ? 0 : 256 - st->rl;
235 10 : st->enc_p = PDF_STM_F_RL_WRL;
236 : }
237 :
238 20 : if (st->enc_p == PDF_STM_F_RL_WRL)
239 : {
240 20 : if (pdf_buffer_full_p (out))
241 : {
242 10 : return -1;
243 : }
244 10 : out->data[out->wp++] = st->rlchar;
245 10 : st->enc_p = PDF_STM_F_RL_NONE;
246 : }
247 :
248 10 : return 0;
249 : }
250 :
251 :
252 : static int
253 : decode_rl_char (pdf_stm_f_rl_t st, pdf_buffer_t out)
254 : {
255 44 : if (!st->dec_p)
256 : {
257 8 : st->dec_count = 257 - st->rlchar;
258 8 : st->dec_p = PDF_TRUE;
259 : }
260 :
261 88 : while (st->dec_count > 0)
262 : {
263 80 : if (pdf_buffer_full_p (out))
264 : {
265 36 : return -1;
266 : }
267 44 : out->data[out->wp++] = st->curchar;
268 44 : st->dec_count--;
269 : }
270 :
271 8 : st->dec_p = PDF_FALSE;
272 8 : return 0;
273 : }
274 :
275 :
276 : static int
277 : copy_next_bytes (pdf_stm_f_rl_t st, pdf_buffer_t in, pdf_buffer_t out)
278 : {
279 2 : if (!st->dec_p)
280 : {
281 2 : if (pdf_buffer_full_p (out))
282 : {
283 0 : return -1;
284 : }
285 2 : st->dec_count = st->rlchar + 1;
286 2 : st->dec_p = PDF_TRUE;
287 2 : out->data[out->wp++] = st->curchar;
288 2 : in->rp++;
289 2 : st->dec_count--;
290 : }
291 :
292 2 : while (st->dec_count > 0)
293 : {
294 0 : if (pdf_buffer_eob_p (in))
295 : {
296 0 : return 1;
297 : }
298 0 : else if (pdf_buffer_full_p (out))
299 : {
300 0 : return -1;
301 : }
302 0 : out->data[out->wp] = in->data[in->rp];
303 0 : out->wp++;
304 0 : in->rp++;
305 0 : st->dec_count--;
306 : }
307 :
308 2 : st->dec_p = PDF_FALSE;
309 2 : return 0;
310 : }
311 :
312 :
313 : /* End of pdf_stm_f_rl.c */
|