1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * raptor_statement.c - Raptor statements
4  *
5  * Copyright (C) 2008, David Beckett http://www.dajobe.org/
6  *
7  * This package is Free Software and part of Redland http://librdf.org/
8  *
9  * It is licensed under the following three licenses as alternatives:
10  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
11  *   2. GNU General Public License (GPL) V2 or any newer version
12  *   3. Apache License, V2.0 or any newer version
13  *
14  * You may not use this file except in compliance with at least one of
15  * the above three licenses.
16  *
17  * See LICENSE.html or LICENSE.txt at the top of this package for the
18  * complete terms and further detail along with the license texts for
19  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
20  *
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <raptor_config.h>
25 #endif
26 
27 #ifdef WIN32
28 #include <win32_raptor_config.h>
29 #endif
30 
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <stdarg.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 
40 /* Raptor includes */
41 #include "raptor.h"
42 #include "raptor_internal.h"
43 
44 
45 /* prototypes for helper functions */
46 static void raptor_print_statement_part_as_ntriples(raptor_world* world, FILE* stream, const void *term, raptor_identifier_type type, raptor_uri* literal_datatype, const unsigned char *literal_language);
47 static void raptor_print_statement_as_ntriples_common(raptor_world* world, const raptor_statement *statement, FILE *stream);
48 static int raptor_statement_compare_common(raptor_world* world, const raptor_statement *s1, const raptor_statement *s2);
49 
50 
51 /**
52  * raptor_statement_copy_v2:
53  * @statement: statement to copy
54  *
55  * Copy a #raptor_statement.
56  *
57  * Return value: a new #raptor_statement_v2 or NULL on error
58  */
59 raptor_statement_v2*
raptor_statement_copy_v2(const raptor_statement_v2 * statement)60 raptor_statement_copy_v2(const raptor_statement_v2 *statement)
61 {
62   return raptor_statement_copy_v2_from_v1(statement->world, statement->s);
63 }
64 
65 
66 /**
67  * raptor_statement_copy_v2_from_v1:
68  * @world: raptor_world object
69  * @statement: statement to copy
70  *
71  * Copy a #raptor_statement and wrap it in #raptor_statement_v2.
72  *
73  * Return value: a new #raptor_statement_v2 or NULL on error
74  */
75 raptor_statement_v2*
raptor_statement_copy_v2_from_v1(raptor_world * world,const raptor_statement * statement)76 raptor_statement_copy_v2_from_v1(raptor_world* world, const raptor_statement *statement)
77 {
78   raptor_statement_v2 *s;
79 
80   s=(raptor_statement_v2*)RAPTOR_CALLOC(raptor_statement_v2, 1, sizeof(raptor_statement_v2));
81   if(!s)
82     return NULL;
83 
84   s->world=world;
85   s->s=raptor_statement_copy(world, statement);
86   if(!s->s) {
87     raptor_free_statement_v2(s);
88     s=NULL;
89   }
90 
91   return s;
92 }
93 
94 
95 /**
96  * raptor_statement_copy:
97  * @world: raptor_world object
98  * @statement: statement to copy
99  *
100  * Copy a #raptor_statement.
101  *
102  * Return value: a new #raptor_statement or NULL on error
103  */
104 raptor_statement*
raptor_statement_copy(raptor_world * world,const raptor_statement * statement)105 raptor_statement_copy(raptor_world* world, const raptor_statement *statement)
106 {
107   raptor_statement *s;
108 
109   s=(raptor_statement*)RAPTOR_CALLOC(raptor_statement, 1, sizeof(raptor_statement));
110   if(!s)
111     return NULL;
112 
113   s->subject_type=statement->subject_type;
114   if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
115     unsigned char *new_blank=(unsigned char*)RAPTOR_MALLOC(cstring, strlen((char*)statement->subject)+1);
116     if(!new_blank)
117       goto oom;
118     strcpy((char*)new_blank, (const char*)statement->subject);
119     s->subject=new_blank;
120   } else if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL) {
121     s->subject=raptor_new_uri_from_rdf_ordinal(world, *((int*)statement->subject));
122     s->subject_type=RAPTOR_IDENTIFIER_TYPE_RESOURCE;
123   } else
124     s->subject=raptor_uri_copy_v2(world, (raptor_uri*)statement->subject);
125 
126   s->predicate_type=RAPTOR_IDENTIFIER_TYPE_RESOURCE;
127   if(statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL)
128     s->predicate=raptor_new_uri_from_rdf_ordinal(world, *((int*)statement->predicate));
129   else
130     s->predicate=raptor_uri_copy_v2(world, (raptor_uri*)statement->predicate);
131 
132 
133   s->object_type=statement->object_type;
134   if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_LITERAL ||
135      statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
136     unsigned char *string;
137     char *language=NULL;
138     raptor_uri *uri=NULL;
139 
140     string=(unsigned char*)RAPTOR_MALLOC(cstring, strlen((char*)statement->object)+1);
141     if(!string)
142       goto oom;
143     strcpy((char*)string, (const char*)statement->object);
144     s->object=string;
145 
146     if(statement->object_literal_language) {
147       language=(char*)RAPTOR_MALLOC(cstring, strlen((const char*)statement->object_literal_language)+1);
148       if(!language)
149         goto oom;
150       strcpy(language, (const char*)statement->object_literal_language);
151       s->object_literal_language=(const unsigned char*)language;
152     }
153 
154     if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
155       /* nop */
156     } else if(statement->object_literal_datatype) {
157       uri=raptor_uri_copy_v2(world, (raptor_uri*)statement->object_literal_datatype);
158       s->object_literal_datatype=uri;
159     }
160   } else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
161     char *blank=(char*)statement->object;
162     unsigned char *new_blank=(unsigned char*)RAPTOR_MALLOC(cstring, strlen(blank)+1);
163     if(!new_blank)
164       goto oom;
165     strcpy((char*)new_blank, (const char*)blank);
166     s->object=new_blank;
167   } else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL) {
168     s->object=raptor_new_uri_from_rdf_ordinal(world, *((int*)statement->object));
169     s->object_type=RAPTOR_IDENTIFIER_TYPE_RESOURCE;
170   } else {
171     raptor_uri *uri=raptor_uri_copy_v2(world, (raptor_uri*)statement->object);
172     s->object=uri;
173   }
174 
175   return s;
176 
177   oom:
178   raptor_free_statement(world, s);
179   return NULL;
180 }
181 
182 
183 /**
184  * raptor_free_statement_v2:
185  * @statement: statement
186  *
187  * Destructor
188  *
189  */
190 void
raptor_free_statement_v2(raptor_statement_v2 * statement)191 raptor_free_statement_v2(raptor_statement_v2 *statement)
192 {
193   RAPTOR_ASSERT_OBJECT_POINTER_RETURN(statement, raptor_statement);
194   raptor_free_statement(statement->world, statement->s);
195   RAPTOR_FREE(raptor_statement_v2, statement);
196 }
197 
198 
199 /**
200  * raptor_free_statement:
201  * @statement: statement
202  *
203  * Destructor
204  *
205  */
206 void
raptor_free_statement(raptor_world * world,raptor_statement * statement)207 raptor_free_statement(raptor_world *world, raptor_statement *statement)
208 {
209   if(statement->subject) {
210     if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_RESOURCE)
211       raptor_free_uri_v2(world, (raptor_uri*)statement->subject);
212     else
213       RAPTOR_FREE(cstring, (void*)statement->subject);
214   }
215 
216   if(statement->predicate) {
217     if(statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_PREDICATE ||
218        statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_RESOURCE)
219       raptor_free_uri_v2(world, (raptor_uri*)statement->predicate);
220     else
221       RAPTOR_FREE(cstring, (void*)statement->predicate);
222   }
223 
224   if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_RESOURCE) {
225     if(statement->object)
226       raptor_free_uri_v2(world, (raptor_uri*)statement->object);
227   } else {
228     if(statement->object)
229       RAPTOR_FREE(cstring, (void*)statement->object);
230 
231     if(statement->object_literal_language)
232       RAPTOR_FREE(cstring, (void*)statement->object_literal_language);
233     if(statement->object_literal_datatype)
234       raptor_free_uri_v2(world, (raptor_uri*)statement->object_literal_datatype);
235   }
236 
237   RAPTOR_FREE(raptor_statement, statement);
238 }
239 
240 
241 #ifndef RAPTOR_DISABLE_V1
242 /**
243  * raptor_print_statement:
244  * @statement: #raptor_statement object to print
245  * @stream: #FILE* stream
246  *
247  * Print a raptor_statement to a stream.
248  *
249  * raptor_init() MUST have been called before calling this function.
250  * Use raptor_print_statement_v2() if using raptor_world APIs.
251  **/
252 void
raptor_print_statement(const raptor_statement * statement,FILE * stream)253 raptor_print_statement(const raptor_statement * statement, FILE *stream)
254 {
255   raptor_print_statement_v1(raptor_world_instance(), statement, stream);
256 }
257 #endif
258 
259 
260 /**
261  * raptor_print_statement_v2:
262  * @statement: #raptor_statement_v2 object to print
263  * @stream: #FILE* stream
264  *
265  * Print a raptor_statement to a stream.
266  **/
267 void
raptor_print_statement_v2(const raptor_statement_v2 * statement,FILE * stream)268 raptor_print_statement_v2(const raptor_statement_v2 * statement, FILE *stream)
269 {
270   raptor_print_statement_v1(statement->world, statement->s, stream);
271 }
272 
273 
274 /**
275  * raptor_print_statement_v1:
276  * @world: raptor_world object
277  * @statement: #raptor_statement object to print
278  * @stream: #FILE* stream
279  *
280  * Print a raptor_statement to a stream.
281  **/
282 void
raptor_print_statement_v1(raptor_world * world,const raptor_statement * statement,FILE * stream)283 raptor_print_statement_v1(raptor_world* world, const raptor_statement * statement, FILE *stream)
284 {
285   fputc('[', stream);
286 
287   if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
288     fputs((const char*)statement->subject, stream);
289   } else {
290 #ifdef RAPTOR_DEBUG
291     if(!statement->subject)
292       RAPTOR_FATAL1("Statement has NULL subject URI\n");
293 #endif
294     fputs((const char*)raptor_uri_as_string_v2(world, (raptor_uri*)statement->subject), stream);
295   }
296 
297   fputs(", ", stream);
298 
299   if(statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL)
300     fprintf(stream, "[rdf:_%d]", *((int*)statement->predicate));
301   else {
302 #ifdef RAPTOR_DEBUG
303     if(!statement->predicate)
304       RAPTOR_FATAL1("Statement has NULL predicate URI\n");
305 #endif
306     fputs((const char*)raptor_uri_as_string_v2(world, (raptor_uri*)statement->predicate), stream);
307   }
308 
309   fputs(", ", stream);
310 
311   if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_LITERAL ||
312      statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
313     if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
314       fputc('<', stream);
315       fputs((const char*)raptor_xml_literal_datatype_uri_string, stream);
316       fputc('>', stream);
317     } else if(statement->object_literal_datatype) {
318       fputc('<', stream);
319       fputs((const char*)raptor_uri_as_string_v2(world, (raptor_uri*)statement->object_literal_datatype), stream);
320       fputc('>', stream);
321     }
322     fputc('"', stream);
323     fputs((const char*)statement->object, stream);
324     fputc('"', stream);
325   } else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS)
326     fputs((const char*)statement->object, stream);
327   else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL)
328     fprintf(stream, "[rdf:_%d]", *((int*)statement->object));
329   else {
330 #ifdef RAPTOR_DEBUG
331     if(!statement->object)
332       RAPTOR_FATAL1("Statement has NULL object URI\n");
333 #endif
334     fputs((const char*)raptor_uri_as_string_v2(world, (raptor_uri*)statement->object), stream);
335   }
336 
337   fputc(']', stream);
338 }
339 
340 
341 #if !defined(RAPTOR_DISABLE_DEPRECATED) && !defined(RAPTOR_DISABLE_V1)
342 /**
343  * raptor_print_statement_detailed:
344  * @statement: #raptor_statement object to print
345  * @detailed: unused
346  * @stream: #FILE* stream
347  *
348  * Print a raptor_statement to a stream in a detailed fashion.
349  *
350  * raptor_init() MUST have been called before calling this function.
351  *
352  * @deprecated: an internal function, do not use.
353  *
354  * No current difference from calling raptor_print_statement().
355  *
356  **/
357 void
raptor_print_statement_detailed(const raptor_statement * statement,int detailed,FILE * stream)358 raptor_print_statement_detailed(const raptor_statement * statement,
359                                 int detailed, FILE *stream)
360 {
361   raptor_print_statement(statement, stream);
362 }
363 #endif
364 
365 
366 #ifndef RAPTOR_DISABLE_V1
367 /**
368  * raptor_statement_part_as_counted_string:
369  * @term: #raptor_statement part (subject, predicate, object)
370  * @type: #raptor_statement part type
371  * @literal_datatype: #raptor_statement part datatype
372  * @literal_language: #raptor_statement part language
373  * @len_p: Pointer to location to store length of new string (if not NULL)
374  *
375  * Turns part of raptor statement into a N-Triples format counted string.
376  *
377  * Turns the given @term into an N-Triples escaped string using all the
378  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
379  *
380  * The part (subject, predicate, object) of the raptor_statement is
381  * typically passed in as @term, the part type (subject_type,
382  * predicate_type, object_type) is passed in as @type.  When the part
383  * is a literal, the @literal_datatype and @literal_language fields
384  * are set, otherwise NULL (usually object_datatype,
385  * object_literal_language).
386  *
387  * raptor_init() MUST have been called before calling this function.
388  * Use raptor_statement_part_as_counted_string_v2() if using raptor_world APIs.
389  *
390  * Return value: the new string or NULL on failure.  The length of
391  * the new string is returned in *@len_p if len_p is not NULL.
392  **/
393 unsigned char*
raptor_statement_part_as_counted_string(const void * term,raptor_identifier_type type,raptor_uri * literal_datatype,const unsigned char * literal_language,size_t * len_p)394 raptor_statement_part_as_counted_string(const void *term,
395                                         raptor_identifier_type type,
396                                         raptor_uri* literal_datatype,
397                                         const unsigned char *literal_language,
398                                         size_t* len_p)
399 {
400   return raptor_statement_part_as_counted_string_v2(raptor_world_instance(),
401                                                     term,
402                                                     type,
403                                                     literal_datatype,
404                                                     literal_language,
405                                                     len_p);
406 }
407 #endif
408 
409 
410 /**
411  * raptor_statement_part_as_counted_string_v2:
412  * @world: raptor_world object
413  * @term: #raptor_statement part (subject, predicate, object)
414  * @type: #raptor_statement part type
415  * @literal_datatype: #raptor_statement part datatype
416  * @literal_language: #raptor_statement part language
417  * @len_p: Pointer to location to store length of new string (if not NULL)
418  *
419  * Turns part of raptor statement into a N-Triples format counted string.
420  *
421  * Turns the given @term into an N-Triples escaped string using all the
422  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
423  *
424  * The part (subject, predicate, object) of the raptor_statement is
425  * typically passed in as @term, the part type (subject_type,
426  * predicate_type, object_type) is passed in as @type.  When the part
427  * is a literal, the @literal_datatype and @literal_language fields
428  * are set, otherwise NULL (usually object_datatype,
429  * object_literal_language).
430  *
431  * Return value: the new string or NULL on failure.  The length of
432  * the new string is returned in *@len_p if len_p is not NULL.
433  **/
434 unsigned char*
raptor_statement_part_as_counted_string_v2(raptor_world * world,const void * term,raptor_identifier_type type,raptor_uri * literal_datatype,const unsigned char * literal_language,size_t * len_p)435 raptor_statement_part_as_counted_string_v2(raptor_world* world,
436                                            const void *term,
437                                            raptor_identifier_type type,
438                                            raptor_uri* literal_datatype,
439                                            const unsigned char *literal_language,
440                                            size_t* len_p)
441 {
442   size_t len=0, term_len, uri_len;
443   size_t language_len=0;
444   unsigned char *s, *buffer=NULL;
445   unsigned char *uri_string=NULL;
446 
447   switch(type) {
448     case RAPTOR_IDENTIFIER_TYPE_LITERAL:
449     case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
450       term_len=strlen((const char*)term);
451       len=2+term_len;
452       if(literal_language && type == RAPTOR_IDENTIFIER_TYPE_LITERAL) {
453         language_len=strlen((const char*)literal_language);
454         len+= language_len+1;
455       }
456       if(type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL)
457         len += 4+raptor_xml_literal_datatype_uri_string_len;
458       else if(literal_datatype) {
459         uri_string=raptor_uri_as_counted_string_v2(world, (raptor_uri*)literal_datatype, &uri_len);
460         len += 4+uri_len;
461       }
462 
463       buffer=(unsigned char*)RAPTOR_MALLOC(cstring, len+1);
464       if(!buffer)
465         return NULL;
466 
467       s=buffer;
468       *s++ ='"';
469       /* raptor_print_ntriples_string(stream, (const char*)term, '"'); */
470       strcpy((char*)s, (const char*)term);
471       s+= term_len;
472       *s++ ='"';
473       if(literal_language && type == RAPTOR_IDENTIFIER_TYPE_LITERAL) {
474         *s++ ='@';
475         strcpy((char*)s, (const char*)literal_language);
476         s+= language_len;
477       }
478 
479       if(type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
480         *s++ ='^';
481         *s++ ='^';
482         *s++ ='<';
483         strcpy((char*)s, (const char*)raptor_xml_literal_datatype_uri_string);
484         s+= raptor_xml_literal_datatype_uri_string_len;
485         *s++ ='>';
486       } else if(literal_datatype) {
487         *s++ ='^';
488         *s++ ='^';
489         *s++ ='<';
490         strcpy((char*)s, (const char*)uri_string);
491         s+= uri_len;
492         *s++ ='>';
493       }
494       *s++ ='\0';
495 
496       break;
497 
498     case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
499       len=2+strlen((const char*)term);
500       buffer=(unsigned char*)RAPTOR_MALLOC(cstring, len+1);
501       if(!buffer)
502         return NULL;
503       s=buffer;
504       *s++ ='_';
505       *s++ =':';
506       strcpy((char*)s, (const char*)term);
507       break;
508 
509     case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
510       len=raptor_rdf_namespace_uri_len + 13;
511       buffer=(unsigned char*)RAPTOR_MALLOC(cstring, len+1);
512       if(!buffer)
513         return NULL;
514 
515       sprintf((char*)buffer, "<%s_%d>",
516               raptor_rdf_namespace_uri, *((int*)term));
517       break;
518 
519     case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
520     case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
521       uri_string=raptor_uri_as_counted_string_v2(world, (raptor_uri*)term, &uri_len);
522       len=2+uri_len;
523       buffer=(unsigned char*)RAPTOR_MALLOC(cstring, len+1);
524       if(!buffer)
525         return NULL;
526 
527       s=buffer;
528       *s++ ='<';
529       /* raptor_print_ntriples_string(stream, raptor_uri_as_string((raptor_uri*)term), '\0'); */
530       strcpy((char*)s, (const char*)uri_string);
531       s+= uri_len;
532       *s++ ='>';
533       *s++ ='\0';
534       break;
535 
536     case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
537     default:
538       RAPTOR_FATAL2("Unknown type %d", type);
539   }
540 
541   if(len_p)
542     *len_p=len;
543 
544  return buffer;
545 }
546 
547 
548 #ifndef RAPTOR_DISABLE_V1
549 /**
550  * raptor_statement_part_as_string:
551  * @term: #raptor_statement part (subject, predicate, object)
552  * @type: #raptor_statement part type
553  * @literal_datatype: #raptor_statement part datatype
554  * @literal_language: #raptor_statement part language
555  *
556  * Turns part of raptor statement into a N-Triples format string.
557  *
558  * Turns the given @term into an N-Triples escaped string using all the
559  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
560  *
561  * The part (subject, predicate, object) of the raptor_statement is
562  * typically passed in as @term, the part type (subject_type,
563  * predicate_type, object_type) is passed in as @type.  When the part
564  * is a literal, the @literal_datatype and @literal_language fields
565  * are set, otherwise NULL (usually object_datatype,
566  * object_literal_language).
567  *
568  * raptor_init() MUST have been called before calling this function.
569  * Use raptor_statement_part_as_string_v2() if using raptor_world APIs.
570  *
571  * Return value: the new string or NULL on failure.
572  **/
573 unsigned char*
raptor_statement_part_as_string(const void * term,raptor_identifier_type type,raptor_uri * literal_datatype,const unsigned char * literal_language)574 raptor_statement_part_as_string(const void *term,
575                                 raptor_identifier_type type,
576                                 raptor_uri* literal_datatype,
577                                 const unsigned char *literal_language)
578 {
579   return raptor_statement_part_as_string_v2(raptor_world_instance(),
580                                             term,
581                                             type,
582                                             literal_datatype,
583                                             literal_language);
584 }
585 #endif
586 
587 
588 /**
589  * raptor_statement_part_as_string_v2:
590  * @world: raptor_world object
591  * @term: #raptor_statement part (subject, predicate, object)
592  * @type: #raptor_statement part type
593  * @literal_datatype: #raptor_statement part datatype
594  * @literal_language: #raptor_statement part language
595  *
596  * Turns part of raptor statement into a N-Triples format string.
597  *
598  * Turns the given @term into an N-Triples escaped string using all the
599  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
600  *
601  * The part (subject, predicate, object) of the raptor_statement is
602  * typically passed in as @term, the part type (subject_type,
603  * predicate_type, object_type) is passed in as @type.  When the part
604  * is a literal, the @literal_datatype and @literal_language fields
605  * are set, otherwise NULL (usually object_datatype,
606  * object_literal_language).
607  *
608  * Return value: the new string or NULL on failure.
609  **/
610 unsigned char*
raptor_statement_part_as_string_v2(raptor_world * world,const void * term,raptor_identifier_type type,raptor_uri * literal_datatype,const unsigned char * literal_language)611 raptor_statement_part_as_string_v2(raptor_world* world,
612                                    const void *term,
613                                    raptor_identifier_type type,
614                                    raptor_uri* literal_datatype,
615                                    const unsigned char *literal_language)
616 {
617   return raptor_statement_part_as_counted_string_v2(world, term, type,
618                                                     literal_datatype,
619                                                     literal_language,
620                                                     NULL);
621 }
622 
623 
624 static void
raptor_print_statement_part_as_ntriples(raptor_world * world,FILE * stream,const void * term,raptor_identifier_type type,raptor_uri * literal_datatype,const unsigned char * literal_language)625 raptor_print_statement_part_as_ntriples(raptor_world* world,
626                                         FILE* stream,
627                                         const void *term,
628                                         raptor_identifier_type type,
629                                         raptor_uri* literal_datatype,
630                                         const unsigned char *literal_language)
631 {
632   switch(type) {
633     case RAPTOR_IDENTIFIER_TYPE_LITERAL:
634     case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
635       fputc('"', stream);
636       raptor_print_ntriples_string(stream, (const unsigned char*)term, '"');
637       fputc('"', stream);
638       if(literal_language && type == RAPTOR_IDENTIFIER_TYPE_LITERAL) {
639         fputc('@', stream);
640         fputs((const char*)literal_language, stream);
641       }
642       if(type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
643         fputs("^^<", stream);
644         fputs((const char*)raptor_xml_literal_datatype_uri_string, stream);
645         fputc('>', stream);
646       } else if(literal_datatype) {
647         fputs("^^<", stream);
648         fputs((const char*)raptor_uri_as_string_v2(world, (raptor_uri*)literal_datatype), stream);
649         fputc('>', stream);
650       }
651 
652       break;
653 
654     case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
655       fputs("_:", stream);
656       fputs((const char*)term, stream);
657       break;
658 
659     case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
660       fprintf(stream, "<%s_%d>",
661               raptor_rdf_namespace_uri, *((int*)term));
662       break;
663 
664     case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
665     case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
666       fputc('<', stream);
667       raptor_print_ntriples_string(stream, raptor_uri_as_string_v2(world, (raptor_uri*)term), '\0');
668       fputc('>', stream);
669       break;
670 
671     case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
672     default:
673       RAPTOR_FATAL2("Unknown type %d", type);
674   }
675 }
676 
677 
678 #ifndef RAPTOR_DISABLE_V1
679 /**
680  * raptor_print_statement_as_ntriples:
681  * @statement: #raptor_statement to print
682  * @stream: #FILE* stream
683  *
684  * Print a raptor_statement in N-Triples form.
685  *
686  * raptor_init() MUST have been called before calling this function.
687  * Use raptor_print_statement_as_ntriples_v2() if using raptor_world APIs.
688  *
689  **/
690 void
raptor_print_statement_as_ntriples(const raptor_statement * statement,FILE * stream)691 raptor_print_statement_as_ntriples(const raptor_statement * statement,
692                                    FILE *stream)
693 {
694   raptor_print_statement_as_ntriples_common(raptor_world_instance(),
695                                             statement,
696                                             stream);
697 }
698 #endif
699 
700 
701 /**
702  * raptor_print_statement_as_ntriples_v2:
703  * @statement: #raptor_statement_v2 to print
704  * @stream: #FILE* stream
705  *
706  * Print a raptor_statement in N-Triples form.
707  *
708  **/
709 void
raptor_print_statement_as_ntriples_v2(const raptor_statement_v2 * statement,FILE * stream)710 raptor_print_statement_as_ntriples_v2(const raptor_statement_v2 * statement,
711                                       FILE *stream)
712 {
713   raptor_print_statement_as_ntriples_common(statement->world,
714                                             statement->s,
715                                             stream);
716 }
717 
718 
719 static void
raptor_print_statement_as_ntriples_common(raptor_world * world,const raptor_statement * statement,FILE * stream)720 raptor_print_statement_as_ntriples_common(raptor_world* world,
721                                           const raptor_statement *statement,
722                                           FILE *stream)
723 {
724   raptor_print_statement_part_as_ntriples(world,
725                                           stream,
726                                           statement->subject,
727                                           statement->subject_type,
728                                           NULL, NULL);
729   fputc(' ', stream);
730   raptor_print_statement_part_as_ntriples(world,
731                                           stream,
732                                           statement->predicate,
733                                           statement->predicate_type,
734                                           NULL, NULL);
735   fputc(' ', stream);
736   raptor_print_statement_part_as_ntriples(world,
737                                           stream,
738                                           statement->object,
739                                           statement->object_type,
740                                           statement->object_literal_datatype,
741                                           statement->object_literal_language);
742   fputs(" .", stream);
743 }
744 
745 
746 #ifndef RAPTOR_DISABLE_V1
747 /**
748  * raptor_statement_compare:
749  * @s1: first statement
750  * @s2: second statement
751  *
752  * Compare a pair of #raptor_statement
753  *
754  * If types are different, the #raptor_identifier_type order is used.
755  * Resource and datatype URIs are compared with raptor_uri_compare(),
756  * blank nodes and literals with strcmp().  If one literal has no
757  * language, it is earlier than one with a language.  If one literal
758  * has no datatype, it is earlier than one with a datatype.
759  *
760  * raptor_init() MUST have been called before calling this function.
761  * Use raptor_statement_compare_v2() if using raptor_world APIs.
762  *
763  * Return value: <0 if s1 is before s2, 0 if equal, >0 if s1 is after s2
764  */
765 int
raptor_statement_compare(const raptor_statement * s1,const raptor_statement * s2)766 raptor_statement_compare(const raptor_statement *s1,
767                          const raptor_statement *s2)
768 {
769   return raptor_statement_compare_common(raptor_world_instance(), s1, s2);
770 }
771 #endif
772 
773 
774 /**
775  * raptor_statement_compare_v2:
776  * @s1: first statement
777  * @s2: second statement
778  *
779  * Compare a pair of #raptor_statement_v2
780  *
781  * If types are different, the #raptor_identifier_type order is used.
782  * Resource and datatype URIs are compared with raptor_uri_compare(),
783  * blank nodes and literals with strcmp().  If one literal has no
784  * language, it is earlier than one with a language.  If one literal
785  * has no datatype, it is earlier than one with a datatype.
786  *
787  * Return value: <0 if s1 is before s2, 0 if equal, >0 if s1 is after s2
788  */
789 int
raptor_statement_compare_v2(const raptor_statement_v2 * s1,const raptor_statement_v2 * s2)790 raptor_statement_compare_v2(const raptor_statement_v2 *s1,
791                             const raptor_statement_v2 *s2)
792 {
793   return raptor_statement_compare_common(s1->world, s1->s, s2->s);
794 }
795 
796 
797 static int
raptor_statement_compare_common(raptor_world * world,const raptor_statement * s1,const raptor_statement * s2)798 raptor_statement_compare_common(raptor_world* world,
799                                 const raptor_statement *s1,
800                                 const raptor_statement *s2)
801 {
802   int d=0;
803 
804   if(s1->subject && s2->subject) {
805     d=s1->subject_type != s2->subject_type;
806     if(d)
807       return d;
808 
809     /* subjects are URIs or blank nodes */
810     if(s1->subject_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS)
811       d=strcmp((char*)s1->subject, (char*)s2->subject);
812     else
813       d=raptor_uri_compare_v2(world,
814                               (raptor_uri*)s1->subject,
815                               (raptor_uri*)s2->subject);
816   } else if(s1->subject || s2->subject)
817     d=(!s1->subject ? -1 : 1);
818   if(d)
819     return d;
820 
821 
822   /* predicates are URIs */
823   if(s1->predicate && s2->predicate) {
824     d=raptor_uri_compare_v2(world,
825                             (raptor_uri*)s1->predicate,
826                             (raptor_uri*)s2->predicate);
827   } else if(s1->predicate || s2->predicate)
828     d=(!s1->predicate ? -1 : 1);
829   if(d)
830     return d;
831 
832 
833   /* objects are URIs or blank nodes or literals */
834   if(s1->object && s2->object) {
835     if(s1->object_type == RAPTOR_IDENTIFIER_TYPE_LITERAL ||
836        s1->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
837       d=strcmp((char*)s1->object, (char*)s2->object);
838       if(d)
839         return d;
840 
841       if(s1->object_literal_language && s2->object_literal_language) {
842         /* both have a language */
843         d=strcmp((char*)s1->object_literal_language,
844                  (char*)s2->object_literal_language);
845       } else if(s1->object_literal_language || s2->object_literal_language)
846         /* only one has a language; the language-less one is earlier */
847         d=(!s1->object_literal_language ? -1 : 1);
848       if(d)
849         return d;
850 
851       if(s1->object_literal_datatype && s2->object_literal_datatype) {
852         /* both have a datatype */
853         d=raptor_uri_compare_v2(world,
854                                 (raptor_uri*)s1->object_literal_datatype,
855                                 (raptor_uri*)s2->object_literal_datatype);
856       } else if(s1->object_literal_datatype || s2->object_literal_datatype)
857         /* only one has a datatype; the datatype-less one is earlier */
858         d=(!s1->object_literal_datatype ? -1 : 1);
859       if(d)
860         return d;
861 
862     } else if(s1->object_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS)
863       d=strcmp((char*)s1->object, (char*)s2->object);
864     else
865       d=raptor_uri_compare_v2(world, (raptor_uri*)s1->object, (raptor_uri*)s2->object);
866   } else if(s1->object || s2->object)
867     d=(!s1->object ? -1 : 1);
868 
869   return d;
870 }
871