1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * rdf_serializer.c - RDF Serializer (RDF triples to syntax) interface
4  *
5  * Copyright (C) 2002-2008, David Beckett http://www.dajobe.org/
6  * Copyright (C) 2002-2005, 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 
26 #ifdef HAVE_CONFIG_H
27 #include <rdf_config.h>
28 #endif
29 
30 #ifdef WIN32
31 #include <win32_rdf_config.h>
32 #endif
33 
34 #include <stdio.h>
35 #include <string.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #ifdef HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42 
43 #include <redland.h>
44 
45 
46 #ifndef STANDALONE
47 
48 /**
49  * librdf_init_serializer:
50  * @world: redland world object
51  *
52  * INTERNAL - Initialise the serializer module.
53  *
54  **/
55 void
librdf_init_serializer(librdf_world * world)56 librdf_init_serializer(librdf_world *world)
57 {
58   librdf_serializer_raptor_constructor(world);
59 }
60 
61 
62 /**
63  * librdf_finish_serializer:
64  * @world: redland world object
65  *
66  * INTERNAL - Terminate the serializer module.
67  *
68  **/
69 void
librdf_finish_serializer(librdf_world * world)70 librdf_finish_serializer(librdf_world *world)
71 {
72   if(world->serializers) {
73     raptor_free_sequence(world->serializers);
74     world->serializers=NULL;
75   }
76 #ifdef HAVE_RAPTOR_RDF_SERIALIZER
77   librdf_serializer_raptor_destructor();
78 #endif
79 }
80 
81 
82 /* helper functions */
83 static void
librdf_free_serializer_factory(librdf_serializer_factory * factory)84 librdf_free_serializer_factory(librdf_serializer_factory *factory)
85 {
86   if(factory->name)
87     LIBRDF_FREE(char*, factory->name);
88   if(factory->label)
89     LIBRDF_FREE(char*, factory->label);
90   if(factory->mime_type)
91     LIBRDF_FREE(char*, factory->mime_type);
92   if(factory->type_uri)
93     librdf_free_uri(factory->type_uri);
94   LIBRDF_FREE(librdf_serializer_factory, factory);
95 }
96 
97 
98 /**
99  * librdf_serializer_register_factory:
100  * @world: redland world object
101  * @name: the name of the serializer
102  * @label: the label of the serializer (optional)
103  * @mime_type: MIME type of the syntax (optional)
104  * @uri_string: URI of the syntax (optional)
105  * @factory: function to be called to register the factor parameters
106  *
107  * Register a serializer factory .
108  *
109  **/
110 REDLAND_EXTERN_C
111 void
librdf_serializer_register_factory(librdf_world * world,const char * name,const char * label,const char * mime_type,const unsigned char * uri_string,void (* factory)(librdf_serializer_factory *))112 librdf_serializer_register_factory(librdf_world *world,
113                                    const char *name, const char *label,
114                                    const char *mime_type,
115                                    const unsigned char *uri_string,
116                                    void (*factory) (librdf_serializer_factory*))
117 {
118   librdf_serializer_factory *serializer;
119 
120   librdf_world_open(world);
121 
122 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
123   LIBRDF_DEBUG2("Received registration for serializer %s\n", name);
124 #endif
125 
126   if(!world->serializers) {
127     world->serializers = raptor_new_sequence((raptor_data_free_handler)librdf_free_serializer_factory, NULL);
128 
129     if(!world->serializers)
130       goto oom;
131   }
132 
133   serializer = LIBRDF_CALLOC(librdf_serializer_factory*, 1, sizeof(*serializer));
134   if(!serializer)
135     goto oom;
136 
137   serializer->name = LIBRDF_MALLOC(char*, strlen(name) + 1);
138   if(!serializer->name)
139     goto oom_tidy;
140   strcpy(serializer->name, name);
141 
142   if(label) {
143     serializer->label = LIBRDF_MALLOC(char*, strlen(label) + 1);
144     if(!serializer->label)
145       goto oom_tidy;
146     strcpy(serializer->label, label);
147   }
148 
149   /* register mime type if any */
150   if(mime_type) {
151     serializer->mime_type = LIBRDF_MALLOC(char*, strlen(mime_type) + 1);
152     if(!serializer->mime_type)
153       goto oom_tidy;
154     strcpy(serializer->mime_type, mime_type);
155   }
156 
157   /* register URI if any */
158   if(uri_string) {
159     serializer->type_uri=librdf_new_uri(world, uri_string);
160     if(!serializer->type_uri)
161       goto oom_tidy;
162   }
163 
164   if(raptor_sequence_push(world->serializers, serializer))
165     goto oom;
166 
167   /* Call the serializer registration function on the new object */
168   (*factory)(serializer);
169 
170 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
171   LIBRDF_DEBUG3("%s has context size %d\n", name, serializer->context_length);
172 #endif
173 
174   return;
175 
176   oom_tidy:
177   librdf_free_serializer_factory(serializer);
178   oom:
179   LIBRDF_FATAL1(world, LIBRDF_FROM_SERIALIZER, "Out of memory");
180 }
181 
182 
183 /**
184  * librdf_get_serializer_factory:
185  * @world: redland world object
186  * @name: the name of the factory (or NULL or empty string if don't care)
187  * @mime_type: the MIME type of the syntax (NULL or empty string if not used)
188  * @type_uri: URI of syntax (NULL if not used)
189  *
190  * Get a serializer factory by name.
191  *
192  * If all fields are NULL, this means any parser supporting
193  * MIME Type "application/rdf+xml"
194  *
195  * Return value: the factory or NULL if not found
196  **/
197 librdf_serializer_factory*
librdf_get_serializer_factory(librdf_world * world,const char * name,const char * mime_type,librdf_uri * type_uri)198 librdf_get_serializer_factory(librdf_world *world,
199                               const char *name, const char *mime_type,
200                               librdf_uri *type_uri)
201 {
202   librdf_serializer_factory *factory;
203 
204   librdf_world_open(world);
205 
206   if(name && !*name)
207     name=NULL;
208   if(!mime_type || (mime_type && !*mime_type)) {
209     if(!name && !type_uri)
210       name="rdfxml";
211     else
212       mime_type=NULL;
213   }
214 
215   /* return 1st serializer if no particular one wanted */
216   if(!name && !mime_type && !type_uri) {
217     factory=(librdf_serializer_factory*)raptor_sequence_get_at(world->serializers, 0);
218     if(!factory) {
219       LIBRDF_DEBUG1("No serializers available\n");
220       return NULL;
221     }
222   } else {
223     int i;
224 
225     for(i=0;
226         (factory=(librdf_serializer_factory*)raptor_sequence_get_at(world->serializers, i));
227         i++) {
228       /* next if name does not match */
229       if(name && strcmp(factory->name, name))
230 	continue;
231 
232       /* MIME type may need to match */
233       if(mime_type) {
234         if(!factory->mime_type)
235           continue;
236         if(strcmp(factory->mime_type, mime_type))
237           continue;
238       }
239 
240       /* URI may need to match */
241       if(type_uri) {
242         if(!factory->type_uri)
243           continue;
244 
245         if(!librdf_uri_equals(factory->type_uri, type_uri))
246           continue;
247       }
248 
249       /* found it */
250       break;
251     }
252     /* else FACTORY with given arguments not found */
253     if(!factory)
254       return NULL;
255   }
256 
257   return factory;
258 }
259 
260 
261 /**
262  * librdf_serializer_enumerate:
263  * @world: redland world object
264  * @counter: index into the list of serializers
265  * @name: pointer to store the name of the serializer (or NULL)
266  * @label: pointer to store syntax readable label (or NULL)
267  *
268  * Get information on serializers.
269  *
270  * @Deprecated: use librdf_serializer_get_description() to return more information in a static structure.
271  *
272  * Return value: non 0 on failure of if counter is out of range
273  **/
274 int
librdf_serializer_enumerate(librdf_world * world,const unsigned int counter,const char ** name,const char ** label)275 librdf_serializer_enumerate(librdf_world* world,
276                         const unsigned int counter,
277                         const char **name, const char **label)
278 {
279   librdf_serializer_factory *factory;
280   int ioffset = LIBRDF_GOOD_CAST(int, counter);
281 
282   librdf_world_open(world);
283 
284   factory = (librdf_serializer_factory*)raptor_sequence_get_at(world->serializers,
285                                                                ioffset);
286   if(!factory)
287     return 1;
288 
289   if(name)
290     *name = factory->name;
291 
292   if(label)
293     *label = factory->label;
294 
295   return 0;
296 }
297 
298 
299 /**
300  * librdf_serializer_get_description:
301  * @world: world object
302  * @counter: index into the list of serializers
303  *
304  * Get serializer descriptive syntax information
305  *
306  * Return value: description or NULL if counter is out of range
307  **/
308 const raptor_syntax_description*
librdf_serializer_get_description(librdf_world * world,unsigned int counter)309 librdf_serializer_get_description(librdf_world* world,
310                                   unsigned int counter)
311 {
312   librdf_world_open(world);
313 
314   return raptor_world_get_serializer_description(world->raptor_world_ptr,
315                                                  counter);
316 }
317 
318 
319 /**
320  * librdf_serializer_check_name:
321  * @world: redland world object
322  * @name: name of serializer
323  *
324  * Check if a serializer name is known
325  *
326  * Return value: non 0 if name is a known serializer
327  **/
328 int
librdf_serializer_check_name(librdf_world * world,const char * name)329 librdf_serializer_check_name(librdf_world* world, const char *name)
330 {
331   librdf_serializer_factory *factory;
332   int i;
333 
334   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(name, char*, 0);
335 
336   librdf_world_open(world);
337 
338   for(i = 0;
339       (factory = (librdf_serializer_factory*)raptor_sequence_get_at(world->serializers, i));
340       i++) {
341     if(!strcmp(factory->name, name))
342       return 1;
343   }
344 
345   return 0;
346 }
347 
348 
349 /**
350  * librdf_new_serializer:
351  * @world: redland world object
352  * @name: the serializer factory name (or NULL or empty string if don't care)
353  * @mime_type: the MIME type of the syntax (NULL if not used)
354  * @type_uri: URI of syntax (NULL if not used)
355  *
356  * Constructor - create a new #librdf_serializer object.
357  *
358  * Return value: new #librdf_serializer object or NULL
359  **/
360 librdf_serializer*
librdf_new_serializer(librdf_world * world,const char * name,const char * mime_type,librdf_uri * type_uri)361 librdf_new_serializer(librdf_world *world,
362                       const char *name, const char *mime_type,
363                       librdf_uri *type_uri)
364 {
365   librdf_serializer_factory* factory;
366 
367   librdf_world_open(world);
368 
369   factory = librdf_get_serializer_factory(world, name, mime_type, type_uri);
370   if(!factory) {
371     if(name)
372       librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER, NULL,
373                  "serializer '%s' not found", name);
374     else if(mime_type)
375       librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER, NULL,
376                  "serializer for mime_type '%s' not found", mime_type);
377     else if(type_uri)
378       librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER, NULL,
379                  "serializer for type URI '%s' not found",
380                  librdf_uri_as_string(type_uri));
381     else
382       librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER, NULL,
383                  "default serializer not found");
384     return NULL;
385   }
386 
387   return librdf_new_serializer_from_factory(world, factory);
388 }
389 
390 
391 /**
392  * librdf_new_serializer_from_factory:
393  * @world: redland world object
394  * @factory: the serializer factory to use to create this serializer
395  *
396  * Constructor - create a new #librdf_serializer object.
397  *
398  * Return value: new #librdf_serializer object or NULL
399  **/
400 librdf_serializer*
librdf_new_serializer_from_factory(librdf_world * world,librdf_serializer_factory * factory)401 librdf_new_serializer_from_factory(librdf_world *world,
402                                    librdf_serializer_factory *factory)
403 {
404   librdf_serializer* d;
405 
406   librdf_world_open(world);
407 
408   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(factory, librdf_serializer_factory, NULL);
409 
410   d = LIBRDF_CALLOC(librdf_serializer*, 1, sizeof(*d));
411   if(!d)
412     return NULL;
413 
414   d->context = LIBRDF_CALLOC(void*, 1, factory->context_length);
415   if(!d->context) {
416     librdf_free_serializer(d);
417     return NULL;
418   }
419 
420   d->world=world;
421 
422   d->factory=factory;
423 
424   if(factory->init)
425     if(factory->init(d, d->context)) {
426       librdf_free_serializer(d);
427       return NULL;
428     }
429 
430   return d;
431 }
432 
433 
434 /**
435  * librdf_free_serializer:
436  * @serializer: the serializer
437  *
438  * Destructor - destroys a #librdf_serializer object.
439  *
440  **/
441 void
librdf_free_serializer(librdf_serializer * serializer)442 librdf_free_serializer(librdf_serializer *serializer)
443 {
444   if(!serializer)
445     return;
446 
447   if(serializer->context) {
448     if(serializer->factory->terminate)
449       serializer->factory->terminate(serializer->context);
450     LIBRDF_FREE(serializer_context, serializer->context);
451   }
452   LIBRDF_FREE(librdf_serializer, serializer);
453 }
454 
455 
456 
457 /* methods */
458 
459 
460 #ifndef REDLAND_DISABLE_DEPRECATED
461 /**
462  * librdf_serializer_serialize_model:
463  * @serializer: the serializer
464  * @handle: file handle to serialize to
465  * @base_uri: the base URI to use (or NULL)
466  * @model: the #librdf_model model to use
467  *
468  * @Deprecated: Use librdf_serializer_serialize_model_to_file_handle()
469  *
470  * Write a serialized #librdf_model to a FILE*.
471  *
472  * Return value: non 0 on failure
473  **/
474 int
librdf_serializer_serialize_model(librdf_serializer * serializer,FILE * handle,librdf_uri * base_uri,librdf_model * model)475 librdf_serializer_serialize_model(librdf_serializer* serializer,
476                                   FILE *handle, librdf_uri* base_uri,
477                                   librdf_model* model)
478 {
479   return librdf_serializer_serialize_model_to_file_handle(serializer,
480                                                           handle, base_uri,
481                                                           model);
482 }
483 #endif
484 
485 
486 /**
487  * librdf_serializer_serialize_stream_to_file_handle:
488  * @serializer: the serializer
489  * @handle: file handle to serialize to
490  * @base_uri: the base URI to use (or NULL)
491  * @stream: the #librdf_stream model to use
492  *
493  * Write a #librdf_stream to a FILE*.
494  *
495  * Return value: non 0 on failure
496  **/
497 int
librdf_serializer_serialize_stream_to_file_handle(librdf_serializer * serializer,FILE * handle,librdf_uri * base_uri,librdf_stream * stream)498 librdf_serializer_serialize_stream_to_file_handle(librdf_serializer* serializer,
499                                                   FILE *handle,
500                                                   librdf_uri* base_uri,
501                                                   librdf_stream* stream)
502 {
503   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
504   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(handle, FILE*, 1);
505   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, 1);
506 
507   return serializer->factory->serialize_stream_to_file_handle(serializer->context,
508                                                               handle, base_uri, stream);
509 }
510 
511 
512 /**
513  * librdf_serializer_serialize_model_to_file_handle:
514  * @serializer: the serializer
515  * @handle: file handle to serialize to
516  * @base_uri: the base URI to use (or NULL)
517  * @model: the #librdf_model model to use
518  *
519  * Write a serialized #librdf_model to a FILE*.
520  *
521  * Return value: non 0 on failure
522  **/
523 int
librdf_serializer_serialize_model_to_file_handle(librdf_serializer * serializer,FILE * handle,librdf_uri * base_uri,librdf_model * model)524 librdf_serializer_serialize_model_to_file_handle(librdf_serializer* serializer,
525                                                  FILE *handle,
526                                                  librdf_uri* base_uri,
527                                                  librdf_model* model)
528 {
529   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
530   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(handle, FILE*, 1);
531   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(model, librdf_model, 1);
532 
533   return serializer->factory->serialize_model_to_file_handle(serializer->context,
534                                                              handle, base_uri, model);
535 }
536 
537 
538 /**
539  * librdf_serializer_serialize_stream_to_file:
540  * @serializer: the serializer
541  * @name: filename to serialize to
542  * @base_uri: the base URI to use (or NULL)
543  * @stream: the #librdf_stream stream to use
544  *
545  * Write a #librdf_stream to a file.
546  *
547  * Return value: non 0 on failure
548  **/
549 int
librdf_serializer_serialize_stream_to_file(librdf_serializer * serializer,const char * name,librdf_uri * base_uri,librdf_stream * stream)550 librdf_serializer_serialize_stream_to_file(librdf_serializer* serializer,
551                                            const char *name,
552                                            librdf_uri* base_uri,
553                                            librdf_stream* stream)
554 {
555   FILE* fh;
556   int status;
557 
558   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
559   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(name, string, 1);
560   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, 1);
561 
562   fh=fopen(name, "w+");
563   if(!fh) {
564     librdf_log(serializer->world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER,
565                NULL, "failed to open file '%s' for writing - %s",
566                name, strerror(errno));
567     return 1;
568   }
569 
570   status=librdf_serializer_serialize_stream_to_file_handle(serializer, fh,
571                                                            base_uri, stream);
572   fclose(fh);
573   return status;
574 }
575 
576 
577 /**
578  * librdf_serializer_serialize_model_to_file:
579  * @serializer: the serializer
580  * @name: filename to serialize to
581  * @base_uri: the base URI to use (or NULL)
582  * @model: the #librdf_model model to use
583  *
584  * Write a serialized #librdf_model to a file.
585  *
586  * Return value: non 0 on failure
587  **/
588 int
librdf_serializer_serialize_model_to_file(librdf_serializer * serializer,const char * name,librdf_uri * base_uri,librdf_model * model)589 librdf_serializer_serialize_model_to_file(librdf_serializer* serializer,
590                                           const char *name,
591                                           librdf_uri* base_uri,
592                                           librdf_model* model)
593 {
594   FILE* fh;
595   int status;
596 
597   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
598   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(name, string, 1);
599   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(model, librdf_model, 1);
600 
601   fh=fopen(name, "w+");
602   if(!fh) {
603     librdf_log(serializer->world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_SERIALIZER,
604                NULL, "failed to open file '%s' for writing - %s",
605                name, strerror(errno));
606     return 1;
607   }
608 
609   status=librdf_serializer_serialize_model_to_file_handle(serializer, fh,
610                                                           base_uri, model);
611   fclose(fh);
612   return status;
613 }
614 
615 
616 /**
617  * librdf_serializer_serialize_stream_to_counted_string:
618  * @serializer: the serializer
619  * @base_uri: the base URI to use (or NULL)
620  * @stream: the #librdf_stream stream to use
621  * @length_p: pointer to store length or NULL
622  *
623  * Write a #librdf_stream to a counted string.
624  * Caller should free the string with librdf_free_memory().
625  *
626  * Return value: stream as string or NULL on failure
627  **/
628 unsigned char*
librdf_serializer_serialize_stream_to_counted_string(librdf_serializer * serializer,librdf_uri * base_uri,librdf_stream * stream,size_t * length_p)629 librdf_serializer_serialize_stream_to_counted_string(librdf_serializer* serializer,
630                                                      librdf_uri* base_uri,
631                                                      librdf_stream* stream,
632                                                      size_t* length_p)
633 {
634   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, NULL);
635   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, NULL);
636 
637   if(length_p)
638     *length_p=0;
639 
640   return serializer->factory->serialize_stream_to_counted_string(serializer->context,
641                                                                  base_uri,
642                                                                  stream,
643                                                                  length_p);
644 }
645 
646 
647 /**
648  * librdf_serializer_serialize_model_to_counted_string:
649  * @serializer: the serializer
650  * @base_uri: the base URI to use (or NULL)
651  * @model: the #librdf_model model to use
652  * @length_p: pointer to store length or NULL
653  *
654  * Write a serialized #librdf_model to a counted string.
655  * The returned string must be freed by the caller using librdf_free_memory().
656  *
657  * Return value: non 0 on failure
658  **/
659 unsigned char*
librdf_serializer_serialize_model_to_counted_string(librdf_serializer * serializer,librdf_uri * base_uri,librdf_model * model,size_t * length_p)660 librdf_serializer_serialize_model_to_counted_string(librdf_serializer* serializer,
661                                                     librdf_uri* base_uri,
662                                                     librdf_model* model,
663                                                     size_t* length_p)
664 {
665   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, NULL);
666   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(model, librdf_model, NULL);
667 
668   if(length_p)
669     *length_p=0;
670 
671   return serializer->factory->serialize_model_to_counted_string(serializer->context,
672                                                                 base_uri, model,
673                                                                 length_p);
674 }
675 
676 
677 /**
678  * librdf_serializer_serialize_stream_to_string:
679  * @serializer: the serializer
680  * @base_uri: the base URI to use (or NULL)
681  * @stream: the #librdf_stream stream to use
682  *
683  * Write a #librdf_stream to a string.
684  *
685  * Return value: NULL on failure
686  **/
687 unsigned char*
librdf_serializer_serialize_stream_to_string(librdf_serializer * serializer,librdf_uri * base_uri,librdf_stream * stream)688 librdf_serializer_serialize_stream_to_string(librdf_serializer* serializer,
689                                              librdf_uri* base_uri,
690                                              librdf_stream* stream)
691 {
692   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, NULL);
693   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, NULL);
694 
695   return serializer->factory->serialize_stream_to_counted_string(serializer->context,
696                                                                  base_uri,
697                                                                  stream,
698                                                                  NULL);
699 }
700 
701 
702 /**
703  * librdf_serializer_serialize_model_to_string:
704  * @serializer: the serializer
705  * @base_uri: the base URI to use (or NULL)
706  * @model: the #librdf_model model to use
707  *
708  * Write a serialized #librdf_model to a string.
709  * The returned string must be freed by the caller using librdf_free_memory().
710  *
711  * Return value: NULL on failure
712  **/
713 unsigned char*
librdf_serializer_serialize_model_to_string(librdf_serializer * serializer,librdf_uri * base_uri,librdf_model * model)714 librdf_serializer_serialize_model_to_string(librdf_serializer* serializer,
715                                             librdf_uri* base_uri,
716                                             librdf_model* model)
717 {
718   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, NULL);
719   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(model, librdf_model, NULL);
720 
721   return serializer->factory->serialize_model_to_counted_string(serializer->context,
722                                                                 base_uri, model,
723                                                                 NULL);
724 }
725 
726 
727 /**
728  * librdf_serializer_serialize_stream_to_iostream:
729  * @serializer: the serializer
730  * @base_uri: the base URI to use (or NULL)
731  * @stream: the #librdf_stream stream to use
732  * @iostr: the #raptor_iostream to write to
733  *
734  * Write a #librdf_stream to a #raptor_iostream.
735  * This function takes ownership of the iostream and frees it.
736  *
737  * Return value: non-0 on failure
738  **/
739 int
librdf_serializer_serialize_stream_to_iostream(librdf_serializer * serializer,librdf_uri * base_uri,librdf_stream * stream,raptor_iostream * iostr)740 librdf_serializer_serialize_stream_to_iostream(librdf_serializer* serializer,
741                                               librdf_uri* base_uri,
742                                               librdf_stream *stream,
743                                               raptor_iostream* iostr)
744 {
745   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
746   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, 1);
747 
748   return serializer->factory->serialize_stream_to_iostream(serializer->context,
749                                                            base_uri, stream,
750                                                            iostr);
751 }
752 
753 
754 
755 /**
756  * librdf_serializer_serialize_model_to_iostream:
757  * @serializer: the serializer
758  * @base_uri: the base URI to use (or NULL)
759  * @model: the #librdf_model model to use
760  * @iostr: the #raptor_iostream to write to
761  *
762  * Write a serialized #librdf_model to a #raptor_iostream.
763  * This function takes ownership of the iostream and frees it.
764  *
765  * Return value: non-0 on failure
766  **/
767 int
librdf_serializer_serialize_model_to_iostream(librdf_serializer * serializer,librdf_uri * base_uri,librdf_model * model,raptor_iostream * iostr)768 librdf_serializer_serialize_model_to_iostream(librdf_serializer* serializer,
769                                               librdf_uri* base_uri,
770                                               librdf_model *model,
771                                               raptor_iostream* iostr)
772 {
773   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
774   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(model, librdf_model, 1);
775 
776   return serializer->factory->serialize_model_to_iostream(serializer->context,
777                                                           base_uri, model,
778                                                           iostr);
779 }
780 
781 
782 #ifndef REDLAND_DISABLE_DEPRECATED
783 /**
784  * librdf_serializer_set_error:
785  * @serializer: the serializer
786  * @user_data: user data to pass to function
787  * @error_fn: pointer to the function
788  *
789  * @Deprecated: Does nothing
790  *
791  * Set the serializer error handling function.
792  *
793  **/
794 REDLAND_EXTERN_C
795 void
librdf_serializer_set_error(librdf_serializer * serializer,void * user_data,void (* error_fn)(void * user_data,const char * msg,...))796 librdf_serializer_set_error(librdf_serializer* serializer, void *user_data,
797                             void (*error_fn)(void *user_data, const char *msg, ...))
798 {
799 }
800 #endif
801 
802 
803 #ifndef REDLAND_DISABLE_DEPRECATED
804 /**
805  * librdf_serializer_set_warning:
806  * @serializer: the serializer
807  * @user_data: user data to pass to function
808  * @warning_fn: pointer to the function
809  *
810  * @Deprecated: Does nothing
811  *
812  * Set the serializer warning handling function.
813  *
814  **/
815 REDLAND_EXTERN_C
816 void
librdf_serializer_set_warning(librdf_serializer * serializer,void * user_data,void (* warning_fn)(void * user_data,const char * msg,...))817 librdf_serializer_set_warning(librdf_serializer* serializer, void *user_data,
818                               void (*warning_fn)(void *user_data, const char *msg, ...))
819 {
820 }
821 #endif
822 
823 
824 /**
825  * librdf_serializer_get_feature:
826  * @serializer: serializer object
827  * @feature: URI of feature
828  *
829  * Get the value of a serializer feature.
830  *
831  * Return value: the value of the feature or NULL if no such feature
832  * exists or the value is empty.
833  **/
834 librdf_node*
librdf_serializer_get_feature(librdf_serializer * serializer,librdf_uri * feature)835 librdf_serializer_get_feature(librdf_serializer* serializer, librdf_uri *feature)
836 {
837   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, NULL);
838   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, NULL);
839 
840   if(serializer->factory->get_feature)
841     return serializer->factory->get_feature(serializer->context, feature);
842 
843   return NULL;
844 }
845 
846 /**
847  * librdf_serializer_set_feature:
848  * @serializer: serializer object
849  * @feature: URI of feature
850  * @value: value to set
851  *
852  * Set the value of a serializer feature.
853  *
854  * Return value: non 0 on failure (negative if no such feature)
855  **/
856 
857 int
librdf_serializer_set_feature(librdf_serializer * serializer,librdf_uri * feature,librdf_node * value)858 librdf_serializer_set_feature(librdf_serializer* serializer,
859                               librdf_uri *feature, librdf_node* value)
860 {
861   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, -1);
862   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, -1);
863   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(value, librdf_node, -1);
864 
865   if(serializer->factory->set_feature)
866     return serializer->factory->set_feature(serializer->context, feature, value);
867 
868   return (-1);
869 }
870 
871 /**
872  * librdf_serializer_set_namespace:
873  * @serializer: serializer object
874  * @uri: URI of namespace or NULL
875  * @prefix: prefix to use or NULL
876  *
877  * Set a namespace URI/prefix mapping.
878  *
879  * Return value: non 0 on failure
880  **/
881 
882 int
librdf_serializer_set_namespace(librdf_serializer * serializer,librdf_uri * uri,const char * prefix)883 librdf_serializer_set_namespace(librdf_serializer* serializer,
884                                 librdf_uri *uri, const char *prefix)
885 {
886   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(serializer, librdf_serializer, 1);
887   if(uri && !*librdf_uri_as_string(uri))
888     uri=NULL;
889   if(prefix && !*prefix)
890     prefix=NULL;
891 
892   if(serializer->factory->set_namespace)
893     return serializer->factory->set_namespace(serializer->context, uri, prefix);
894   return 1;
895 }
896 
897 #endif
898 
899 
900 /* TEST CODE */
901 
902 
903 #ifdef STANDALONE
904 
905 #ifdef HAVE_SYS_STAT_H
906 #include <sys/stat.h>
907 #endif
908 
909 #ifdef HAVE_UNISTD_H
910 #include <unistd.h>
911 #endif
912 
913 /* one more prototype */
914 int main(int argc, char *argv[]);
915 
916 
917 struct log_data {
918   int errors;
919   int warnings;
920 } LogData;
921 
922 
923 static int REDLAND_CALLBACK_STDCALL
log_handler(void * user_data,librdf_log_message * message)924 log_handler(void *user_data, librdf_log_message *message)
925 {
926   struct log_data* ld=(struct log_data*)user_data;
927 
928   switch(message->level) {
929     case LIBRDF_LOG_ERROR:
930       ld->errors++;
931       break;
932     case LIBRDF_LOG_WARN:
933       ld->warnings++;
934       break;
935 
936     case LIBRDF_LOG_NONE:
937     case LIBRDF_LOG_DEBUG:
938     case LIBRDF_LOG_INFO:
939     case LIBRDF_LOG_FATAL:
940     default:
941       break;
942   }
943 
944   return 1;
945 }
946 
947 
948 #define EXPECTED_ERRORS1 3
949 /* Extra error is another UTF-8 encoding error */
950 #define EXPECTED_ERRORS2 4
951 #define EXPECTED_WARNINGS 0
952 
953 #define SYNTAX_TYPE "ntriples"
954 #define SYNTAX_CONTENT \
955 "<http://purl.org/net/dajobe/> <http://purl.org/dc/elements/1.1/creator> \"Dave Beckett\" .\n" \
956 "<http://purl.org/net/dajobe/> <http://purl.org/dc/elements/1.1/description> \"The generic home page of Dave Beckett.\" .\n" \
957 "<http://purl.org/net/dajobe/> <http://purl.org/dc/elements/1.1/title> \"Dave Beckett's Home Page\" . \n"
958 
959 
960 int
main(int argc,char * argv[])961 main(int argc, char *argv[])
962 {
963   const char *program=librdf_basename((const char*)argv[0]);
964   const char *test_serializer_types[]={"rdfxml", "ntriples", NULL};
965   int i;
966   const char *type;
967   unsigned char *string;
968   size_t string_length;
969   librdf_world *world;
970   librdf_storage *storage;
971   librdf_model* model;
972   librdf_uri* base_uri;
973   librdf_statement* statement;
974   librdf_serializer* serializer;
975   librdf_parser* parser;
976   librdf_stream* stream;
977   FILE *fh;
978   struct stat st_buf;
979 
980   world=librdf_new_world();
981   librdf_world_open(world);
982 
983   librdf_world_set_logger(world, &LogData, log_handler);
984 
985   for(i=0; (type=test_serializer_types[i]); i++) {
986     fprintf(stderr, "%s: Trying to create new %s serializer\n", program, type);
987     serializer=librdf_new_serializer(world, type, NULL, NULL);
988     if(!serializer) {
989       fprintf(stderr, "%s: Failed to create new serializer type %s\n", program, type);
990       continue;
991     }
992 
993     fprintf(stderr, "%s: Freeing serializer\n", program);
994     librdf_free_serializer(serializer);
995   }
996 
997 
998   storage=librdf_new_storage(world, NULL, NULL, NULL);
999   model=librdf_new_model(world, storage, NULL);
1000 
1001   /* ERROR: Subject URI is bad UTF-8 */
1002   statement=librdf_new_statement_from_nodes(world,
1003     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://example.org/foo\xfc"),
1004     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://example.org/bar"),
1005     librdf_new_node_from_literal(world, (const unsigned char*)"blah", NULL, 0));
1006 
1007   librdf_model_add_statement(model, statement);
1008   librdf_free_statement(statement);
1009 
1010   /* ERROR: Predicate URI is not serializable */
1011   statement=librdf_new_statement_from_nodes(world,
1012     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://example.org/foo"),
1013     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://bad.example.org/"),
1014     librdf_new_node_from_literal(world, (const unsigned char*)"blah", NULL, 0));
1015 
1016   librdf_model_add_statement(model, statement);
1017   librdf_free_statement(statement);
1018 
1019   /* ERROR: Object literal is bad UTF-8 */
1020   statement=librdf_new_statement_from_nodes(world,
1021     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://example.org/foo"),
1022     librdf_new_node_from_uri_string(world, (const unsigned char*)"http://example.org/abc"),
1023     librdf_new_node_from_literal(world, (const unsigned char*)"\xfc", NULL, 0));
1024 
1025   librdf_model_add_statement(model, statement);
1026   librdf_free_statement(statement);
1027 
1028   serializer=librdf_new_serializer(world, "rdfxml", NULL, NULL);
1029   base_uri=librdf_new_uri(world, (const unsigned char*)"http://example.org/base#");
1030 
1031   string=librdf_serializer_serialize_model_to_counted_string(serializer,
1032                                                              base_uri, model,
1033                                                              &string_length);
1034 #define EXPECTED_BAD_STRING_LENGTH1 382
1035 /* Raptor 2.0.11 changed the serialization slightly */
1036 #define EXPECTED_BAD_STRING_LENGTH2 378
1037   if(string_length != EXPECTED_BAD_STRING_LENGTH1 &&
1038      string_length != EXPECTED_BAD_STRING_LENGTH2) {
1039     fprintf(stderr, "%s: Serialising model to RDF/XML returned string '%s' size %d, expected %d or %d\n", program, string,
1040             (int)string_length,
1041             EXPECTED_BAD_STRING_LENGTH1, EXPECTED_BAD_STRING_LENGTH2);
1042     return 1;
1043   }
1044 
1045   librdf_free_memory(string);
1046 
1047   librdf_free_uri(base_uri); base_uri=NULL;
1048   librdf_free_model(model); model=NULL;
1049   librdf_free_storage(storage); storage=NULL;
1050 
1051 
1052   if(LogData.errors != EXPECTED_ERRORS1 && LogData.errors != EXPECTED_ERRORS2) {
1053     fprintf(stderr, "%s: Serialising to RDF/XML returned %d errors, expected %d or %d\n", program,
1054             LogData.errors, EXPECTED_ERRORS1, EXPECTED_ERRORS2);
1055     return 1;
1056   }
1057 
1058   if(LogData.warnings != EXPECTED_WARNINGS) {
1059     fprintf(stderr, "%s: Serialising to RDF/XML returned %d warnings, expected %d\n", program,
1060             LogData.warnings, EXPECTED_WARNINGS);
1061     return 1;
1062   }
1063 
1064 
1065   /* Good model to serialize */
1066   storage=librdf_new_storage(world, NULL, NULL, NULL);
1067   model=librdf_new_model(world, storage, NULL);
1068 
1069   parser=librdf_new_parser(world, SYNTAX_TYPE, NULL, NULL);
1070   if(!parser) {
1071     fprintf(stderr, "%s: Failed to create new parser type %s\n", program,
1072             SYNTAX_TYPE);
1073     return 1;
1074   }
1075 
1076   fprintf(stderr, "%s: Adding %s string content\n", program, SYNTAX_TYPE);
1077   if(librdf_parser_parse_string_into_model(parser,
1078                                            (const unsigned char*)SYNTAX_CONTENT,
1079                                            NULL /* no base URI*/,
1080                                            model)) {
1081     fprintf(stderr, "%s: Failed to parse RDF from %s string into model\n",
1082             SYNTAX_TYPE, program);
1083     return 1;
1084   }
1085   librdf_free_parser(parser);
1086 
1087 
1088   fprintf(stderr, "%s: Serializing stream to a string\n", program);
1089 
1090   stream=librdf_model_as_stream(model);
1091   string_length=0;
1092   string=librdf_serializer_serialize_stream_to_counted_string(serializer,
1093                                                               NULL, stream,
1094                                                               &string_length);
1095 #define EXPECTED_GOOD_STRING_LENGTH 668
1096   if(string_length != EXPECTED_GOOD_STRING_LENGTH) {
1097     fprintf(stderr, "%s: Serialising stream to RDF/XML returned string '%s' size %d, expected %d\n", program, string,
1098             (int)string_length, EXPECTED_GOOD_STRING_LENGTH);
1099     return 1;
1100   }
1101   librdf_free_stream(stream);
1102 
1103   librdf_free_memory(string);
1104 
1105 
1106   fprintf(stderr, "%s: Serializing stream to a file handle\n", program);
1107 
1108   stream=librdf_model_as_stream(model);
1109 
1110 #define FILENAME "test.rdf"
1111   fh=fopen(FILENAME, "w");
1112   if(!fh) {
1113     fprintf(stderr, "%s: Failed to fopen for writing '%s' - %s\n",
1114             program, FILENAME, strerror(errno));
1115     return 1;
1116   }
1117   librdf_serializer_serialize_stream_to_file_handle(serializer, fh, NULL,
1118                                                     stream);
1119   fclose(fh);
1120   stat(FILENAME, &st_buf);
1121 
1122   if((int)st_buf.st_size != EXPECTED_GOOD_STRING_LENGTH) {
1123     fprintf(stderr, "%s: Serialising stream to file handle returned file '%s' of size %d bytes, expected %d\n", program, FILENAME, (int)st_buf.st_size,
1124             EXPECTED_GOOD_STRING_LENGTH);
1125     return 1;
1126   }
1127   unlink(FILENAME);
1128 
1129   librdf_free_stream(stream);
1130 
1131 
1132   librdf_free_serializer(serializer); serializer=NULL;
1133   librdf_free_model(model); model=NULL;
1134   librdf_free_storage(storage); storage=NULL;
1135 
1136 
1137   librdf_free_world(world);
1138 
1139   /* keep gcc -Wall happy */
1140   return(0);
1141 }
1142 
1143 #endif
1144