1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * raptor_iostream.c - Raptor I/O-stream class for abstracting I/O
4 *
5 * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2004, University of Bristol, UK http://www.bristol.ac.uk/
7 *
8 * This package is Free Software and part of Redland http://librdf.org/
9 *
10 * It is licensed under the following three licenses as alternatives:
11 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12 * 2. GNU General Public License (GPL) V2 or any newer version
13 * 3. Apache License, V2.0 or any newer version
14 *
15 * You may not use this file except in compliance with at least one of
16 * the above three licenses.
17 *
18 * See LICENSE.html or LICENSE.txt at the top of this package for the
19 * complete terms and further detail along with the license texts for
20 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21 *
22 */
23
24
25 #ifdef HAVE_CONFIG_H
26 #include <raptor_config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <stdarg.h>
33
34 /* Raptor includes */
35 #include "raptor2.h"
36 #include "raptor_internal.h"
37
38
39 #ifndef STANDALONE
40
41 #define RAPTOR_IOSTREAM_MODE_READ 1
42 #define RAPTOR_IOSTREAM_MODE_WRITE 2
43
44 #define RAPTOR_IOSTREAM_FLAGS_EOF 1
45 #define RAPTOR_IOSTREAM_FLAGS_FREE_HANDLER 2
46
47 struct raptor_iostream_s
48 {
49 raptor_world *world;
50
51 void *user_data;
52 const raptor_iostream_handler* handler;
53 size_t offset;
54 unsigned int mode;
55 int flags;
56 };
57
58
59
60 /* prototypes for local functions */
61
62
63 static int
raptor_iostream_calculate_modes(const raptor_iostream_handler * const handler)64 raptor_iostream_calculate_modes(const raptor_iostream_handler * const handler)
65 {
66 int mode = 0;
67
68 /* API V1 checks */
69 if((handler->version >= 1) &&
70 handler->read_bytes)
71 mode |= RAPTOR_IOSTREAM_MODE_READ;
72
73 /* API V2 checks */
74 if((handler->version >= 2) &&
75 (handler->write_byte || handler->write_bytes))
76 mode |= RAPTOR_IOSTREAM_MODE_WRITE;
77
78 return mode;
79 }
80
81
82 /* Return non-0 if handler is legal and OK for given mode (if not 0 = ANY) */
83 static int
raptor_iostream_check_handler(const raptor_iostream_handler * const handler,unsigned int user_mode)84 raptor_iostream_check_handler(const raptor_iostream_handler * const handler,
85 unsigned int user_mode)
86 {
87 int mode;
88
89 if(handler->version < 1 || handler->version > 2)
90 return 0;
91
92 mode = raptor_iostream_calculate_modes(handler);
93 if(user_mode && !(user_mode & mode))
94 return 0;
95
96 return (mode != 0);
97 }
98
99
100 /**
101 * raptor_new_iostream_from_handler:
102 * @world: raptor_world object
103 * @user_data: pointer to context information to pass in to calls
104 * @handler: pointer to handler methods
105 *
106 * Create a new iostream over a user-defined handler
107 *
108 * Return value: new #raptor_iostream object or NULL on failure
109 **/
110 raptor_iostream*
raptor_new_iostream_from_handler(raptor_world * world,void * user_data,const raptor_iostream_handler * const handler)111 raptor_new_iostream_from_handler(raptor_world *world,
112 void *user_data,
113 const raptor_iostream_handler* const handler)
114 {
115 raptor_iostream* iostr;
116
117 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
118 RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(handler, raptor_iostream_handler, NULL);
119
120 raptor_world_open(world);
121
122 if(!raptor_iostream_check_handler(handler, 0))
123 return NULL;
124
125 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
126 if(!iostr)
127 return NULL;
128
129 iostr->world = world;
130 iostr->handler = handler;
131 iostr->user_data = (void*)user_data;
132 iostr->mode = raptor_iostream_calculate_modes(handler);
133
134 if(iostr->handler->init &&
135 iostr->handler->init(iostr->user_data)) {
136 RAPTOR_FREE(raptor_iostream, iostr);
137 return NULL;
138 }
139 return iostr;
140 }
141
142
143
144 /* Local handlers for reading/writing to/from a sink */
145
146 static int
raptor_sink_iostream_write_byte(void * user_data,const int byte)147 raptor_sink_iostream_write_byte(void *user_data, const int byte)
148 {
149 return 0;
150 }
151
152 static int
raptor_sink_iostream_write_bytes(void * user_data,const void * ptr,size_t size,size_t nmemb)153 raptor_sink_iostream_write_bytes(void *user_data, const void *ptr,
154 size_t size, size_t nmemb)
155 {
156 return RAPTOR_BAD_CAST(int, size * nmemb); /* success */
157 }
158
159 static int
raptor_sink_iostream_read_bytes(void * user_data,void * ptr,size_t size,size_t nmemb)160 raptor_sink_iostream_read_bytes(void *user_data, void *ptr,
161 size_t size, size_t nmemb)
162 {
163 return 0;
164 }
165
166 static int
raptor_sink_iostream_read_eof(void * user_data)167 raptor_sink_iostream_read_eof(void *user_data)
168 {
169 return 1; /* EOF always */
170 }
171
172 static const raptor_iostream_handler raptor_iostream_sink_handler = {
173 /* .version = */ 2,
174 /* .init = */ NULL,
175 /* .finish = */ NULL,
176 /* .write_byte = */ raptor_sink_iostream_write_byte,
177 /* .write_bytes = */ raptor_sink_iostream_write_bytes,
178 /* .write_end = */ NULL,
179 /* .read_bytes = */ raptor_sink_iostream_read_bytes,
180 /* .read_eof = */ raptor_sink_iostream_read_eof
181 };
182
183
184 /**
185 * raptor_new_iostream_to_sink:
186 * @world: raptor_world object
187 *
188 * Create a new write iostream to a sink, throwing away all data.
189 *
190 * Provides an that throw away all writes and returns end of input
191 * immediately on reads. Same as raptor_new_iostream_from_sink()
192 *
193 * Return value: new #raptor_iostream object or NULL on failure
194 **/
195 raptor_iostream*
raptor_new_iostream_to_sink(raptor_world * world)196 raptor_new_iostream_to_sink(raptor_world *world)
197 {
198 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
199
200 raptor_world_open(world);
201
202 return raptor_new_iostream_from_handler(world,
203 NULL, &raptor_iostream_sink_handler);
204 }
205
206
207 /* Local handlers for reading/writing from a filename */
208
209 static void
raptor_filename_iostream_finish(void * user_data)210 raptor_filename_iostream_finish(void *user_data)
211 {
212 FILE* handle = (FILE*)user_data;
213 fclose(handle);
214 }
215
216 static int
raptor_filename_iostream_write_byte(void * user_data,const int byte)217 raptor_filename_iostream_write_byte(void *user_data, const int byte)
218 {
219 FILE* handle = (FILE*)user_data;
220 return (fputc(byte, handle) == byte);
221 }
222
223 static int
raptor_filename_iostream_write_bytes(void * user_data,const void * ptr,size_t size,size_t nmemb)224 raptor_filename_iostream_write_bytes(void *user_data,
225 const void *ptr, size_t size, size_t nmemb)
226 {
227 FILE* handle = (FILE*)user_data;
228 return RAPTOR_BAD_CAST(int, fwrite(ptr, size, nmemb, handle));
229 }
230
231 static int
raptor_filename_iostream_write_end(void * user_data)232 raptor_filename_iostream_write_end(void *user_data)
233 {
234 FILE* handle = (FILE*)user_data;
235 return fclose(handle);
236 }
237
238 static int
raptor_filename_iostream_read_bytes(void * user_data,void * ptr,size_t size,size_t nmemb)239 raptor_filename_iostream_read_bytes(void *user_data,
240 void *ptr, size_t size, size_t nmemb)
241 {
242 FILE* handle = (FILE*)user_data;
243 return RAPTOR_BAD_CAST(int, fread(ptr, size, nmemb, handle));
244 }
245
246 static int
raptor_filename_iostream_read_eof(void * user_data)247 raptor_filename_iostream_read_eof(void *user_data)
248 {
249 FILE* handle = (FILE*)user_data;
250 return feof(handle);
251 }
252
253 static const raptor_iostream_handler raptor_iostream_write_filename_handler = {
254 /* .version = */ 2,
255 /* .init = */ NULL,
256 /* .finish = */ raptor_filename_iostream_finish,
257 /* .write_byte = */ raptor_filename_iostream_write_byte,
258 /* .write_bytes = */ raptor_filename_iostream_write_bytes,
259 /* .write_end = */ raptor_filename_iostream_write_end,
260 /* .read_bytes = */ NULL,
261 /* .read_eof = */ NULL
262 };
263
264
265 /**
266 * raptor_new_iostream_to_filename:
267 * @world: raptor world
268 * @filename: Output filename to open and write to
269 *
270 * Constructor - create a new iostream writing to a filename.
271 *
272 * Return value: new #raptor_iostream object or NULL on failure
273 **/
274 raptor_iostream*
raptor_new_iostream_to_filename(raptor_world * world,const char * filename)275 raptor_new_iostream_to_filename(raptor_world *world, const char *filename)
276 {
277 FILE *handle;
278 raptor_iostream* iostr;
279 const raptor_iostream_handler* handler;
280 const unsigned int mode = RAPTOR_IOSTREAM_MODE_WRITE;
281
282 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
283
284 raptor_world_open(world);
285
286 if(!filename)
287 return NULL;
288
289 handler = &raptor_iostream_write_filename_handler;
290 if(!raptor_iostream_check_handler(handler, mode))
291 return NULL;
292
293 handle = fopen(filename, "wb");
294 if(!handle)
295 return NULL;
296
297 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
298 if(!iostr) {
299 fclose(handle);
300 return NULL;
301 }
302
303 iostr->world = world;
304 iostr->handler = handler;
305 iostr->user_data = (void*)handle;
306 iostr->mode = mode;
307
308 if(iostr->handler->init &&
309 iostr->handler->init(iostr->user_data)) {
310 raptor_free_iostream(iostr);
311 return NULL;
312 }
313 return iostr;
314 }
315
316
317 static const raptor_iostream_handler raptor_iostream_write_file_handler = {
318 /* .version = */ 2,
319 /* .init = */ NULL,
320 /* .finish = */ NULL,
321 /* .write_byte = */ raptor_filename_iostream_write_byte,
322 /* .write_bytes = */ raptor_filename_iostream_write_bytes,
323 /* .write_end = */ NULL,
324 /* .read_bytes = */ NULL,
325 /* .read_eof = */ NULL
326 };
327
328
329 /**
330 * raptor_new_iostream_to_file_handle:
331 * @world: raptor world
332 * @handle: FILE* handle to write to
333 *
334 * Constructor - create a new iostream writing to a FILE*.
335 *
336 * The @handle must already be open for writing.
337 * NOTE: This does not fclose the @handle when it is finished.
338 *
339 * Return value: new #raptor_iostream object or NULL on failure
340 **/
341 raptor_iostream*
raptor_new_iostream_to_file_handle(raptor_world * world,FILE * handle)342 raptor_new_iostream_to_file_handle(raptor_world *world, FILE *handle)
343 {
344 raptor_iostream* iostr;
345 const raptor_iostream_handler* handler;
346 const unsigned int mode = RAPTOR_IOSTREAM_MODE_WRITE;
347
348 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
349
350 raptor_world_open(world);
351
352 if(!handle)
353 return NULL;
354
355 handler = &raptor_iostream_write_file_handler;
356 if(!raptor_iostream_check_handler(handler, mode))
357 return NULL;
358
359 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
360 if(!iostr)
361 return NULL;
362
363 iostr->world = world;
364 iostr->handler = handler;
365 iostr->user_data = (void*)handle;
366 iostr->mode = mode;
367
368 if(iostr->handler->init && iostr->handler->init(iostr->user_data)) {
369 RAPTOR_FREE(raptor_iostream, iostr);
370 return NULL;
371 }
372 return iostr;
373 }
374
375
376
377 struct raptor_write_string_iostream_context {
378 raptor_stringbuffer *sb;
379 void *(*malloc_handler)(size_t size);
380 void **string_p;
381 size_t *length_p;
382 };
383
384
385 /* Local handlers for writing to a string */
386
387 static void
raptor_write_string_iostream_finish(void * user_data)388 raptor_write_string_iostream_finish(void *user_data)
389 {
390 struct raptor_write_string_iostream_context* con;
391 size_t len;
392 void *str = NULL;
393
394 con = (struct raptor_write_string_iostream_context*)user_data;
395 len = raptor_stringbuffer_length(con->sb);
396
397 *con->string_p = NULL;
398 if(con->length_p)
399 *con->length_p = len;
400
401 str = (void*)con->malloc_handler(len+1);
402 if(str) {
403 if(len)
404 raptor_stringbuffer_copy_to_string(con->sb, (unsigned char*)str, len+1);
405 else
406 *(char*)str='\0';
407 *con->string_p = str;
408 }
409
410 if(!str && con->length_p)
411 *con->length_p = 0;
412
413 raptor_free_stringbuffer(con->sb);
414 RAPTOR_FREE(raptor_write_string_iostream_context, con);
415 return;
416 }
417
418 static int
raptor_write_string_iostream_write_byte(void * user_data,const int byte)419 raptor_write_string_iostream_write_byte(void *user_data, const int byte)
420 {
421 struct raptor_write_string_iostream_context* con;
422 unsigned char buf = (unsigned char)byte;
423
424 con = (struct raptor_write_string_iostream_context*)user_data;
425 return raptor_stringbuffer_append_counted_string(con->sb, &buf, 1, 1);
426 }
427
428
429 static int
raptor_write_string_iostream_write_bytes(void * user_data,const void * ptr,size_t size,size_t nmemb)430 raptor_write_string_iostream_write_bytes(void *user_data, const void *ptr,
431 size_t size, size_t nmemb)
432 {
433 struct raptor_write_string_iostream_context* con;
434
435 con = (struct raptor_write_string_iostream_context*)user_data;
436 if(raptor_stringbuffer_append_counted_string(con->sb,
437 (const unsigned char*)ptr, size * nmemb, 1))
438 return 0; /* failure */
439 return RAPTOR_BAD_CAST(int, size * nmemb); /* success */
440 }
441
442 static const raptor_iostream_handler raptor_iostream_write_string_handler = {
443 /* .version = */ 2,
444 /* .init = */ NULL,
445 /* .finish = */ raptor_write_string_iostream_finish,
446 /* .write_byte = */ raptor_write_string_iostream_write_byte,
447 /* .write_bytes = */ raptor_write_string_iostream_write_bytes,
448 /* .write_end = */ NULL,
449 /* .read_bytes = */ NULL,
450 /* .read_eof = */ NULL
451 };
452
453
454 /**
455 * raptor_new_iostream_to_string:
456 * @world: raptor world
457 * @string_p: pointer to location to hold string
458 * @length_p: pointer to location to hold length of string (or NULL)
459 * @malloc_handler: pointer to malloc() to use to make string (or NULL)
460 *
461 * Constructor - create a new iostream writing to a string.
462 *
463 * If @malloc_handler is null, raptor will allocate it using it's
464 * own memory allocator. *@string_p is set to NULL on failure (and
465 * *@length_p to 0 if @length_p is not NULL).
466 *
467 * Return value: new #raptor_iostream object or NULL on failure
468 **/
469 RAPTOR_EXTERN_C
470 raptor_iostream*
raptor_new_iostream_to_string(raptor_world * world,void ** string_p,size_t * length_p,raptor_data_malloc_handler const malloc_handler)471 raptor_new_iostream_to_string(raptor_world *world,
472 void **string_p, size_t *length_p,
473 raptor_data_malloc_handler const malloc_handler)
474 {
475 raptor_iostream* iostr;
476 struct raptor_write_string_iostream_context* con;
477 const raptor_iostream_handler* handler;
478 const unsigned int mode = RAPTOR_IOSTREAM_MODE_WRITE;
479
480 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
481
482 if(!string_p)
483 return NULL;
484
485 raptor_world_open(world);
486
487 handler = &raptor_iostream_write_string_handler;
488 if(!raptor_iostream_check_handler(handler, mode))
489 return NULL;
490
491 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
492 if(!iostr)
493 return NULL;
494
495 con = RAPTOR_CALLOC(struct raptor_write_string_iostream_context*, 1,
496 sizeof(*con));
497 if(!con) {
498 RAPTOR_FREE(raptor_iostream, iostr);
499 return NULL;
500 }
501
502 con->sb = raptor_new_stringbuffer();
503 if(!con->sb) {
504 RAPTOR_FREE(raptor_iostream, iostr);
505 RAPTOR_FREE(raptor_write_string_iostream_context, con);
506 return NULL;
507 }
508
509 con->string_p = string_p;
510 *string_p = NULL;
511
512 con->length_p = length_p;
513 if(length_p)
514 *length_p = 0;
515
516 if(malloc_handler)
517 con->malloc_handler = malloc_handler;
518 else
519 con->malloc_handler = raptor_alloc_memory;
520
521 iostr->world = world;
522 iostr->handler = handler;
523 iostr->user_data = (void*)con;
524 iostr->mode = mode;
525
526 if(iostr->handler->init && iostr->handler->init(iostr->user_data)) {
527 raptor_free_iostream(iostr);
528 return NULL;
529 }
530 return iostr;
531 }
532
533
534 /**
535 * raptor_new_iostream_from_sink:
536 * @world: raptor world
537 *
538 * Create a new read iostream from a sink, returning no data.
539 *
540 * Provides an I/O source that returns end of input immediately on
541 * reads, and throw away all writes. Same as
542 * raptor_new_iostream_to_sink()
543 *
544 * Return value: new #raptor_iostream object or NULL on failure
545 **/
546 raptor_iostream*
raptor_new_iostream_from_sink(raptor_world * world)547 raptor_new_iostream_from_sink(raptor_world *world)
548 {
549 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
550
551 raptor_world_open(world);
552
553 return raptor_new_iostream_from_handler(world, NULL,
554 &raptor_iostream_sink_handler);
555 }
556
557
558 static const raptor_iostream_handler raptor_iostream_read_filename_handler = {
559 /* .version = */ 2,
560 /* .init = */ NULL,
561 /* .finish = */ raptor_filename_iostream_finish,
562 /* .write_byte = */ NULL,
563 /* .write_bytes = */ NULL,
564 /* .write_end = */ NULL,
565 /* .read_bytes = */ raptor_filename_iostream_read_bytes,
566 /* .read_eof = */ raptor_filename_iostream_read_eof
567 };
568
569
570 /**
571 * raptor_new_iostream_from_filename:
572 * @world: raptor world
573 * @filename: Input filename to open and read from
574 *
575 * Constructor - create a new iostream reading from a filename.
576 *
577 * Return value: new #raptor_iostream object or NULL on failure
578 **/
579 raptor_iostream*
raptor_new_iostream_from_filename(raptor_world * world,const char * filename)580 raptor_new_iostream_from_filename(raptor_world *world, const char *filename)
581 {
582 FILE *handle;
583 raptor_iostream* iostr;
584 const raptor_iostream_handler* handler;
585 const unsigned int mode = RAPTOR_IOSTREAM_MODE_READ;
586
587 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
588
589 if(!filename)
590 return NULL;
591
592 raptor_world_open(world);
593
594 handler = &raptor_iostream_read_filename_handler;
595 if(!raptor_iostream_check_handler(handler, mode))
596 return NULL;
597
598 handle = fopen(filename, "rb");
599 if(!handle)
600 return NULL;
601
602 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
603 if(!iostr) {
604 fclose(handle);
605 return NULL;
606 }
607
608 iostr->world = world;
609 iostr->handler = handler;
610 iostr->user_data = (void*)handle;
611 iostr->mode = mode;
612
613 if(iostr->handler->init &&
614 iostr->handler->init(iostr->user_data)) {
615 raptor_free_iostream(iostr);
616 return NULL;
617 }
618 return iostr;
619 }
620
621
622 static const raptor_iostream_handler raptor_iostream_read_file_handle_handler = {
623 /* .version = */ 2,
624 /* .init = */ NULL,
625 /* .finish = */ NULL,
626 /* .write_byte = */ NULL,
627 /* .write_bytes = */ NULL,
628 /* .write_end = */ NULL,
629 /* .read_bytes = */ raptor_filename_iostream_read_bytes,
630 /* .read_eof = */ raptor_filename_iostream_read_eof
631 };
632
633
634 /**
635 * raptor_new_iostream_from_file_handle:
636 * @world: raptor world
637 * @handle: Input file_handle to open and read from
638 *
639 * Constructor - create a new iostream reading from a file_handle.
640 *
641 * The @handle must already be open for reading.
642 * NOTE: This does not fclose the @handle when it is finished.
643 *
644 * Return value: new #raptor_iostream object or NULL on failure
645 **/
646 raptor_iostream*
raptor_new_iostream_from_file_handle(raptor_world * world,FILE * handle)647 raptor_new_iostream_from_file_handle(raptor_world *world, FILE *handle)
648 {
649 raptor_iostream* iostr;
650 const raptor_iostream_handler* handler;
651 const unsigned int mode = RAPTOR_IOSTREAM_MODE_READ;
652
653 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
654
655 if(!handle)
656 return NULL;
657
658 raptor_world_open(world);
659
660 handler = &raptor_iostream_read_file_handle_handler;
661 if(!raptor_iostream_check_handler(handler, mode))
662 return NULL;
663
664 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
665 if(!iostr)
666 return NULL;
667
668 iostr->world = world;
669 iostr->handler = handler;
670 iostr->user_data = (void*)handle;
671 iostr->mode = mode;
672
673 if(iostr->handler->init &&
674 iostr->handler->init(iostr->user_data)) {
675 RAPTOR_FREE(raptor_iostream, iostr);
676 return NULL;
677 }
678 return iostr;
679 }
680
681
682 /**
683 * raptor_free_iostream:
684 * @iostr: iostream object
685 *
686 * Destructor - destroy an iostream.
687 **/
688 void
raptor_free_iostream(raptor_iostream * iostr)689 raptor_free_iostream(raptor_iostream *iostr)
690 {
691 if(!iostr)
692 return;
693
694 if(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF)
695 raptor_iostream_write_end(iostr);
696
697 if(iostr->handler->finish)
698 iostr->handler->finish(iostr->user_data);
699
700 if((iostr->flags & RAPTOR_IOSTREAM_FLAGS_FREE_HANDLER))
701 RAPTOR_FREE(raptor_iostream_handler, iostr->handler);
702
703 RAPTOR_FREE(raptor_iostream, iostr);
704 }
705
706
707
708 /**
709 * raptor_iostream_write_byte:
710 * @byte: byte to write
711 * @iostr: raptor iostream
712 *
713 * Write a byte to the iostream.
714 *
715 * Return value: non-0 on failure
716 **/
717 int
raptor_iostream_write_byte(const int byte,raptor_iostream * iostr)718 raptor_iostream_write_byte(const int byte, raptor_iostream *iostr)
719 {
720 iostr->offset++;
721
722 if(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF)
723 return 1;
724 if(!iostr->handler->write_byte)
725 return 1;
726 if(!(iostr->mode & RAPTOR_IOSTREAM_MODE_WRITE))
727 return 1;
728 return iostr->handler->write_byte(iostr->user_data, byte);
729 }
730
731
732 /**
733 * raptor_iostream_write_bytes:
734 * @ptr: start of objects to write
735 * @size: size of object
736 * @nmemb: number of objects
737 * @iostr: raptor iostream
738 *
739 * Write bytes to the iostream.
740 *
741 * Return value: number of objects actually written, which may be less than nmemb. <0 on failure
742 **/
743 int
raptor_iostream_write_bytes(const void * ptr,size_t size,size_t nmemb,raptor_iostream * iostr)744 raptor_iostream_write_bytes(const void *ptr, size_t size, size_t nmemb,
745 raptor_iostream *iostr)
746 {
747 int nobj;
748
749 if(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF)
750 return -1;
751 if(!iostr->handler->write_bytes)
752 return -1;
753 if(!(iostr->mode & RAPTOR_IOSTREAM_MODE_WRITE))
754 return -1;
755
756 nobj = iostr->handler->write_bytes(iostr->user_data, ptr, size, nmemb);
757 if(nobj > 0)
758 iostr->offset += (size * nobj);
759
760 return nobj;
761 }
762
763
764 /**
765 * raptor_iostream_string_write:
766 * @string: string
767 * @iostr: raptor iostream
768 *
769 * Write a NULL-terminated string to the iostream.
770 *
771 * Return value: non-0 on failure
772 **/
773 int
raptor_iostream_string_write(const void * string,raptor_iostream * iostr)774 raptor_iostream_string_write(const void *string, raptor_iostream *iostr)
775 {
776 size_t len = strlen((const char*)string);
777 int nobj = raptor_iostream_write_bytes(string, 1, len, iostr);
778 return (RAPTOR_BAD_CAST(size_t, nobj) != len);
779 }
780
781
782 /**
783 * raptor_iostream_counted_string_write:
784 * @string: string
785 * @len: string length
786 * @iostr: raptor iostream
787 *
788 * Write a counted string to the iostream.
789 *
790 * Return value: non-0 on failure
791 **/
792 int
raptor_iostream_counted_string_write(const void * string,size_t len,raptor_iostream * iostr)793 raptor_iostream_counted_string_write(const void *string, size_t len,
794 raptor_iostream *iostr)
795 {
796 int nobj = raptor_iostream_write_bytes(string, 1, len, iostr);
797 return (RAPTOR_BAD_CAST(size_t, nobj) != len);
798 }
799
800
801 /**
802 * raptor_uri_write:
803 * @uri: URI
804 * @iostr: raptor iostream
805 *
806 * Write a raptor URI to the iostream.
807 *
808 * Return value: non-0 on failure
809 **/
810 int
raptor_uri_write(raptor_uri * uri,raptor_iostream * iostr)811 raptor_uri_write(raptor_uri* uri, raptor_iostream* iostr)
812 {
813 size_t len;
814 const void *string = raptor_uri_as_counted_string(uri, &len);
815 int nobj = raptor_iostream_write_bytes(string, 1, len, iostr);
816 return (RAPTOR_BAD_CAST(size_t, nobj) != len);
817 }
818
819
820 /**
821 * raptor_iostream_write_end:
822 * @iostr: raptor iostream
823 *
824 * End writing to the iostream.
825 *
826 * Return value: non-0 on failure
827 **/
828 int
raptor_iostream_write_end(raptor_iostream * iostr)829 raptor_iostream_write_end(raptor_iostream *iostr)
830 {
831 int rc = 0;
832
833 if(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF)
834 return 1;
835 if(iostr->handler->write_end)
836 rc = iostr->handler->write_end(iostr->user_data);
837 iostr->flags |= RAPTOR_IOSTREAM_FLAGS_EOF;
838
839 return rc;
840 }
841
842
843 /**
844 * raptor_stringbuffer_write:
845 * @sb: #raptor_stringbuffer to write
846 * @iostr: raptor iostream
847 *
848 * Write a stringbuffer to an iostream.
849 *
850 * Return value: non-0 on failure
851 **/
852 int
raptor_stringbuffer_write(raptor_stringbuffer * sb,raptor_iostream * iostr)853 raptor_stringbuffer_write(raptor_stringbuffer *sb, raptor_iostream* iostr)
854 {
855 size_t length;
856 if(!sb)
857 return 1;
858
859 length = raptor_stringbuffer_length(sb);
860 if(length) {
861 int nobj = raptor_iostream_write_bytes(raptor_stringbuffer_as_string(sb),
862 1, length, iostr);
863 return (RAPTOR_BAD_CAST(size_t, nobj) != length);
864 } else
865 return 0;
866 }
867
868
869 /**
870 * raptor_iostream_decimal_write:
871 * @integer: integer to format as decimal
872 * @iostr: raptor iostream
873 *
874 * Write an integer in decimal to the iostream.
875 *
876 * Return value: non-0 on failure
877 **/
878 int
raptor_iostream_decimal_write(int integer,raptor_iostream * iostr)879 raptor_iostream_decimal_write(int integer, raptor_iostream* iostr)
880 {
881 /* enough for 64 bit signed integer
882 * INT64_MAX is 9223372036854775807 (19 digits) + 1 for sign
883 */
884 unsigned char buf[20];
885 unsigned char *p;
886 int i = integer;
887 size_t length = 1;
888 int nobj;
889
890 if(integer < 0) {
891 length++;
892 i= -integer;
893 }
894 while(i /= 10)
895 length++;
896
897 p = buf+length-1;
898 i = integer;
899 if(i < 0)
900 i= -i;
901 do {
902 *p-- ='0'+(i %10);
903 i /= 10;
904 } while(i);
905 if(integer < 0)
906 *p= '-';
907
908 nobj = raptor_iostream_write_bytes(buf, 1, length, iostr);
909 return (RAPTOR_BAD_CAST(size_t, nobj) != length);
910 }
911
912
913 /**
914 * raptor_iostream_hexadecimal_write:
915 * @integer: unsigned integer to format as hexadecimal
916 * @width: field width
917 * @iostr: raptor iostream
918 *
919 * Write an integer in hexadecimal to the iostream.
920 *
921 * Always 0-fills the entire field and writes in uppercase A-F
922 *
923 * Return value: non-0 on failure
924 **/
925 int
raptor_iostream_hexadecimal_write(unsigned int integer,int width,raptor_iostream * iostr)926 raptor_iostream_hexadecimal_write(unsigned int integer, int width,
927 raptor_iostream* iostr)
928 {
929 char *buf;
930 int nobj;
931
932 if(width < 1)
933 return 1;
934
935 buf = RAPTOR_MALLOC(char*, width + 1);
936 if(!buf)
937 return 1;
938
939 (void)raptor_format_integer(buf, width + 1, integer, /* base */ 16,
940 width, '0');
941
942 nobj = raptor_iostream_write_bytes(buf, 1, width, iostr);
943 RAPTOR_FREE(char*, buf);
944 return (nobj != width);
945 }
946
947
948
949 /**
950 * raptor_iostream_read_bytes:
951 * @ptr: start of buffer to read objects into
952 * @size: size of object
953 * @nmemb: number of objects to read
954 * @iostr: raptor iostream
955 *
956 * Read bytes to the iostream.
957 *
958 * Return value: number of objects read, 0 or less than nmemb on EOF, <0 on failure
959 **/
960 int
raptor_iostream_read_bytes(void * ptr,size_t size,size_t nmemb,raptor_iostream * iostr)961 raptor_iostream_read_bytes(void *ptr, size_t size, size_t nmemb,
962 raptor_iostream *iostr)
963 {
964 int count;
965
966 if(!(iostr->mode & RAPTOR_IOSTREAM_MODE_READ))
967 return -1;
968
969 if(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF)
970 return 0;
971
972 if(!iostr->handler->read_bytes)
973 count= -1;
974 else
975 count = iostr->handler->read_bytes(iostr->user_data, ptr, size, nmemb);
976
977 if(count > 0)
978 iostr->offset += (size*count);
979
980 if(RAPTOR_BAD_CAST(size_t, count) < nmemb)
981 iostr->flags |= RAPTOR_IOSTREAM_FLAGS_EOF;
982
983 return count;
984 }
985
986
987 /**
988 * raptor_iostream_read_eof:
989 * @iostr: raptor read iostream
990 *
991 * Check if an read iostream has ended
992 *
993 * Return value: non-0 if EOF (or not a read iostream)
994 **/
995 int
raptor_iostream_read_eof(raptor_iostream * iostr)996 raptor_iostream_read_eof(raptor_iostream *iostr)
997 {
998 /* Streams without read are always EOF */
999 if(!(iostr->mode & RAPTOR_IOSTREAM_MODE_READ))
1000 return 1;
1001
1002 if(!(iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF) &&
1003 iostr->handler->read_eof &&
1004 iostr->handler->read_eof(iostr->user_data))
1005 iostr->flags |= RAPTOR_IOSTREAM_FLAGS_EOF;
1006
1007 return ((iostr->flags & RAPTOR_IOSTREAM_FLAGS_EOF) != 0);
1008 }
1009
1010
1011 struct raptor_read_string_iostream_context {
1012 /* input buffer */
1013 void* string;
1014 size_t length;
1015 /* pointer into buffer */
1016 size_t offset;
1017 };
1018
1019
1020 /* Local handlers for reading from a string */
1021
1022 static void
raptor_read_string_iostream_finish(void * user_data)1023 raptor_read_string_iostream_finish(void *user_data)
1024 {
1025 struct raptor_read_string_iostream_context* con;
1026
1027 con = (struct raptor_read_string_iostream_context*)user_data;
1028 RAPTOR_FREE(raptor_read_string_iostream_context, con);
1029 return;
1030 }
1031
1032 static int
raptor_read_string_iostream_read_bytes(void * user_data,void * ptr,size_t size,size_t nmemb)1033 raptor_read_string_iostream_read_bytes(void *user_data, void *ptr,
1034 size_t size, size_t nmemb)
1035 {
1036 struct raptor_read_string_iostream_context* con;
1037 size_t avail;
1038 size_t blen;
1039
1040 if(!ptr || size <= 0 || !nmemb)
1041 return -1;
1042
1043 con = (struct raptor_read_string_iostream_context*)user_data;
1044 if(con->offset >= con->length)
1045 return 0;
1046
1047 avail = (con->length - con->offset) / size;
1048 if(avail > nmemb)
1049 avail = nmemb;
1050 blen = (avail * size);
1051 memcpy(ptr, (char*)con->string + con->offset, blen);
1052 con->offset += blen;
1053
1054 return RAPTOR_BAD_CAST(int, avail);
1055 }
1056
1057 static int
raptor_read_string_iostream_read_eof(void * user_data)1058 raptor_read_string_iostream_read_eof(void *user_data)
1059 {
1060 struct raptor_read_string_iostream_context* con;
1061
1062 con = (struct raptor_read_string_iostream_context*)user_data;
1063 return (con->offset >= con->length);
1064 }
1065
1066
1067 static const raptor_iostream_handler raptor_iostream_read_string_handler = {
1068 /* .version = */ 2,
1069 /* .init = */ NULL,
1070 /* .finish = */ raptor_read_string_iostream_finish,
1071 /* .write_byte = */ NULL,
1072 /* .write_bytes = */ NULL,
1073 /* .write_end = */ NULL,
1074 /* .read_bytes = */ raptor_read_string_iostream_read_bytes,
1075 /* .read_eof = */ raptor_read_string_iostream_read_eof
1076 };
1077
1078
1079 /**
1080 * raptor_new_iostream_from_string:
1081 * @world: raptor world
1082 * @string: pointer to string
1083 * @length: length of string
1084 *
1085 * Constructor - create a new iostream reading from a string.
1086 *
1087 * Return value: new #raptor_iostream object or NULL on failure
1088 **/
1089 raptor_iostream*
raptor_new_iostream_from_string(raptor_world * world,void * string,size_t length)1090 raptor_new_iostream_from_string(raptor_world *world,
1091 void *string, size_t length)
1092 {
1093 raptor_iostream* iostr;
1094 struct raptor_read_string_iostream_context* con;
1095 const raptor_iostream_handler* handler;
1096 const unsigned int mode = RAPTOR_IOSTREAM_MODE_READ;
1097
1098 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
1099
1100 if(!string)
1101 return NULL;
1102
1103 raptor_world_open(world);
1104
1105 handler = &raptor_iostream_read_string_handler;
1106 if(!raptor_iostream_check_handler(handler, mode))
1107 return NULL;
1108
1109 iostr = RAPTOR_CALLOC(raptor_iostream*, 1, sizeof(*iostr));
1110 if(!iostr)
1111 return NULL;
1112
1113 con = RAPTOR_CALLOC(struct raptor_read_string_iostream_context*, 1,
1114 sizeof(*con));
1115 if(!con) {
1116 RAPTOR_FREE(raptor_iostream, iostr);
1117 return NULL;
1118 }
1119
1120 con->string = string;
1121 con->length = length;
1122
1123 iostr->world = world;
1124 iostr->handler = handler;
1125 iostr->user_data = (void*)con;
1126 iostr->mode = mode;
1127
1128 if(iostr->handler->init && iostr->handler->init(iostr->user_data)) {
1129 raptor_free_iostream(iostr);
1130 return NULL;
1131 }
1132 return iostr;
1133 }
1134
1135
1136 /**
1137 * raptor_iostream_tell:
1138 * @iostr: raptor iostream
1139 *
1140 * Get the offset in the iostream.
1141 *
1142 * Return value: offset in iostream
1143 **/
1144 unsigned long
raptor_iostream_tell(raptor_iostream * iostr)1145 raptor_iostream_tell(raptor_iostream *iostr)
1146 {
1147 return RAPTOR_BAD_CAST(unsigned long, iostr->offset);
1148 }
1149
1150
1151 /* internal */
1152 raptor_world*
raptor_iostream_get_world(raptor_iostream * iostr)1153 raptor_iostream_get_world(raptor_iostream *iostr)
1154 {
1155 return iostr->world;
1156 }
1157
1158
1159 #endif
1160
1161
1162
1163 #ifdef STANDALONE
1164
1165 /* one more prototype */
1166 int main(int argc, char *argv[]);
1167
1168
1169 static const char *program;
1170
1171 #define READ_BUFFER_SIZE 256
1172
1173
1174 static int
test_write_to_filename(raptor_world * world,const char * filename,const char * test_string,size_t test_string_len,const unsigned int expected_bytes_count)1175 test_write_to_filename(raptor_world *world, const char* filename,
1176 const char* test_string, size_t test_string_len,
1177 const unsigned int expected_bytes_count)
1178 {
1179 raptor_iostream *iostr = NULL;
1180 unsigned long count;
1181 int rc = 0;
1182 const char* const label="write iostream to filename";
1183
1184 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1185 fprintf(stderr, "%s: Testing %s '%s'\n", program, label, filename);
1186 #endif
1187
1188 iostr = raptor_new_iostream_to_filename(world, filename);
1189 if(!iostr) {
1190 fprintf(stderr, "%s: Failed to create %s '%s'\n", program, label, filename);
1191 rc = 1;
1192 goto tidy;
1193 }
1194
1195 raptor_iostream_write_bytes(test_string, 1, test_string_len, iostr);
1196 raptor_iostream_write_byte('\n', iostr);
1197
1198 count = raptor_iostream_tell(iostr);
1199 if(count != expected_bytes_count) {
1200 fprintf(stderr, "%s: %s wrote %d bytes, expected %d\n", program, label,
1201 (int)count, expected_bytes_count);
1202 rc = 1;
1203 goto tidy;
1204 }
1205
1206 tidy:
1207 if(iostr)
1208 raptor_free_iostream(iostr);
1209 remove(filename);
1210
1211 if(rc)
1212 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1213
1214 return rc;
1215 }
1216
1217
1218 static int
test_write_to_file_handle(raptor_world * world,FILE * handle,const char * test_string,size_t test_string_len,const unsigned int expected_bytes_count)1219 test_write_to_file_handle(raptor_world *world, FILE* handle,
1220 const char* test_string, size_t test_string_len,
1221 const unsigned int expected_bytes_count)
1222 {
1223 raptor_iostream *iostr = NULL;
1224 unsigned long count;
1225 int rc = 0;
1226 const char* const label="write iostream to file handle";
1227
1228 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1229 fprintf(stderr, "%s: Testing %s\n", program, label);
1230 #endif
1231
1232 iostr = raptor_new_iostream_to_file_handle(world, handle);
1233 if(!iostr) {
1234 fprintf(stderr, "%s: Failed to create %s\n", program, label);
1235 rc = 1;
1236 goto tidy;
1237 }
1238
1239 raptor_iostream_write_bytes(test_string, 1, test_string_len, iostr);
1240 raptor_iostream_write_byte('\n', iostr);
1241
1242 count = raptor_iostream_tell(iostr);
1243 if(count != expected_bytes_count) {
1244 fprintf(stderr, "%s: %s wrote %d bytes, expected %d\n", program, label,
1245 (int)count, expected_bytes_count);
1246 rc = 1;
1247 }
1248
1249 tidy:
1250 if(iostr)
1251 raptor_free_iostream(iostr);
1252
1253 if(rc)
1254 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1255
1256 return rc;
1257 }
1258
1259
1260 static int
test_write_to_string(raptor_world * world,const char * test_string,size_t test_string_len,const unsigned int expected_bytes_count)1261 test_write_to_string(raptor_world *world,
1262 const char* test_string, size_t test_string_len,
1263 const unsigned int expected_bytes_count)
1264 {
1265 raptor_iostream *iostr = NULL;
1266 unsigned long count;
1267 int rc = 0;
1268 void *string = NULL;
1269 size_t string_len;
1270 const char* const label="write iostream to a string";
1271
1272
1273 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1274 fprintf(stderr, "%s: Testing %s\n", program, label);
1275 #endif
1276
1277 iostr = raptor_new_iostream_to_string(world, &string, &string_len, NULL);
1278 if(!iostr) {
1279 fprintf(stderr, "%s: Failed to create write iostream to string\n",
1280 program);
1281 rc = 1;
1282 goto tidy;
1283 }
1284
1285 raptor_iostream_write_bytes(test_string, 1, test_string_len, iostr);
1286 raptor_iostream_write_byte('\n', iostr);
1287
1288 count = raptor_iostream_tell(iostr);
1289 if(count != expected_bytes_count) {
1290 fprintf(stderr, "%s: %s wrote %d bytes, expected %d\n", program, label,
1291 (int)count, expected_bytes_count);
1292 rc = 1;
1293 }
1294
1295 raptor_free_iostream(iostr); iostr = NULL;
1296
1297 if(!string) {
1298 fprintf(stderr, "%s: %s failed to create a string\n", program, label);
1299 return 1;
1300 }
1301 if(string_len != count) {
1302 fprintf(stderr, "%s: %s created a string length %d, expected %d\n",
1303 program, label, (int)string_len, (int)count);
1304 return 1;
1305 }
1306
1307 tidy:
1308 if(string)
1309 raptor_free_memory(string);
1310 if(iostr)
1311 raptor_free_iostream(iostr);
1312
1313 if(rc)
1314 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1315
1316 return rc;
1317 }
1318
1319
1320 static int
test_write_to_sink(raptor_world * world,const char * test_string,size_t test_string_len,const unsigned int expected_bytes_count)1321 test_write_to_sink(raptor_world *world,
1322 const char* test_string, size_t test_string_len,
1323 const unsigned int expected_bytes_count)
1324 {
1325 raptor_iostream *iostr = NULL;
1326 unsigned long count;
1327 int rc = 0;
1328 const char* const label="write iostream to sink";
1329
1330 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1331 fprintf(stderr, "%s: Testing %s\n", program, label);
1332 #endif
1333
1334 iostr = raptor_new_iostream_to_sink(world);
1335 if(!iostr) {
1336 fprintf(stderr, "%s: Failed to create %s\n", program, label);
1337 rc = 1;
1338 goto tidy;
1339 }
1340
1341 raptor_iostream_write_bytes(test_string, 1, test_string_len, iostr);
1342 raptor_iostream_write_byte('\n', iostr);
1343
1344 count = raptor_iostream_tell(iostr);
1345 if(count != expected_bytes_count) {
1346 fprintf(stderr, "%s: %s wrote %d bytes, expected %d\n", program, label,
1347 (int)count, expected_bytes_count);
1348 rc = 1;
1349 }
1350
1351 tidy:
1352 if(iostr)
1353 raptor_free_iostream(iostr);
1354
1355 if(rc)
1356 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1357
1358 return rc;
1359 }
1360
1361
1362 static int
test_read_from_filename(raptor_world * world,const char * filename,const char * test_string,size_t test_string_len,const int expected_len,const int expected_len2)1363 test_read_from_filename(raptor_world *world,
1364 const char* filename,
1365 const char* test_string, size_t test_string_len,
1366 const int expected_len,
1367 const int expected_len2)
1368 {
1369 raptor_iostream *iostr = NULL;
1370 char buffer[READ_BUFFER_SIZE];
1371 int count;
1372 int rc = 0;
1373 const char* const label="read iostream from filename";
1374
1375 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1376 fprintf(stderr, "%s: Testing %s '%s'\n", program, label, filename);
1377 #endif
1378
1379 iostr = raptor_new_iostream_from_filename(world, filename);
1380 if(!iostr) {
1381 fprintf(stderr, "%s: Failed to create %s '%s'\n", program, label, filename);
1382 rc = 1;
1383 goto tidy;
1384 }
1385
1386 count = raptor_iostream_read_bytes(buffer, 1, test_string_len, iostr);
1387 if(count != expected_len) {
1388 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1389 (int)count, (int)expected_len);
1390 rc = 1;
1391 goto tidy;
1392 }
1393
1394 count = raptor_iostream_read_bytes(buffer, 1, test_string_len, iostr);
1395 if(count != expected_len2) {
1396 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1397 (int)count, (int)expected_len2);
1398 rc = 1;
1399 goto tidy;
1400 }
1401
1402 if(!raptor_iostream_read_eof(iostr)) {
1403 fprintf(stderr, "%s: %s not EOF as expected\n", program, label);
1404 rc = 1;
1405 goto tidy;
1406 }
1407
1408 if(strncmp(buffer, test_string, test_string_len)) {
1409 fprintf(stderr, "%s: %s returned '%s' expected '%s'\n", program, label,
1410 buffer, test_string);
1411 rc = 1;
1412 }
1413
1414 tidy:
1415 if(iostr)
1416 raptor_free_iostream(iostr);
1417
1418 if(rc)
1419 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1420
1421 return rc;
1422 }
1423
1424
1425 static int
test_read_from_file_handle(raptor_world * world,FILE * handle,const char * test_string,size_t test_string_len,const unsigned int expected_len,const unsigned int expected_len2)1426 test_read_from_file_handle(raptor_world *world, FILE* handle,
1427 const char* test_string, size_t test_string_len,
1428 const unsigned int expected_len,
1429 const unsigned int expected_len2)
1430 {
1431 raptor_iostream *iostr = NULL;
1432 char buffer[READ_BUFFER_SIZE];
1433 unsigned long count;
1434 int rc = 0;
1435 const char* const label="read iostream from file handle";
1436
1437 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1438 fprintf(stderr, "%s: Testing %s\n", program, label);
1439 #endif
1440
1441 iostr = raptor_new_iostream_from_file_handle(world, handle);
1442 if(!iostr) {
1443 fprintf(stderr, "%s: Failed to create %s\n", program, label);
1444 rc = 1;
1445 goto tidy;
1446 }
1447
1448 count = raptor_iostream_read_bytes(buffer, 1, test_string_len, iostr);
1449 if(count != expected_len) {
1450 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1451 (int)count, (int)expected_len);
1452 rc = 1;
1453 }
1454
1455 count = raptor_iostream_read_bytes(buffer, 1, test_string_len, iostr);
1456 if(count != expected_len2) {
1457 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1458 (int)count, (int)expected_len2);
1459 rc = 1;
1460 goto tidy;
1461 }
1462
1463 if(!raptor_iostream_read_eof(iostr)) {
1464 fprintf(stderr, "%s: %s not EOF as expected\n", program, label);
1465 rc = 1;
1466 }
1467
1468 if(strncmp(buffer, test_string, test_string_len)) {
1469 fprintf(stderr, "%s: %s returned '%s' expected '%s'\n", program, label,
1470 buffer, test_string);
1471 rc = 1;
1472 }
1473
1474 tidy:
1475 if(iostr)
1476 raptor_free_iostream(iostr);
1477
1478 if(rc)
1479 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1480
1481 return rc;
1482 }
1483
1484
1485 static int
test_read_from_string(raptor_world * world,const char * test_string,size_t test_string_len,const unsigned int expected_len)1486 test_read_from_string(raptor_world *world,
1487 const char* test_string, size_t test_string_len,
1488 const unsigned int expected_len)
1489 {
1490 raptor_iostream *iostr = NULL;
1491 char buffer[READ_BUFFER_SIZE];
1492 unsigned long count;
1493 int rc = 0;
1494 const char* const label="read iostream from a string";
1495
1496 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1497 fprintf(stderr, "%s: Testing %s\n", program, label);
1498 #endif
1499
1500 iostr = raptor_new_iostream_from_string(world,
1501 (void*)test_string, test_string_len);
1502 if(!iostr) {
1503 fprintf(stderr, "%s: Failed to create %s\n", program, label);
1504 rc = 1;
1505 goto tidy;
1506 }
1507
1508 count = raptor_iostream_read_bytes(buffer, 1, test_string_len, iostr);
1509 if(count != expected_len) {
1510 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1511 (int)count, (int)expected_len);
1512 rc = 1;
1513 }
1514
1515 if(!raptor_iostream_read_eof(iostr)) {
1516 fprintf(stderr, "%s: %s not EOF as expected\n", program, label);
1517 rc = 1;
1518 }
1519
1520 if(strncmp(buffer, test_string, test_string_len)) {
1521 fprintf(stderr, "%s: %s returned '%s' expected '%s'\n", program, label,
1522 buffer, test_string);
1523 rc = 1;
1524 }
1525
1526 tidy:
1527 if(iostr)
1528 raptor_free_iostream(iostr);
1529
1530 if(rc)
1531 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1532
1533 return rc;
1534 }
1535
1536
1537 static int
test_read_from_sink(raptor_world * world,size_t read_len,size_t expected_len)1538 test_read_from_sink(raptor_world *world, size_t read_len, size_t expected_len)
1539 {
1540 raptor_iostream *iostr = NULL;
1541 char buffer[READ_BUFFER_SIZE];
1542 unsigned long count;
1543 int rc = 0;
1544 const char* const label="read iostream from sink";
1545
1546 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
1547 fprintf(stderr, "%s: Testing %s\n", program, label);
1548 #endif
1549 expected_len = 0;
1550 iostr = raptor_new_iostream_from_sink(world);
1551 if(!iostr) {
1552 fprintf(stderr, "%s: Failed to create %s\n", program, label);
1553 rc = 1;
1554 goto tidy;
1555 }
1556
1557 count = raptor_iostream_read_bytes(buffer, 1, read_len, iostr);
1558 if(count != expected_len) {
1559 fprintf(stderr, "%s: %s read %d bytes, expected %d\n", program, label,
1560 (int)count, (int)expected_len);
1561 rc = 1;
1562 }
1563
1564 if(!raptor_iostream_read_eof(iostr)) {
1565 fprintf(stderr, "%s: %s not EOF as expected\n", program, label);
1566 rc = 1;
1567 }
1568
1569 tidy:
1570 if(iostr)
1571 raptor_free_iostream(iostr);
1572
1573 if(rc)
1574 fprintf(stderr, "%s: FAILED Testing %s\n", program, label);
1575
1576 return rc;
1577 }
1578
1579
1580 #define OUT_FILENAME "out.bin"
1581 #define OUT_BYTES_COUNT 14
1582 #define TEST_STRING "Hello, world!"
1583 #define TEST_STRING_LEN 13
1584 #define IN_FILENAME "in.bin"
1585
1586
1587 int
main(int argc,char * argv[])1588 main(int argc, char *argv[])
1589 {
1590 raptor_world *world;
1591 FILE *handle = NULL;
1592 int failures = 0;
1593
1594 program = raptor_basename(argv[0]);
1595
1596 world = raptor_new_world();
1597 if(!world || raptor_world_open(world))
1598 exit(1);
1599
1600 /* Write tests */
1601 failures+= test_write_to_filename(world, (const char*)OUT_FILENAME,
1602 TEST_STRING, TEST_STRING_LEN, (int)OUT_BYTES_COUNT);
1603 handle = fopen((const char*)OUT_FILENAME, "wb");
1604 if(!handle) {
1605 fprintf(stderr, "%s: Failed to create write file handle to file %s\n",
1606 program, OUT_FILENAME);
1607 failures++;
1608 } else {
1609 failures+= test_write_to_file_handle(world,
1610 handle, TEST_STRING, TEST_STRING_LEN,
1611 (int)OUT_BYTES_COUNT);
1612 fclose(handle);
1613 remove(OUT_FILENAME);
1614 }
1615
1616 failures+= test_write_to_string(world,
1617 TEST_STRING,
1618 TEST_STRING_LEN, (int)OUT_BYTES_COUNT);
1619 failures+= test_write_to_sink(world,
1620 TEST_STRING,
1621 TEST_STRING_LEN, (int)OUT_BYTES_COUNT);
1622
1623 remove(OUT_FILENAME);
1624
1625
1626 /* Read tests */
1627 handle = fopen((const char*)IN_FILENAME, "wb");
1628 if(!handle) {
1629 fprintf(stderr, "%s: Failed to create write handle to file %s\n",
1630 program, IN_FILENAME);
1631 failures++;
1632 } else {
1633 fwrite(TEST_STRING, 1, TEST_STRING_LEN, handle);
1634 fclose(handle);
1635
1636 failures+= test_read_from_filename(world,
1637 (const char*)IN_FILENAME,
1638 TEST_STRING, TEST_STRING_LEN,
1639 TEST_STRING_LEN, 0);
1640 handle = fopen((const char*)IN_FILENAME, "rb");
1641 if(!handle) {
1642 fprintf(stderr, "%s: Failed to create read file handle to file %s\n",
1643 program, IN_FILENAME);
1644 failures++;
1645 } else {
1646 failures+= test_read_from_file_handle(world,
1647 handle,
1648 TEST_STRING, TEST_STRING_LEN,
1649 TEST_STRING_LEN, 0);
1650 fclose(handle); handle = NULL;
1651 }
1652 }
1653
1654 failures+= test_read_from_string(world,
1655 TEST_STRING, TEST_STRING_LEN,
1656 TEST_STRING_LEN);
1657 failures+= test_read_from_sink(world, TEST_STRING_LEN, 0);
1658
1659 remove(IN_FILENAME);
1660
1661 raptor_free_world(world);
1662
1663 return failures;
1664 }
1665
1666 #endif
1667