1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * raptor_term.c - Raptor terms
4  *
5  * Copyright (C) 2010, 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 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <stdarg.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 
35 /* Raptor includes */
36 #include "raptor2.h"
37 #include "raptor_internal.h"
38 
39 
40 #ifndef STANDALONE
41 
42 /**
43  * raptor_new_term_from_uri:
44  * @world: raptor world
45  * @uri: uri
46  *
47  * Constructor - create a new URI statement term
48  *
49  * Takes a copy (reference) of the passed in @uri
50  *
51  * Return value: new term or NULL on failure
52 */
53 raptor_term*
raptor_new_term_from_uri(raptor_world * world,raptor_uri * uri)54 raptor_new_term_from_uri(raptor_world* world, raptor_uri* uri)
55 {
56   raptor_term *t;
57 
58   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
59 
60   if(!uri)
61     return NULL;
62 
63   raptor_world_open(world);
64 
65   t = RAPTOR_CALLOC(raptor_term*, 1, sizeof(*t));
66   if(!t)
67     return NULL;
68 
69   t->usage = 1;
70   t->world = world;
71   t->type = RAPTOR_TERM_TYPE_URI;
72   t->value.uri = raptor_uri_copy(uri);
73 
74   return t;
75 }
76 
77 
78 /**
79  * raptor_new_term_from_counted_uri_string:
80  * @world: raptor world
81  * @uri_string: UTF-8 encoded URI string.
82  * @length: length of URI string
83  *
84  * Constructor - create a new URI statement term from a UTF-8 encoded Unicode string
85  *
86  * Note: The @uri_string need not be NULL terminated - a NULL will be
87  * added to the copied string used.
88  *
89  * Return value: new term or NULL on failure
90 */
91 raptor_term*
raptor_new_term_from_counted_uri_string(raptor_world * world,const unsigned char * uri_string,size_t length)92 raptor_new_term_from_counted_uri_string(raptor_world* world,
93                                         const unsigned char *uri_string,
94                                         size_t length)
95 {
96   raptor_term *t;
97   raptor_uri* uri;
98 
99   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
100 
101   uri = raptor_new_uri_from_counted_string(world, uri_string, length);
102   if(!uri)
103     return NULL;
104 
105   t = raptor_new_term_from_uri(world, uri);
106 
107   raptor_free_uri(uri);
108 
109   return t;
110 }
111 
112 
113 /**
114  * raptor_new_term_from_uri_string:
115  * @world: raptor world
116  * @uri_string: UTF-8 encoded URI string.
117  *
118  * Constructor - create a new URI statement term from a UTF-8 encoded Unicode string
119  *
120  * Return value: new term or NULL on failure
121 */
122 raptor_term*
raptor_new_term_from_uri_string(raptor_world * world,const unsigned char * uri_string)123 raptor_new_term_from_uri_string(raptor_world* world,
124                                 const unsigned char *uri_string)
125 {
126   raptor_term *t;
127   raptor_uri* uri;
128 
129   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
130 
131   uri = raptor_new_uri(world, uri_string);
132   if(!uri)
133     return NULL;
134 
135   t = raptor_new_term_from_uri(world, uri);
136 
137   raptor_free_uri(uri);
138 
139   return t;
140 }
141 
142 
143 /**
144  * raptor_new_term_from_counted_literal:
145  * @world: raptor world
146  * @literal: UTF-8 encoded literal string (or NULL for empty literal)
147  * @literal_len: length of literal
148  * @datatype: literal datatype URI (or NULL)
149  * @language: literal language (or NULL for no language)
150  * @language_len: literal language length
151  *
152  * Constructor - create a new literal statement term from a counted UTF-8 encoded literal string
153  *
154  * Takes copies of the passed in @literal, @datatype, @language
155  *
156  * Only one of @language or @datatype may be given.  If both are
157  * given, NULL is returned.  If @language is the empty string, it is
158  * the equivalent to NULL.
159  *
160  * Note: The @literal need not be NULL terminated - a NULL will be
161  * added to the copied string used.
162  *
163  * Return value: new term or NULL on failure
164  */
165 raptor_term*
raptor_new_term_from_counted_literal(raptor_world * world,const unsigned char * literal,size_t literal_len,raptor_uri * datatype,const unsigned char * language,unsigned char language_len)166 raptor_new_term_from_counted_literal(raptor_world* world,
167                                      const unsigned char* literal,
168                                      size_t literal_len,
169                                      raptor_uri* datatype,
170                                      const unsigned char* language,
171                                      unsigned char language_len)
172 {
173   raptor_term *t;
174   unsigned char* new_literal = NULL;
175   unsigned char* new_language = NULL;
176 
177   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
178 
179   raptor_world_open(world);
180 
181   if(language && !*language)
182     language = NULL;
183 
184   if(language && datatype)
185     return NULL;
186 
187 
188   new_literal = RAPTOR_MALLOC(unsigned char*, literal_len + 1);
189   if(!new_literal)
190     return NULL;
191 
192   if(!literal || !*literal)
193     literal_len = 0;
194 
195   if(literal_len) {
196     memcpy(new_literal, literal, literal_len);
197     new_literal[literal_len] = '\0';
198   } else
199     *new_literal = '\0';
200 
201   if(language) {
202     unsigned char c;
203     unsigned char* l;
204 
205     new_language = RAPTOR_MALLOC(unsigned char*, language_len + 1);
206     if(!new_language) {
207       RAPTOR_FREE(char*, new_literal);
208       return NULL;
209     }
210 
211     l = new_language;
212     while((c = *language++)) {
213       if(c == '_')
214         c = '-';
215       *l++ = c;
216     }
217     *l = '\0';
218   } else
219     language_len = 0;
220 
221   if(datatype)
222     datatype = raptor_uri_copy(datatype);
223 
224 
225   t = RAPTOR_CALLOC(raptor_term*, 1, sizeof(*t));
226   if(!t) {
227     if(new_literal)
228       RAPTOR_FREE(char*, new_literal);
229     if(new_language)
230       RAPTOR_FREE(char*, new_language);
231     if(datatype)
232       raptor_free_uri(datatype);
233     return NULL;
234   }
235   t->usage = 1;
236   t->world = world;
237   t->type = RAPTOR_TERM_TYPE_LITERAL;
238   t->value.literal.string = new_literal;
239   t->value.literal.string_len = RAPTOR_LANG_LEN_FROM_INT(literal_len);
240   t->value.literal.language = new_language;
241   t->value.literal.language_len = language_len;
242   t->value.literal.datatype = datatype;
243 
244   return t;
245 }
246 
247 
248 /**
249  * raptor_new_term_from_literal:
250  * @world: raptor world
251  * @literal: UTF-8 encoded literal string (or NULL for empty literal)
252  * @datatype: literal datatype URI (or NULL)
253  * @language: literal language (or NULL)
254  *
255  * Constructor - create a new literal statement term
256  *
257  * Takes copies of the passed in @literal, @datatype, @language
258  *
259  * Only one of @language or @datatype may be given.  If both are
260  * given, NULL is returned.  If @language is the empty string, it is
261  * the equivalent to NULL.
262  *
263  * Return value: new term or NULL on failure
264 */
265 raptor_term*
raptor_new_term_from_literal(raptor_world * world,const unsigned char * literal,raptor_uri * datatype,const unsigned char * language)266 raptor_new_term_from_literal(raptor_world* world,
267                              const unsigned char* literal,
268                              raptor_uri* datatype,
269                              const unsigned char* language)
270 {
271   size_t literal_len = 0;
272   size_t language_len = 0;
273 
274   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
275 
276   raptor_world_open(world);
277 
278   if(literal)
279     literal_len = strlen(RAPTOR_GOOD_CAST(const char*, literal));
280 
281   if(language)
282     language_len = strlen(RAPTOR_GOOD_CAST(const char*, language));
283 
284   return raptor_new_term_from_counted_literal(world, literal, literal_len,
285                                               datatype, language,
286                                               RAPTOR_BAD_CAST(unsigned char, language_len));
287 }
288 
289 
290 /**
291  * raptor_new_term_from_counted_blank:
292  * @world: raptor world
293  * @blank: UTF-8 encoded blank node identifier (or NULL)
294  * @length: length of identifier (or 0)
295  *
296  * Constructor - create a new blank node statement term from a counted UTF-8 encoded blank node ID
297  *
298  * Takes a copy of the passed in @blank
299  *
300  * If @blank is NULL, creates a new internal identifier and uses it.
301  * This will use the handler set with
302  * raptor_world_set_generate_bnodeid_parameters()
303  *
304  * Note: The @blank need not be NULL terminated - a NULL will be
305  * added to the copied string used.
306  *
307  * Return value: new term or NULL on failure
308 */
309 raptor_term*
raptor_new_term_from_counted_blank(raptor_world * world,const unsigned char * blank,size_t length)310 raptor_new_term_from_counted_blank(raptor_world* world,
311                                    const unsigned char* blank, size_t length)
312 {
313   raptor_term *t;
314   unsigned char* new_id;
315 
316   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
317 
318   raptor_world_open(world);
319 
320   if (blank) {
321     new_id = RAPTOR_MALLOC(unsigned char*, length + 1);
322     if(!new_id)
323       return NULL;
324     memcpy(new_id, blank, length);
325     new_id[length] = '\0';
326   } else {
327     new_id = raptor_world_generate_bnodeid(world);
328     length = strlen((const char*)new_id);
329   }
330 
331   t = RAPTOR_CALLOC(raptor_term*, 1, sizeof(*t));
332   if(!t) {
333     RAPTOR_FREE(char*, new_id);
334     return NULL;
335   }
336 
337   t->usage = 1;
338   t->world = world;
339   t->type = RAPTOR_TERM_TYPE_BLANK;
340   t->value.blank.string = new_id;
341   t->value.blank.string_len = RAPTOR_BAD_CAST(int, length);
342 
343   return t;
344 }
345 
346 
347 /**
348  * raptor_new_term_from_blank:
349  * @world: raptor world
350  * @blank: UTF-8 encoded blank node identifier (or NULL)
351  *
352  * Constructor - create a new blank node statement term from a UTF-8 encoded blank node ID
353  *
354  * Takes a copy of the passed in @blank
355  *
356  * If @blank is NULL or an empty string, creates a new internal
357  * identifier and uses it.  This will use the handler set with
358  * raptor_world_set_generate_bnodeid_parameters()
359  *
360  * Return value: new term or NULL on failure
361 */
362 raptor_term*
raptor_new_term_from_blank(raptor_world * world,const unsigned char * blank)363 raptor_new_term_from_blank(raptor_world* world, const unsigned char* blank)
364 {
365   size_t length = 0;
366 
367   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
368 
369   raptor_world_open(world);
370 
371   if(blank) {
372     if(*blank)
373       length = strlen((const char*)blank);
374     else
375       blank = NULL;
376   }
377 
378   return raptor_new_term_from_counted_blank(world, blank, length);
379 }
380 
381 
382 /**
383  * raptor_new_term_from_counted_string:
384  * @world: raptor world
385  * @string: N-Triples format string (UTF-8)
386  * @length: length of @string (or 0)
387  *
388  * Constructor - create a new term from a Turtle / N-Triples format string in UTF-8
389  *
390  * See also raptor_term_to_counted_string() and raptor_term_to_string()
391  *
392  * Return value: new term or NULL on failure
393 */
394 raptor_term*
raptor_new_term_from_counted_string(raptor_world * world,unsigned char * string,size_t length)395 raptor_new_term_from_counted_string(raptor_world* world,
396                                     unsigned char* string, size_t length)
397 {
398   raptor_term* term = NULL;
399   size_t bytes_read;
400   raptor_locator locator;
401 
402   RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
403 
404   if(!string)
405     return NULL;
406 
407   if(!length)
408     length = strlen(RAPTOR_GOOD_CAST(const char*, string));
409 
410   raptor_world_open(world);
411 
412   memset(&locator, '\0', sizeof(locator));
413   locator.line = -1;
414 
415   bytes_read = raptor_ntriples_parse_term(world, &locator,
416                                           string, &length, &term, 1);
417 
418   if(!bytes_read || length != 0) {
419     if(term)
420       raptor_free_term(term);
421     term = NULL;
422   }
423 
424   return term;
425 }
426 
427 
428 /**
429  * raptor_term_copy:
430  * @term: raptor term
431  *
432  * Copy constructor - get a copy of a statement term
433  *
434  * Return value: new term object or NULL on failure
435  */
436 raptor_term*
raptor_term_copy(raptor_term * term)437 raptor_term_copy(raptor_term* term)
438 {
439   if(!term)
440     return NULL;
441 
442   term->usage++;
443   return term;
444 }
445 
446 
447 /**
448  * raptor_free_term:
449  * @term: #raptor_term object
450  *
451  * Destructor - destroy a raptor_term object.
452  *
453  **/
454 void
raptor_free_term(raptor_term * term)455 raptor_free_term(raptor_term *term)
456 {
457   if(!term)
458     return;
459 
460   if(--term->usage)
461     return;
462 
463   switch(term->type) {
464     case RAPTOR_TERM_TYPE_URI:
465       if(term->value.uri) {
466         raptor_free_uri(term->value.uri);
467         term->value.uri = NULL;
468       }
469       break;
470 
471     case RAPTOR_TERM_TYPE_BLANK:
472       if(term->value.blank.string) {
473         RAPTOR_FREE(char*, term->value.blank.string);
474         term->value.blank.string = NULL;
475       }
476       break;
477 
478     case RAPTOR_TERM_TYPE_LITERAL:
479       if(term->value.literal.string) {
480         RAPTOR_FREE(char*, term->value.literal.string);
481         term->value.literal.string = NULL;
482       }
483 
484       if(term->value.literal.datatype) {
485         raptor_free_uri(term->value.literal.datatype);
486         term->value.literal.datatype = NULL;
487       }
488 
489       if(term->value.literal.language) {
490         RAPTOR_FREE(char*, term->value.literal.language);
491         term->value.literal.language = NULL;
492       }
493       break;
494 
495     case RAPTOR_TERM_TYPE_UNKNOWN:
496     default:
497       break;
498   }
499 
500   RAPTOR_FREE(term, term);
501 }
502 
503 
504 /**
505  * raptor_term_to_counted_string:
506  * @term: #raptor_term
507  * @len_p: Pointer to location to store length of new string (if not NULL)
508  *
509  * Turns a raptor term into a N-Triples format counted string.
510  *
511  * Turns the given @term into an N-Triples escaped string using all the
512  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
513  *
514  * This function uses raptor_term_ntriples_write() to write to an
515  * #raptor_iostream which is the prefered way to write formatted
516  * output.
517  *
518  * See also raptor_new_term_from_counted_string() to reverse this.
519  *
520  * See also raptor_term_to_turtle_string() to write as Turtle which
521  * will include Turtle syntax such as 'true' for booleans and """quoting"""
522  *
523  * Return value: the new string or NULL on failure.  The length of
524  * the new string is returned in *@len_p if len_p is not NULL.
525  **/
526 unsigned char*
raptor_term_to_counted_string(raptor_term * term,size_t * len_p)527 raptor_term_to_counted_string(raptor_term *term, size_t* len_p)
528 {
529   raptor_iostream *iostr;
530   void *string = NULL;
531   int rc;
532 
533   RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(term, raptor_term, NULL);
534 
535   iostr = raptor_new_iostream_to_string(term->world,
536                                         &string, len_p, NULL);
537   if(!iostr)
538     return NULL;
539 
540   rc = raptor_term_escaped_write(term, 0, iostr);
541   raptor_free_iostream(iostr);
542 
543   if(rc) {
544     if(string) {
545       RAPTOR_FREE(char*, string);
546       string = NULL;
547     }
548   }
549 
550   return (unsigned char *)string;
551 }
552 
553 
554 /**
555  * raptor_term_to_string:
556  * @term: #raptor_term
557  *
558  * Turns a raptor term into a N-Triples format string.
559  *
560  * Turns the given @term into an N-Triples escaped string using all the
561  * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples
562  *
563  * See also raptor_new_term_from_counted_string() to reverse this.
564  *
565  * See also raptor_term_to_turtle_string() to write as Turtle which
566  * will include Turtle syntax such as 'true' for booleans and """quoting"""
567  *
568  * Return value: the new string or NULL on failure.
569  **/
570 unsigned char*
raptor_term_to_string(raptor_term * term)571 raptor_term_to_string(raptor_term *term)
572 {
573   RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(term, raptor_term, NULL);
574 
575   return raptor_term_to_counted_string(term, NULL);
576 }
577 
578 
579 /*
580  * raptor_term_print_as_ntriples:
581  * @term: #raptor_term
582  * @stream: FILE stream
583  *
584  * INTERNAL - Print a term as N-Triples
585  */
586 int
raptor_term_print_as_ntriples(const raptor_term * term,FILE * stream)587 raptor_term_print_as_ntriples(const raptor_term *term, FILE* stream)
588 {
589   int rc = 0;
590   raptor_iostream* iostr;
591 
592   RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(term, raptor_term, 1);
593   RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, FILE*, 1);
594 
595   iostr = raptor_new_iostream_to_file_handle(term->world, stream);
596   if(!iostr)
597     return 1;
598 
599   rc = raptor_term_escaped_write(term, 0, iostr);
600 
601   raptor_free_iostream(iostr);
602 
603   return rc;
604 }
605 
606 
607 /**
608  * raptor_term_equals:
609  * @t1: first term
610  * @t2: second term
611  *
612  * Compare a pair of #raptor_term for equality
613  *
614  * Return value: non-0 if the terms are equal
615  */
616 int
raptor_term_equals(raptor_term * t1,raptor_term * t2)617 raptor_term_equals(raptor_term* t1, raptor_term* t2)
618 {
619   int d = 0;
620 
621   if(!t1 || !t2)
622     return 0;
623 
624   if(t1->type != t2->type)
625     return 0;
626 
627   if(t1 == t2)
628     return 1;
629 
630   switch(t1->type) {
631     case RAPTOR_TERM_TYPE_URI:
632       d = raptor_uri_equals(t1->value.uri, t2->value.uri);
633       break;
634 
635     case RAPTOR_TERM_TYPE_BLANK:
636       if(t1->value.blank.string_len != t2->value.blank.string_len)
637         /* different lengths */
638         break;
639 
640       d = !strcmp((const char*)t1->value.blank.string,
641                   (const char*)t2->value.blank.string);
642       break;
643 
644     case RAPTOR_TERM_TYPE_LITERAL:
645       if(t1->value.literal.string_len != t2->value.literal.string_len)
646         /* different lengths */
647         break;
648 
649       d = !strcmp((const char*)t1->value.literal.string,
650                   (const char*)t2->value.literal.string);
651       if(!d)
652         break;
653 
654       if(t1->value.literal.language && t2->value.literal.language) {
655         /* both have a language */
656         d = !strcmp((const char*)t1->value.literal.language,
657                     (const char*)t2->value.literal.language);
658         if(!d)
659           break;
660       } else if(t1->value.literal.language || t2->value.literal.language) {
661         /* only one has a language - different */
662         d = 0;
663         break;
664       }
665 
666       if(t1->value.literal.datatype && t2->value.literal.datatype) {
667         /* both have a datatype */
668         d = raptor_uri_equals(t1->value.literal.datatype,
669                               t2->value.literal.datatype);
670       } else if(t1->value.literal.datatype || t2->value.literal.datatype) {
671         /* only one has a datatype - different */
672         d = 0;
673       }
674       break;
675 
676     case RAPTOR_TERM_TYPE_UNKNOWN:
677     default:
678       break;
679   }
680 
681   return d;
682 }
683 
684 
685 /**
686  * raptor_term_compare:
687  * @t1: first term
688  * @t2: second term
689  *
690  * Compare a pair of #raptor_term
691  *
692  * If types are different, the #raptor_term_type order is used.
693  *
694  * Resource and datatype URIs are compared with raptor_uri_compare(),
695  * blank nodes and literals with strcmp().  If one literal has no
696  * language, it is earlier than one with a language.  If one literal
697  * has no datatype, it is earlier than one with a datatype.
698  *
699  * Return value: <0 if t1 is before t2, 0 if equal, >0 if t1 is after t2
700  */
701 int
raptor_term_compare(const raptor_term * t1,const raptor_term * t2)702 raptor_term_compare(const raptor_term *t1,  const raptor_term *t2)
703 {
704   int d = 0;
705 
706   /* check for NULL terms */
707   if(!t1 || !t2) {
708     if(!t1 && !t2)
709       return 0; /* both NULL */
710 
711     /* place NULLs before any other term */
712     return t1 ? 1 : -1;
713   }
714 
715   if(t1->type != t2->type)
716     return (t1->type - t2->type);
717 
718   switch(t1->type) {
719     case RAPTOR_TERM_TYPE_URI:
720       d = raptor_uri_compare(t1->value.uri, t2->value.uri);
721       break;
722 
723     case RAPTOR_TERM_TYPE_BLANK:
724       d = strcmp((const char*)t1->value.blank.string,
725                  (const char*)t2->value.blank.string);
726       break;
727 
728     case RAPTOR_TERM_TYPE_LITERAL:
729       d = strcmp((const char*)t1->value.literal.string,
730                  (const char*)t2->value.literal.string);
731       if(d)
732         break;
733 
734       if(t1->value.literal.language && t2->value.literal.language) {
735         /* both have a language */
736         d = strcmp((const char*)t1->value.literal.language,
737                    (const char*)t2->value.literal.language);
738       } else if(t1->value.literal.language || t2->value.literal.language)
739         /* only one has a language; the language-less one is earlier */
740         d = (!t1->value.literal.language ? -1 : 1);
741       if(d)
742         break;
743 
744       if(t1->value.literal.datatype && t2->value.literal.datatype) {
745         /* both have a datatype */
746         d = raptor_uri_compare(t1->value.literal.datatype,
747                                t2->value.literal.datatype);
748       } else if(t1->value.literal.datatype || t2->value.literal.datatype)
749         /* only one has a datatype; the datatype-less one is earlier */
750         d = (!t1->value.literal.datatype ? -1 : 1);
751       break;
752 
753     case RAPTOR_TERM_TYPE_UNKNOWN:
754     default:
755       break;
756   }
757 
758   return d;
759 }
760 #endif
761 
762 
763 
764 #ifdef STANDALONE
765 
766 /* one more prototype */
767 int main(int argc, char *argv[]);
768 
769 static const unsigned char *uri_string1 = (const unsigned char *)"http://http://www.dajobe.org/";
770 static unsigned int uri_string1_len = 29; /* strlen(uri_string1) */
771 static raptor_term_type uri_string1_type = RAPTOR_TERM_TYPE_URI;
772 static const unsigned char *uri_string2 = (const unsigned char *)"http://www.example.org/";
773 static unsigned int uri_string2_len = 23; /* strlen(uri_string2) */
774 static raptor_term_type uri_string2_type = RAPTOR_TERM_TYPE_URI;
775 static const unsigned char *literal_string1 = (const unsigned char *)"Dave Beckett";
776 static unsigned int literal_string1_len = 12; /* strlen(literal_string1) */
777 static raptor_term_type literal_string1_type = RAPTOR_TERM_TYPE_LITERAL;
778 static const unsigned char *bnodeid1 = (const unsigned char *)"abc123";
779 static unsigned int bnodeid1_len = 6; /* strlen(bnode_id1) */
780 static raptor_term_type bnodeid1_type = RAPTOR_TERM_TYPE_BLANK;
781 static const unsigned char* language1 = (const unsigned char*)"en";
782 
783 int
main(int argc,char * argv[])784 main(int argc, char *argv[])
785 {
786   raptor_world *world;
787   const char *program = raptor_basename(argv[0]);
788   int rc = 0;
789   raptor_term* term1 = NULL; /* URI string 1 */
790   raptor_term* term2 = NULL; /* literal string1 */
791   raptor_term* term3 = NULL; /* blank node 1 */
792   raptor_term* term4 = NULL; /* URI string 2 */
793   raptor_term* term5 = NULL; /* URI string 1 again */
794   raptor_uri* uri1;
795   unsigned char* uri_str;
796   size_t uri_len;
797 
798 
799   world = raptor_new_world();
800   if(!world || raptor_world_open(world))
801     exit(1);
802 
803 
804   /* check a term for NULL URI fails */
805   term1 = raptor_new_term_from_uri(world, NULL);
806   if(term1) {
807     fprintf(stderr, "%s: raptor_new_uri(NULL) returned object rather than failing\n", program);
808     rc = 1;
809     goto tidy;
810   }
811 
812   /* check a term for non-NULL URI succeeds */
813   uri1 = raptor_new_uri(world, uri_string1);
814   if(!uri1) {
815     fprintf(stderr, "%s: raptor_new_uri(%s) failed\n", program, uri_string1);
816     rc = 1;
817     goto tidy;
818   }
819   term1 = raptor_new_term_from_uri(world, uri1);
820   if(!term1) {
821     fprintf(stderr, "%s: raptor_new_term_from_uri_string(URI %s) failed\n",
822             program, uri_string1);
823     rc = 1;
824     goto tidy;
825   }
826   raptor_free_uri(uri1); uri1 = NULL;
827   if(term1->type != uri_string1_type) {
828     fprintf(stderr, "%s: raptor term 1 is of type %d expected %d\n",
829             program, term1->type, uri_string1_type);
830     rc = 1;
831     goto tidy;
832   }
833 
834 
835   /* returns a pointer to shared string */
836   uri_str = raptor_uri_as_counted_string(term1->value.uri, &uri_len);
837   if(!uri_str) {
838     fprintf(stderr, "%s: raptor_uri_as_counted_string term 1 failed\n",
839             program);
840     rc = 1;
841     goto tidy;
842   }
843 
844   if(uri_len != uri_string1_len) {
845     fprintf(stderr, "%s: raptor term 1 URI is of length %d expected %d\n",
846             program, (int)uri_len, (int)uri_string1_len);
847     rc = 1;
848     goto tidy;
849   }
850 
851 
852   /* check an empty literal is created from a NULL literal pointer succeeds */
853   term2 = raptor_new_term_from_counted_literal(world, NULL, 0, NULL, NULL, 0);
854   if(!term2) {
855     fprintf(stderr, "%s: raptor_new_term_from_counted_literal() with all NULLs failed\n", program);
856     rc = 1;
857     goto tidy;
858   }
859   raptor_free_term(term2);
860 
861 
862   /* check an empty literal from an empty language literal pointer succeeds */
863   term2 = raptor_new_term_from_counted_literal(world, NULL, 0, NULL,
864                                                (const unsigned char*)"", 0);
865   if(!term2) {
866     fprintf(stderr, "%s: raptor_new_term_from_counted_literal() with empty language failed\n", program);
867     rc = 1;
868     goto tidy;
869   }
870   raptor_free_term(term2);
871 
872   /* check a literal with language and datatype fails */
873   uri1 = raptor_new_uri(world, uri_string1);
874   if(!uri1) {
875     fprintf(stderr, "%s: raptor_new_uri(%s) failed\n", program, uri_string1);
876     rc = 1;
877     goto tidy;
878   }
879   term2 = raptor_new_term_from_counted_literal(world, literal_string1,
880                                                literal_string1_len,
881                                                uri1, language1, 0);
882   raptor_free_uri(uri1); uri1 = NULL;
883   if(term2) {
884     fprintf(stderr, "%s: raptor_new_term_from_counted_literal() with language and datatype returned object rather than failing\n", program);
885     rc = 1;
886     goto tidy;
887   }
888 
889   /* check a literal with no language and no datatype succeeds */
890   term2 = raptor_new_term_from_counted_literal(world, literal_string1,
891                                                literal_string1_len, NULL, NULL, 0);
892   if(!term2) {
893     fprintf(stderr, "%s: raptor_new_term_from_counted_literal(%s) failed\n",
894             program, literal_string1);
895     rc = 1;
896     goto tidy;
897   }
898   if(term2->type != literal_string1_type) {
899     fprintf(stderr, "%s: raptor term 2 is of type %d expected %d\n",
900             program, term2->type, literal_string1_type);
901     rc = 1;
902     goto tidy;
903   }
904 
905 
906   /* check a blank node term with NULL id generates a new identifier */
907   term3 = raptor_new_term_from_counted_blank(world, NULL, 0);
908   if(!term3) {
909     fprintf(stderr, "%s: raptor_new_term_from_counted_blank(NULL) failed\n",
910             program);
911     rc = 1;
912     goto tidy;
913   }
914   if(term3->type != bnodeid1_type) {
915     fprintf(stderr, "%s: raptor term 3 is of type %d expected %d\n",
916             program, term3->type, bnodeid1_type);
917     rc = 1;
918     goto tidy;
919   }
920   raptor_free_term(term3);
921 
922   /* check a blank node term with an identifier succeeds */
923   term3 = raptor_new_term_from_counted_blank(world, bnodeid1, bnodeid1_len);
924   if(!term3) {
925     fprintf(stderr, "%s: raptor_new_term_from_counted_blank(%s) failed\n",
926             program, bnodeid1);
927     rc = 1;
928     goto tidy;
929   }
930   if(term3->type != bnodeid1_type) {
931     fprintf(stderr, "%s: raptor term 3 is of type %d expected %d\n",
932             program, term3->type, bnodeid1_type);
933     rc = 1;
934     goto tidy;
935   }
936 
937 
938   /* check a different URI term succeeds */
939   term4 = raptor_new_term_from_counted_uri_string(world, uri_string2,
940                                                   uri_string2_len);
941   if(!term4) {
942     fprintf(stderr,
943             "%s: raptor_new_term_from_counted_uri_string(URI %s) failed\n",
944             program, uri_string2);
945     rc = 1;
946     goto tidy;
947   }
948   if(term4->type != uri_string2_type) {
949     fprintf(stderr, "%s: raptor term 4 is of type %d expected %d\n",
950             program, term4->type, uri_string2_type);
951     rc = 1;
952     goto tidy;
953   }
954   /* returns a pointer to shared string */
955   uri_str = raptor_uri_as_counted_string(term4->value.uri, &uri_len);
956   if(!uri_str) {
957     fprintf(stderr, "%s: raptor_uri_as_counted_string term 4 failed\n",
958             program);
959     rc = 1;
960     goto tidy;
961   }
962 
963   if(uri_len != uri_string2_len) {
964     fprintf(stderr, "%s: raptor term 4 URI is of length %d expected %d\n",
965             program, (int)uri_len, (int)uri_string2_len);
966     rc = 1;
967     goto tidy;
968   }
969 
970 
971   /* check the same URI term as term1 succeeds */
972   term5 = raptor_new_term_from_uri_string(world, uri_string1);
973   if(!term5) {
974     fprintf(stderr, "%s: raptor_new_term_from_uri_string(URI %s) failed\n",
975             program, uri_string1);
976     rc = 1;
977     goto tidy;
978   }
979 
980 
981   if(raptor_term_equals(term1, term2)) {
982     fprintf(stderr, "%s: raptor_term_equals (URI %s, literal %s) returned equal, expected not-equal\n",
983             program, uri_string1, literal_string1);
984     rc = 1;
985     goto tidy;
986   }
987 
988   if(raptor_term_equals(term1, term3)) {
989     fprintf(stderr, "%s: raptor_term_equals (URI %s, bnode %s) returned equal, expected not-equal\n",
990             program, uri_string1, bnodeid1);
991     rc = 1;
992     goto tidy;
993   }
994 
995   if(raptor_term_equals(term1, term4)) {
996     fprintf(stderr, "%s: raptor_term_equals (URI %s, URI %s) returned equal, expected not-equal\n",
997             program, uri_string1, uri_string2);
998     rc = 1;
999     goto tidy;
1000   }
1001 
1002   if(!raptor_term_equals(term1, term5)) {
1003     fprintf(stderr, "%s: raptor_term_equals (URI %s, URI %s) returned not-equal, expected equal\n",
1004             program, uri_string1, uri_string1);
1005     rc = 1;
1006     goto tidy;
1007   }
1008 
1009   if(term1->value.uri != term5->value.uri) {
1010     fprintf(stderr, "%s: term1 and term5 URI objects returned not-equal pointers, expected equal\n",
1011             program);
1012     /* This is not necessarily a failure if the raptor_uri module has had
1013      * the URI interning disabled with
1014      *   raptor_world_set_flag(world, RAPTOR_WORLD_FLAG_URI_INTERNING, 0)
1015      * however this test suite does not do that, so it is a failure here.
1016      */
1017     rc = 1;
1018     goto tidy;
1019   }
1020 
1021 
1022   tidy:
1023   if(term1)
1024     raptor_free_term(term1);
1025   if(term2)
1026     raptor_free_term(term2);
1027   if(term3)
1028     raptor_free_term(term3);
1029   if(term4)
1030     raptor_free_term(term4);
1031   if(term5)
1032     raptor_free_term(term5);
1033 
1034   raptor_free_world(world);
1035 
1036   return rc;
1037 }
1038 
1039 #endif /* STANDALONE */
1040