1 : /* -*- mode: C -*-
2 : *
3 : * File: pdf-token.c
4 : * Date: Sat Jul 7 03:04:30 2007
5 : *
6 : * GNU PDF Library - PDF token objects
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 <assert.h>
30 : #include <math.h>
31 :
32 : #include <pdf-token.h>
33 : #include <pdf-alloc.h>
34 :
35 : /* Private functions */
36 :
37 : static INLINE pdf_status_t
38 : pdf_token_new (enum pdf_token_type_e type, pdf_token_t *token)
39 1988 : {
40 : pdf_token_t new;
41 1988 : assert (token);
42 :
43 1988 : new = (pdf_token_t) pdf_alloc (sizeof (struct pdf_token_s));
44 1988 : if (!new)
45 0 : return PDF_ENOMEM;
46 :
47 1988 : new->type = type;
48 1988 : *token = new;
49 1988 : return PDF_OK;
50 : }
51 :
52 : pdf_status_t
53 : pdf_token_destroy (pdf_token_t token)
54 1988 : {
55 1988 : assert (token);
56 1988 : switch (token->type)
57 : {
58 : case PDF_TOKEN_STRING: /* fall through */
59 : case PDF_TOKEN_NAME: /* fall through */
60 : case PDF_TOKEN_KEYWORD: /* fall through */
61 : case PDF_TOKEN_COMMENT:
62 : {
63 1358 : pdf_dealloc (token->value.buffer.data);
64 : break;
65 : }
66 : default:
67 : {
68 : /* NOP */
69 : break;
70 : }
71 : }
72 :
73 1988 : pdf_dealloc (token);
74 1988 : return PDF_OK;
75 : }
76 :
77 : static pdf_status_t
78 : pdf_token_buffer_new (enum pdf_token_type_e type,
79 : const pdf_char_t *value,
80 : pdf_size_t size,
81 : pdf_bool_t nullterm,
82 : pdf_token_t *token)
83 1358 : {
84 1358 : pdf_token_t new_obj = NULL;
85 1358 : pdf_status_t rv = pdf_token_new (type, &new_obj);
86 1358 : if (rv != PDF_OK)
87 0 : goto fail;
88 :
89 1358 : rv = PDF_ENOMEM;
90 1358 : new_obj->value.buffer.data = pdf_alloc (size + 1);
91 1358 : if (!new_obj->value.buffer.data)
92 0 : goto fail;
93 :
94 1358 : new_obj->value.buffer.size = size;
95 1358 : memcpy (new_obj->value.buffer.data, value, size);
96 :
97 : /* If the value isn't null terminated, append a non-null character
98 : * to catch bugs. */
99 1358 : new_obj->value.buffer.data[size] = nullterm ? 0 : 'X';
100 :
101 1358 : *token = new_obj;
102 1358 : return PDF_OK;
103 :
104 0 : fail:
105 0 : if (new_obj)
106 0 : pdf_dealloc (new_obj);
107 0 : return rv;
108 : }
109 :
110 :
111 : /* General functions */
112 :
113 : enum pdf_token_type_e
114 : pdf_token_get_type (const pdf_token_t token)
115 1246 : {
116 1246 : assert (token);
117 1246 : return token->type;
118 : }
119 :
120 : pdf_bool_t
121 : pdf_token_equal_p (const pdf_token_t token1, const pdf_token_t token2)
122 364 : {
123 364 : assert (token1 && token2);
124 364 : if (token1->type != token2->type)
125 0 : return PDF_FALSE;
126 :
127 364 : switch (token1->type)
128 : {
129 : case PDF_TOKEN_DICT_START: /* fall through */
130 : case PDF_TOKEN_DICT_END: /* fall through */
131 : case PDF_TOKEN_ARRAY_START: /* fall through */
132 : case PDF_TOKEN_ARRAY_END: /* fall through */
133 : case PDF_TOKEN_PROC_START: /* fall through */
134 : case PDF_TOKEN_PROC_END:
135 6 : return PDF_TRUE;
136 :
137 : case PDF_TOKEN_INTEGER:
138 3 : return token1->value.integer == token2->value.integer;
139 :
140 : case PDF_TOKEN_REAL:
141 2 : return token1->value.real == token2->value.real;
142 :
143 : case PDF_TOKEN_COMMENT: /* fall through */
144 : case PDF_TOKEN_STRING: /* fall through */
145 : case PDF_TOKEN_NAME: /* fall through */
146 : case PDF_TOKEN_KEYWORD:
147 : {
148 353 : struct pdf_token_buffer_s *buf1 = &token1->value.buffer;
149 353 : struct pdf_token_buffer_s *buf2 = &token2->value.buffer;
150 353 : return (buf1->size == buf2->size
151 : && ( buf1->data == buf2->data
152 : || !memcmp (buf1->data, buf2->data, buf1->size) ));
153 : }
154 :
155 : default:
156 0 : assert (0); /* shouldn't happen */
157 : return 0;
158 : }
159 : }
160 :
161 : pdf_status_t
162 : pdf_token_dup (const pdf_token_t token, pdf_token_t *new)
163 0 : {
164 0 : assert (token);
165 0 : switch (token->type)
166 : {
167 : case PDF_TOKEN_DICT_START: /* fall through */
168 : case PDF_TOKEN_DICT_END: /* fall through */
169 : case PDF_TOKEN_ARRAY_START: /* fall through */
170 : case PDF_TOKEN_ARRAY_END: /* fall through */
171 : case PDF_TOKEN_PROC_START: /* fall through */
172 : case PDF_TOKEN_PROC_END:
173 0 : return pdf_token_valueless_new (token->type, new);
174 :
175 : case PDF_TOKEN_INTEGER:
176 0 : return pdf_token_integer_new (token->value.integer, new);
177 :
178 : case PDF_TOKEN_REAL:
179 0 : return pdf_token_real_new (token->value.real, new);
180 :
181 : case PDF_TOKEN_STRING:
182 0 : return pdf_token_string_new (token->value.buffer.data,
183 : token->value.buffer.size,
184 : new);
185 : case PDF_TOKEN_NAME:
186 0 : return pdf_token_name_new (token->value.buffer.data,
187 : token->value.buffer.size,
188 : new);
189 : case PDF_TOKEN_KEYWORD:
190 0 : return pdf_token_keyword_new (token->value.buffer.data,
191 : token->value.buffer.size,
192 : new);
193 : case PDF_TOKEN_COMMENT:
194 0 : return pdf_token_comment_new (token->value.buffer.data,
195 : token->value.buffer.size,
196 : new);
197 : default:
198 : /* Should not be reached: make the compiler happy */
199 0 : return PDF_EBADDATA;
200 : }
201 : }
202 :
203 : pdf_status_t
204 : pdf_token_valueless_new (enum pdf_token_type_e type,
205 : pdf_token_t *token)
206 439 : {
207 439 : switch (type)
208 : {
209 : case PDF_TOKEN_DICT_START: /* fall through */
210 : case PDF_TOKEN_DICT_END: /* fall through */
211 : case PDF_TOKEN_ARRAY_START: /* fall through */
212 : case PDF_TOKEN_ARRAY_END: /* fall through */
213 : case PDF_TOKEN_PROC_START: /* fall through */
214 : case PDF_TOKEN_PROC_END:
215 439 : return pdf_token_new (type, token);
216 : default:
217 0 : return PDF_EBADDATA;
218 : }
219 : }
220 :
221 :
222 : /** integers *****/
223 :
224 : pdf_status_t
225 : pdf_token_integer_new (pdf_i32_t value, pdf_token_t *token)
226 176 : {
227 176 : pdf_status_t rv = pdf_token_new (PDF_TOKEN_INTEGER, token);
228 176 : if (rv == PDF_OK)
229 176 : (*token)->value.integer = value;
230 :
231 176 : return rv;
232 : }
233 :
234 : pdf_i32_t
235 : pdf_token_get_integer_value (const pdf_token_t token)
236 170 : {
237 170 : assert (token && token->type == PDF_TOKEN_INTEGER);
238 170 : return token->value.integer;
239 : }
240 :
241 :
242 : /** reals *****/
243 :
244 : pdf_status_t
245 : pdf_token_real_new (pdf_real_t value, pdf_token_t *token)
246 15 : {
247 : pdf_status_t rv;
248 :
249 15 : if (isnan(value) || isinf(value))
250 0 : return PDF_EBADDATA;
251 :
252 15 : rv = pdf_token_new (PDF_TOKEN_REAL, token);
253 15 : if (rv == PDF_OK)
254 15 : (*token)->value.real = value;
255 :
256 15 : return rv;
257 : }
258 :
259 : pdf_real_t
260 : pdf_token_get_real_value (const pdf_token_t token)
261 11 : {
262 11 : assert (token && token->type == PDF_TOKEN_REAL);
263 11 : return token->value.real;
264 : }
265 :
266 :
267 : /** names *****/
268 :
269 : pdf_status_t
270 : pdf_token_name_new (const pdf_char_t *value,
271 : pdf_size_t size,
272 : pdf_token_t *token)
273 698 : {
274 : pdf_size_t i;
275 1422 : for (i = 0; i < size; ++i)
276 : {
277 724 : if (value[i] == 0) /* names can't include null bytes */
278 0 : return PDF_EBADDATA;
279 : }
280 :
281 698 : return pdf_token_buffer_new (PDF_TOKEN_NAME, value, size, 1, token);
282 : }
283 :
284 : pdf_size_t
285 : pdf_token_get_name_size (const pdf_token_t name)
286 0 : {
287 0 : assert (name && name->type == PDF_TOKEN_NAME);
288 0 : return name->value.buffer.size;
289 : }
290 :
291 : const pdf_char_t *
292 : pdf_token_get_name_data (const pdf_token_t name)
293 14 : {
294 14 : assert (name && name->type == PDF_TOKEN_NAME);
295 14 : return name->value.buffer.data;
296 : }
297 :
298 :
299 : /** strings *****/
300 :
301 : pdf_status_t
302 : pdf_token_string_new (const pdf_char_t *value,
303 : pdf_size_t size,
304 : pdf_token_t *token)
305 19 : {
306 19 : return pdf_token_buffer_new (PDF_TOKEN_STRING, value, size, 0, token);
307 : }
308 :
309 : pdf_size_t
310 : pdf_token_get_string_size (const pdf_token_t token)
311 1 : {
312 1 : assert (token && token->type == PDF_TOKEN_STRING);
313 1 : return token->value.buffer.size;
314 : }
315 :
316 : const pdf_char_t *
317 : pdf_token_get_string_data (const pdf_token_t token)
318 0 : {
319 0 : assert (token && token->type == PDF_TOKEN_STRING);
320 0 : return token->value.buffer.data;
321 : }
322 :
323 :
324 : /** comments *****/
325 :
326 : pdf_status_t
327 : pdf_token_comment_new (const pdf_char_t *value,
328 : pdf_size_t size,
329 : pdf_token_t *token)
330 0 : {
331 : pdf_size_t i;
332 0 : for (i = 0; i < size; ++i)
333 : {
334 : /* comments can't span multiple lines */
335 0 : if (pdf_is_eol_char(value[i]))
336 0 : return PDF_EBADDATA;
337 : }
338 :
339 0 : return pdf_token_buffer_new (PDF_TOKEN_COMMENT, value, size, 0, token);
340 : }
341 :
342 : pdf_size_t
343 : pdf_token_get_comment_size (const pdf_token_t comment)
344 0 : {
345 0 : assert (comment && comment->type == PDF_TOKEN_COMMENT);
346 0 : return comment->value.buffer.size;
347 : }
348 :
349 : const pdf_char_t *
350 : pdf_token_get_comment_data (const pdf_token_t comment)
351 0 : {
352 0 : assert (comment && comment->type == PDF_TOKEN_COMMENT);
353 0 : return comment->value.buffer.data;
354 : }
355 :
356 :
357 : /** keywords *****/
358 :
359 : pdf_status_t
360 : pdf_token_keyword_new (const pdf_char_t *value,
361 : pdf_size_t size,
362 : pdf_token_t *token)
363 641 : {
364 : pdf_size_t i;
365 2856 : for (i = 0; i < size; ++i)
366 : {
367 : /* keywords can only include regular characters */
368 4430 : if (!pdf_is_regular_char(value[i]))
369 0 : return PDF_EBADDATA;
370 : }
371 :
372 641 : return pdf_token_buffer_new (PDF_TOKEN_KEYWORD, value, size, 1, token);
373 : }
374 :
375 : pdf_size_t
376 : pdf_token_get_keyword_size (const pdf_token_t keyword)
377 637 : {
378 637 : assert (keyword && keyword->type == PDF_TOKEN_KEYWORD);
379 637 : return keyword->value.buffer.size;
380 : }
381 :
382 : const pdf_char_t *
383 : pdf_token_get_keyword_data (const pdf_token_t keyword)
384 637 : {
385 637 : assert (keyword && keyword->type == PDF_TOKEN_KEYWORD);
386 637 : return keyword->value.buffer.data;
387 : }
388 :
389 :
390 : /* End of pdf-token.c */
|