1 : /* -*- mode: C -*-
2 : *
3 : * File: pdf-stm-be.c
4 : * Date: Wed Jun 18 21:15:16 2008
5 : *
6 : * GNU PDF Library - Stream backend
7 : *
8 : */
9 :
10 : /* Copyright (C) 2009, 2010, 2011 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 :
30 : #include <pdf-stm-be.h>
31 :
32 : /* Forward declarations */
33 :
34 : static pdf_size_t pdf_stm_be_mem_read (pdf_stm_be_t be,
35 : pdf_char_t *buffer,
36 : pdf_size_t bytes);
37 : static pdf_size_t pdf_stm_be_mem_write (pdf_stm_be_t be,
38 : pdf_char_t *buffer,
39 : pdf_size_t bytes);
40 : static pdf_off_t pdf_stm_be_mem_seek (pdf_stm_be_t be,
41 : pdf_off_t pos);
42 : static pdf_off_t pdf_stm_be_mem_tell (pdf_stm_be_t be);
43 : static pdf_size_t pdf_stm_be_file_read (pdf_stm_be_t be,
44 : pdf_char_t *buffer,
45 : pdf_size_t bytes);
46 : static pdf_size_t pdf_stm_be_file_write (pdf_stm_be_t be,
47 : pdf_char_t *buffer,
48 : pdf_size_t bytes);
49 : static pdf_off_t pdf_stm_be_file_seek (pdf_stm_be_t be,
50 : pdf_off_t pos);
51 : static pdf_off_t pdf_stm_be_file_tell (pdf_stm_be_t be);
52 : static pdf_size_t pdf_stm_be_cfile_read (pdf_stm_be_t be,
53 : pdf_char_t *buffer,
54 : pdf_size_t bytes);
55 : static pdf_size_t pdf_stm_be_cfile_write (pdf_stm_be_t be,
56 : pdf_char_t *buffer,
57 : pdf_size_t bytes);
58 : static pdf_off_t pdf_stm_be_cfile_seek (pdf_stm_be_t be,
59 : pdf_off_t pos);
60 : static pdf_off_t pdf_stm_be_cfile_tell (pdf_stm_be_t be);
61 :
62 : /*
63 : * Public functions
64 : */
65 :
66 : pdf_stm_be_t
67 : pdf_stm_be_new_cfile (FILE* file,
68 : pdf_off_t pos)
69 0 : {
70 : pdf_stm_be_t new;
71 :
72 : /* Allocate a new structure */
73 0 : new = (pdf_stm_be_t) pdf_alloc (sizeof(struct pdf_stm_be_s));
74 :
75 : /* Initialization */
76 0 : new->type = PDF_STM_BE_CFILE;
77 0 : new->data.cfile.file = file;
78 0 : new->data.cfile.pos = pos;
79 :
80 0 : if (pos)
81 : {
82 0 : pdf_stm_be_cfile_seek (new, pos);
83 : }
84 :
85 0 : return new;
86 : }
87 :
88 : pdf_stm_be_t
89 : pdf_stm_be_new_file (pdf_fsys_file_t file,
90 : pdf_off_t pos)
91 10 : {
92 : pdf_stm_be_t new;
93 :
94 : /* Allocate a new structure */
95 10 : new = (pdf_stm_be_t) pdf_alloc(sizeof(struct pdf_stm_be_s));
96 :
97 : /* Initialization */
98 10 : new->type = PDF_STM_BE_FILE;
99 10 : new->data.file.file = file;
100 10 : new->data.file.pos = pos;
101 :
102 10 : return new;
103 : }
104 :
105 : pdf_stm_be_t
106 : pdf_stm_be_new_mem (pdf_char_t *buffer,
107 : pdf_size_t size,
108 : pdf_size_t pos)
109 826 : {
110 : pdf_stm_be_t new;
111 :
112 : /* Allocate a new structure */
113 826 : new = (pdf_stm_be_t) pdf_alloc(sizeof(struct pdf_stm_be_s));
114 :
115 : /* Initialization */
116 826 : new->type = PDF_STM_BE_MEM;
117 826 : new->data.mem.buffer = buffer;
118 826 : new->data.mem.size = size;
119 826 : new->data.mem.pos = pos;
120 :
121 826 : return new;
122 : }
123 :
124 : pdf_status_t
125 : pdf_stm_be_destroy (pdf_stm_be_t be)
126 651 : {
127 651 : pdf_dealloc (be);
128 : /* Note that we are not deallocating the internal buffer (in the
129 : case of a memory backend) nor the open file (in the case of a
130 : file backend) */
131 651 : return PDF_OK;
132 : }
133 :
134 : pdf_size_t
135 : pdf_stm_be_read (pdf_stm_be_t be,
136 : pdf_char_t *buffer,
137 : pdf_size_t bytes)
138 2559 : {
139 : pdf_size_t readed_bytes;
140 :
141 2559 : switch (be->type)
142 : {
143 : case PDF_STM_BE_MEM:
144 : {
145 2537 : readed_bytes = pdf_stm_be_mem_read (be,
146 : buffer,
147 : bytes);
148 2537 : break;
149 : }
150 : case PDF_STM_BE_FILE:
151 : {
152 22 : readed_bytes = pdf_stm_be_file_read (be,
153 : buffer,
154 : bytes);
155 22 : break;
156 : }
157 : case PDF_STM_BE_CFILE:
158 : {
159 0 : readed_bytes = pdf_stm_be_cfile_read (be,
160 : buffer,
161 : bytes);
162 0 : break;
163 : }
164 : default:
165 : {
166 : /* Uh oh */
167 0 : readed_bytes = 0;
168 : break;
169 : }
170 : }
171 :
172 2559 : return readed_bytes;
173 : }
174 :
175 : pdf_size_t
176 : pdf_stm_be_write (pdf_stm_be_t be,
177 : pdf_char_t *buffer,
178 : pdf_size_t bytes)
179 174 : {
180 : pdf_size_t written_bytes;
181 :
182 174 : switch (be->type)
183 : {
184 : case PDF_STM_BE_MEM:
185 : {
186 172 : written_bytes = pdf_stm_be_mem_write (be,
187 : buffer,
188 : bytes);
189 172 : break;
190 : }
191 : case PDF_STM_BE_FILE:
192 : {
193 2 : written_bytes = pdf_stm_be_file_write (be,
194 : buffer,
195 : bytes);
196 2 : break;
197 : }
198 : case PDF_STM_BE_CFILE:
199 : {
200 0 : written_bytes = pdf_stm_be_cfile_write (be,
201 : buffer,
202 : bytes);
203 0 : break;
204 : }
205 : default:
206 : {
207 : /* Uh oh */
208 0 : written_bytes = 0;
209 : break;
210 : }
211 : }
212 :
213 174 : return written_bytes;
214 : }
215 :
216 : pdf_off_t
217 : pdf_stm_be_seek (pdf_stm_be_t be,
218 : pdf_off_t pos)
219 7 : {
220 : pdf_off_t result;
221 :
222 7 : switch (be->type)
223 : {
224 : case PDF_STM_BE_MEM:
225 : {
226 4 : result = pdf_stm_be_mem_seek (be, pos);
227 4 : break;
228 : }
229 : case PDF_STM_BE_FILE:
230 : {
231 3 : result = pdf_stm_be_file_seek (be, pos);
232 3 : break;
233 : }
234 : case PDF_STM_BE_CFILE:
235 : {
236 0 : result = pdf_stm_be_cfile_seek (be, pos);
237 0 : break;
238 : }
239 : default:
240 : {
241 : /* Uh oh */
242 0 : return 0;
243 : }
244 : }
245 :
246 7 : return result;
247 : }
248 :
249 : pdf_off_t
250 : pdf_stm_be_tell (pdf_stm_be_t be)
251 2 : {
252 : pdf_off_t result;
253 :
254 2 : switch (be->type)
255 : {
256 : case PDF_STM_BE_MEM:
257 : {
258 1 : result = pdf_stm_be_mem_tell (be);
259 1 : break;
260 : }
261 : case PDF_STM_BE_FILE:
262 : {
263 1 : result = pdf_stm_be_file_tell (be);
264 1 : break;
265 : }
266 : case PDF_STM_BE_CFILE:
267 : {
268 0 : result = pdf_stm_be_cfile_tell (be);
269 0 : break;
270 : }
271 : default:
272 : {
273 : /* Uh oh */
274 0 : return 0;
275 : }
276 : }
277 :
278 2 : return result;
279 : }
280 :
281 : /*
282 : * Private functions
283 : */
284 :
285 : static pdf_size_t
286 : pdf_stm_be_mem_read (pdf_stm_be_t be,
287 : pdf_char_t *buffer,
288 : pdf_size_t bytes)
289 : {
290 : pdf_size_t free_bytes;
291 : pdf_size_t readed_bytes;
292 :
293 2537 : if ((bytes == 0) || (bytes < 0))
294 : {
295 0 : return 0;
296 : }
297 :
298 : /* How many bytes can we read from the buffer? */
299 2537 : free_bytes = be->data.mem.size - be->data.mem.pos;
300 2537 : if (bytes < free_bytes)
301 : {
302 77 : readed_bytes = bytes;
303 : }
304 : else
305 : {
306 2460 : readed_bytes = free_bytes;
307 : }
308 :
309 2537 : if (readed_bytes != 0)
310 : {
311 : /* Copy the data */
312 828 : memcpy (buffer,
313 : be->data.mem.buffer + be->data.mem.pos,
314 : readed_bytes);
315 :
316 828 : be->data.mem.pos += readed_bytes;
317 : }
318 :
319 : /* Ok, bye bye */
320 2537 : return readed_bytes;
321 : }
322 :
323 : static pdf_size_t
324 : pdf_stm_be_mem_write (pdf_stm_be_t be,
325 : pdf_char_t *buffer,
326 : pdf_size_t bytes)
327 : {
328 : pdf_size_t free_bytes;
329 : pdf_size_t written_bytes;
330 :
331 : /* Check boundaries of the buffer */
332 172 : if ((bytes == 0) || (bytes < 0))
333 : {
334 0 : return 0;
335 : }
336 :
337 : /* How many bytes can we write into the buffer? */
338 172 : free_bytes = be->data.mem.size - be->data.mem.pos;
339 172 : if (bytes < free_bytes)
340 : {
341 164 : written_bytes = bytes;
342 : }
343 : else
344 : {
345 8 : written_bytes = free_bytes;
346 : }
347 :
348 172 : if (written_bytes != 0)
349 : {
350 : /* Copy the data */
351 169 : memcpy (be->data.mem.buffer + be->data.mem.pos,
352 : buffer,
353 : written_bytes);
354 :
355 169 : be->data.mem.pos += written_bytes;
356 : }
357 :
358 : /* Ok, bye bye */
359 172 : return written_bytes;
360 : }
361 :
362 : static pdf_size_t
363 : pdf_stm_be_file_read (pdf_stm_be_t be,
364 : pdf_char_t *buffer,
365 : pdf_size_t bytes)
366 : {
367 : pdf_size_t readed_bytes;
368 : pdf_off_t current_pos;
369 : pdf_status_t ret;
370 :
371 : /* Seek in the file */
372 22 : pdf_fsys_file_get_pos (be->data.file.file,
373 : ¤t_pos);
374 22 : if (pdf_fsys_file_set_pos (be->data.file.file,
375 : be->data.file.pos) == PDF_ERROR)
376 : {
377 : /* Bad position */
378 0 : return 0;
379 : }
380 :
381 : /* Read the requested number of bytes */
382 22 : ret = pdf_fsys_file_read (be->data.file.file,
383 : buffer,
384 : bytes,
385 : &readed_bytes);
386 :
387 : /* Restore the file position and update the position of the
388 : stream */
389 22 : be->data.file.pos = be->data.file.pos + readed_bytes;
390 22 : if (pdf_fsys_file_set_pos (be->data.file.file,
391 : current_pos) == PDF_ERROR)
392 : {
393 : /* This should not happen, but just in case */
394 0 : return 0;
395 : }
396 :
397 22 : return readed_bytes;
398 : }
399 :
400 : static pdf_size_t
401 : pdf_stm_be_file_write (pdf_stm_be_t be,
402 : pdf_char_t *buffer,
403 : pdf_size_t bytes)
404 : {
405 : pdf_size_t written_bytes;
406 : pdf_off_t current_pos;
407 : pdf_status_t ret;
408 :
409 : /* Seek in the file */
410 2 : pdf_fsys_file_get_pos (be->data.file.file,
411 : ¤t_pos);
412 2 : if (pdf_fsys_file_set_pos (be->data.file.file,
413 : be->data.file.pos) == PDF_ERROR)
414 : {
415 : /* Bad position */
416 0 : return 0;
417 : }
418 :
419 : /* Write the requested number of bytes */
420 2 : ret = pdf_fsys_file_write (be->data.file.file,
421 : buffer,
422 : bytes,
423 : &written_bytes);
424 :
425 : /* Restore the file position and update the position of the
426 : stream */
427 2 : be->data.file.pos = be->data.file.pos + written_bytes;
428 2 : if (pdf_fsys_file_set_pos (be->data.file.file,
429 : current_pos) == PDF_ERROR)
430 : {
431 : /* This should not happen, but just in case */
432 0 : return 0;
433 : }
434 :
435 2 : return written_bytes;
436 : }
437 :
438 : static pdf_off_t
439 : pdf_stm_be_mem_seek (pdf_stm_be_t be,
440 : pdf_off_t pos)
441 : {
442 : /* Check the requested position */
443 4 : if (pos >= be->data.mem.size)
444 : {
445 1 : pos = be->data.mem.size - 1;
446 : }
447 4 : if (pos < 0)
448 : {
449 0 : pos = 0;
450 : }
451 :
452 : /* Move there */
453 4 : be->data.mem.pos = pos;
454 :
455 4 : return pos;
456 : }
457 :
458 : static pdf_off_t
459 : pdf_stm_be_mem_tell (pdf_stm_be_t be)
460 : {
461 1 : return be->data.mem.pos;
462 : }
463 :
464 : static pdf_off_t
465 : pdf_stm_be_file_seek (pdf_stm_be_t be,
466 : pdf_off_t pos)
467 : {
468 : pdf_size_t file_size;
469 :
470 3 : file_size = pdf_fsys_file_get_size (be->data.file.file);
471 :
472 : /* Check the requested position */
473 3 : if (pos < 0)
474 : {
475 0 : pos = 0;
476 : }
477 3 : if (pos >= file_size)
478 : {
479 1 : pos = file_size - 1;
480 : }
481 :
482 3 : be->data.file.pos = pos;
483 :
484 3 : return pos;
485 : }
486 :
487 : static pdf_off_t
488 : pdf_stm_be_file_tell (pdf_stm_be_t be)
489 : {
490 1 : return be->data.file.pos;
491 : }
492 :
493 : /* cfile backend implementation */
494 :
495 : static pdf_off_t
496 : pdf_stm_be_cfile_seek (pdf_stm_be_t be,
497 : pdf_off_t pos)
498 0 : {
499 : pdf_off_t max_pos;
500 :
501 0 : fseek (be->data.cfile.file, 0, SEEK_END);
502 0 : max_pos = ftello (be->data.cfile.file);
503 :
504 : /* Check the requested position */
505 0 : if (pos < 0)
506 : {
507 0 : pos = 0;
508 : }
509 0 : if (pos > max_pos)
510 : {
511 0 : pos = max_pos - 1;
512 : }
513 :
514 0 : be->data.cfile.pos = pos;
515 0 : fseeko (be->data.cfile.file,
516 : be->data.cfile.pos,
517 : SEEK_SET);
518 :
519 0 : return pos;
520 : }
521 :
522 : static pdf_off_t
523 : pdf_stm_be_cfile_tell (pdf_stm_be_t be)
524 : {
525 0 : return be->data.cfile.pos;
526 : }
527 :
528 : static pdf_size_t
529 : pdf_stm_be_cfile_read (pdf_stm_be_t be,
530 : pdf_char_t *buffer,
531 : pdf_size_t bytes)
532 : {
533 : pdf_size_t readed_bytes;
534 :
535 : /* Read the requested number of bytes */
536 0 : readed_bytes = fread (buffer,
537 : 1, bytes,
538 : be->data.cfile.file);
539 :
540 0 : return readed_bytes;
541 : }
542 :
543 : static pdf_size_t
544 : pdf_stm_be_cfile_write (pdf_stm_be_t be,
545 : pdf_char_t *buffer,
546 : pdf_size_t bytes)
547 : {
548 : pdf_size_t written_bytes;
549 :
550 : /* Write the requested number of bytes */
551 0 : written_bytes = fwrite (buffer,
552 : 1, bytes,
553 : be->data.cfile.file);
554 :
555 0 : return written_bytes;
556 : }
557 :
558 : /* End of pdf-stm-be.c */
|