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