1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * rdf_term.c - RDF Term (RDF URI, Literal, Blank Node) Interface
4  *
5  * Copyright (C) 2010-2011, 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 
24 
25 #ifdef HAVE_CONFIG_H
26 #include <rdf_config.h>
27 #endif
28 
29 #ifdef WIN32
30 #include <win32_rdf_config.h>
31 #endif
32 
33 #include <stdio.h>
34 #include <string.h>
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38 
39 #include <redland.h>
40 /* needed for utf8 functions and definition of 'byte' */
41 #include <rdf_utf8.h>
42 
43 
44 
45 #ifndef STANDALONE
46 
47 /**
48  * librdf_init_node:
49  * @world: redland world object
50  *
51  * INTERNAL - Initialise the node module.
52  *
53  **/
54 void
librdf_init_node(librdf_world * world)55 librdf_init_node(librdf_world* world)
56 {
57 }
58 
59 
60 /**
61  * librdf_finish_node:
62  * @world: redland world object
63  *
64  * INTERNAL - Terminate the node module.
65  *
66  **/
67 void
librdf_finish_node(librdf_world * world)68 librdf_finish_node(librdf_world* world)
69 {
70 }
71 
72 
73 /* constructors */
74 
75 /**
76  * librdf_new_node:
77  * @world: redland world object
78  *
79  * Constructor - create a new #librdf_node object with a private identifier.
80  *
81  * Calls librdf_new_node_from_blank_identifier(world, NULL) to
82  * construct a new redland blank node identifier and make a
83  * new librdf_node object for it.
84  *
85  * Return value: a new #librdf_node object or NULL on failure
86  **/
87 librdf_node*
librdf_new_node(librdf_world * world)88 librdf_new_node(librdf_world *world)
89 {
90   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
91 
92   librdf_world_open(world);
93 
94   return librdf_new_node_from_blank_identifier(world, (unsigned char*)NULL);
95 }
96 
97 
98 /**
99  * librdf_new_node_from_uri_string:
100  * @world: redland world object
101  * @uri_string: string representing a URI
102  *
103  * Constructor - create a new #librdf_node object from a URI string.
104  *
105  * Return value: a new #librdf_node object or NULL on failure
106  **/
107 librdf_node*
librdf_new_node_from_uri_string(librdf_world * world,const unsigned char * uri_string)108 librdf_new_node_from_uri_string(librdf_world *world,
109                                 const unsigned char *uri_string)
110 {
111   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
112 
113   librdf_world_open(world);
114 
115   return raptor_new_term_from_uri_string(world->raptor_world_ptr, uri_string);
116 }
117 
118 
119 /**
120  * librdf_new_node_from_counted_uri_string:
121  * @world: redland world object
122  * @uri_string: string representing a URI
123  * @len: length of string
124  *
125  * Constructor - create a new #librdf_node object from a counted URI string.
126  *
127  * Return value: a new #librdf_node object or NULL on failure
128  **/
129 librdf_node*
librdf_new_node_from_counted_uri_string(librdf_world * world,const unsigned char * uri_string,size_t len)130 librdf_new_node_from_counted_uri_string(librdf_world *world,
131                                         const unsigned char *uri_string,
132                                         size_t len)
133 {
134   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
135 
136   librdf_world_open(world);
137 
138   return raptor_new_term_from_counted_uri_string(world->raptor_world_ptr,
139                                                  uri_string, len);
140 }
141 
142 
143 /* Create a new (Resource) Node and set the URI. */
144 
145 /**
146  * librdf_new_node_from_uri:
147  * @world: redland world object
148  * @uri: #librdf_uri object
149  *
150  * Constructor - create a new resource #librdf_node object with a given URI.
151  *
152  * Return value: a new #librdf_node object or NULL on failure
153  **/
154 librdf_node*
librdf_new_node_from_uri(librdf_world * world,librdf_uri * uri)155 librdf_new_node_from_uri(librdf_world *world, librdf_uri *uri)
156 {
157   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
158 
159   librdf_world_open(world);
160 
161   return raptor_new_term_from_uri(world->raptor_world_ptr, uri);
162 }
163 
164 
165 /**
166  * librdf_new_node_from_uri_local_name:
167  * @world: redland world object
168  * @uri: #librdf_uri object
169  * @local_name: local name to append to URI
170  *
171  * Constructor - create a new resource #librdf_node object with a given URI and local name.
172  *
173  * Return value: a new #librdf_node object or NULL on failure
174  **/
175 librdf_node*
librdf_new_node_from_uri_local_name(librdf_world * world,librdf_uri * uri,const unsigned char * local_name)176 librdf_new_node_from_uri_local_name(librdf_world *world,
177                                     librdf_uri *uri,
178                                     const unsigned char *local_name)
179 {
180   raptor_uri *new_uri;
181   librdf_node* node;
182 
183   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
184 
185   librdf_world_open(world);
186 
187   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(uri, raptor_uri, NULL);
188   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(local_name, string, NULL);
189 
190   new_uri = raptor_new_uri_from_uri_local_name(world->raptor_world_ptr,
191                                                uri, local_name);
192   if(!new_uri)
193     return NULL;
194 
195   node = raptor_new_term_from_uri(world->raptor_world_ptr, new_uri);
196   raptor_free_uri(new_uri);
197   return node;
198 }
199 
200 
201 /**
202  * librdf_new_node_from_normalised_uri_string:
203  * @world: redland world object
204  * @uri_string: UTF-8 encoded string representing a URI
205  * @source_uri: source URI
206  * @base_uri: base URI
207  *
208  * Constructor - create a new #librdf_node object from a UTF-8 encoded URI string normalised to a new base URI.
209  *
210  * Return value: a new #librdf_node object or NULL on failure
211  **/
212 librdf_node*
librdf_new_node_from_normalised_uri_string(librdf_world * world,const unsigned char * uri_string,librdf_uri * source_uri,librdf_uri * base_uri)213 librdf_new_node_from_normalised_uri_string(librdf_world *world,
214                                            const unsigned char *uri_string,
215                                            librdf_uri *source_uri,
216                                            librdf_uri *base_uri)
217 {
218   librdf_uri* new_uri;
219   librdf_node* node;
220 
221   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
222 
223   librdf_world_open(world);
224 
225   new_uri = librdf_new_uri_normalised_to_base(uri_string,
226                                               source_uri, base_uri);
227   if(!new_uri)
228     return NULL;
229 
230   node = raptor_new_term_from_uri(world->raptor_world_ptr, new_uri);
231   raptor_free_uri(new_uri);
232   return node;
233 }
234 
235 
236 #define LIBRDF_XSD_BOOLEAN_TRUE (const unsigned char*)"true"
237 #define LIBRDF_XSD_BOOLEAN_TRUE_LEN 4
238 #define LIBRDF_XSD_BOOLEAN_FALSE (const unsigned char*)"false"
239 #define LIBRDF_XSD_BOOLEAN_FALSE_LEN 5
240 
241 static int
librdf_xsd_boolean_value_from_string(const unsigned char * string,unsigned int len)242 librdf_xsd_boolean_value_from_string(const unsigned char* string,
243                                      unsigned int len)
244 {
245   int integer = 0;
246 
247   /* FIXME
248    * Strictly only {true, false, 1, 0} are allowed according to
249    * http://www.w3.org/TR/xmlschema-2/#boolean
250    */
251   if((len == LIBRDF_XSD_BOOLEAN_TRUE_LEN &&
252      (!strcmp(LIBRDF_GOOD_CAST(const char*, string), "true") ||
253       !strcmp(LIBRDF_GOOD_CAST(const char*, string), "TRUE"))
254       )
255      ||
256      (len == 1 &&
257       !strcmp(LIBRDF_GOOD_CAST(const char*, string), "1")
258       )
259      )
260      integer = 1;
261 
262   return integer;
263 }
264 
265 
266 /*
267  * librdf_node_normalize:
268  * @world: world
269  * @node: node
270  *
271  * INTERNAL - Normalize the literal of datatyped literals to canonical form
272  *
273  * Currently handles xsd:boolean.
274  *
275  * FIXME: This should be in Raptor or Rasqal since
276  * librdf_xsd_boolean_value_from_string and the canonicalization was
277  * ripped out of Rasqal.
278  *
279  * Return value: new node (or same one if no action was taken)
280  */
281 static librdf_node*
librdf_node_normalize(librdf_world * world,librdf_node * node)282 librdf_node_normalize(librdf_world* world, librdf_node* node)
283 {
284   if(!node)
285     return NULL;
286 
287   if(node->value.literal.datatype) {
288     librdf_uri* dt_uri;
289 
290     dt_uri = librdf_new_uri_from_uri_local_name(world->xsd_namespace_uri,
291                                                 LIBRDF_GOOD_CAST(const unsigned char*, "boolean"));
292     if(raptor_uri_equals(node->value.literal.datatype, dt_uri)) {
293       const unsigned char* value;
294       size_t value_len;
295       int bvalue;
296 
297       bvalue = librdf_xsd_boolean_value_from_string(node->value.literal.string,
298                                                     node->value.literal.string_len);
299 
300       value = bvalue ? LIBRDF_XSD_BOOLEAN_TRUE :
301                        LIBRDF_XSD_BOOLEAN_FALSE;
302       value_len = bvalue ? LIBRDF_XSD_BOOLEAN_TRUE_LEN :
303                            LIBRDF_XSD_BOOLEAN_FALSE_LEN;
304 
305       if(node->value.literal.string_len != value_len ||
306          strcmp(LIBRDF_GOOD_CAST(const char*, node->value.literal.string),
307                 LIBRDF_GOOD_CAST(const char*, value))) {
308         /* If literal is not canonical, replace the node */
309         librdf_free_node(node);
310         node = NULL;
311 
312         /* Have to use Raptor constructor here since
313          * librdf_new_node_from_typed_counted_literal() calls this
314          */
315         node = raptor_new_term_from_counted_literal(world->raptor_world_ptr,
316                                                     value, value_len,
317                                                     dt_uri,
318                                                     (const unsigned char*)NULL,
319                                                     (unsigned char)0);
320       }
321     }
322 
323     if(dt_uri)
324       librdf_free_uri(dt_uri);
325   }
326 
327   return node;
328 }
329 
330 
331 /**
332  * librdf_new_node_from_literal:
333  * @world: redland world object
334  * @string: literal UTF-8 encoded string value
335  * @xml_language: literal XML language (or NULL, empty string)
336  * @is_wf_xml: non 0 if literal is XML
337  *
338  * Constructor - create a new literal #librdf_node object.
339  *
340  * 0.9.12: xml_space argument deleted
341  *
342  * An @xml_language cannot be used when @is_wf_xml is non-0. If both
343  * are given, NULL is returned.  If @xml_language is the empty string,
344  * it is the equivalent to NULL.
345  *
346  * Return value: new #librdf_node object or NULL on failure
347  **/
348 librdf_node*
librdf_new_node_from_literal(librdf_world * world,const unsigned char * string,const char * xml_language,int is_wf_xml)349 librdf_new_node_from_literal(librdf_world *world,
350                              const unsigned char *string,
351                              const char *xml_language,
352                              int is_wf_xml)
353 {
354   librdf_uri* datatype_uri;
355   librdf_node* n;
356 
357   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
358 
359   librdf_world_open(world);
360 
361   datatype_uri = (is_wf_xml ?  LIBRDF_RS_XMLLiteral_URI(world) : NULL);
362 
363   n = raptor_new_term_from_literal(world->raptor_world_ptr,
364                                    string, datatype_uri,
365                                    (const unsigned char*)xml_language);
366   return librdf_node_normalize(world, n);
367 }
368 
369 
370 /**
371  * librdf_new_node_from_typed_literal:
372  * @world: redland world object
373  * @value: literal UTF-8 encoded string value
374  * @xml_language: literal XML language (or NULL, empty string)
375  * @datatype_uri: URI of typed literal datatype or NULL
376  *
377  * Constructor - create a new typed literal #librdf_node object.
378  *
379  * Only one of @xml_language or @datatype_uri may be given.  If both
380  * are given, NULL is returned.  If @xml_language is the empty string,
381  * it is the equivalent to NULL.
382  *
383  * Return value: new #librdf_node object or NULL on failure
384  **/
385 librdf_node*
librdf_new_node_from_typed_literal(librdf_world * world,const unsigned char * value,const char * xml_language,librdf_uri * datatype_uri)386 librdf_new_node_from_typed_literal(librdf_world *world,
387                                    const unsigned char *value,
388                                    const char *xml_language,
389                                    librdf_uri *datatype_uri)
390 {
391   librdf_node* n;
392 
393   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
394 
395   librdf_world_open(world);
396 
397   n = raptor_new_term_from_literal(world->raptor_world_ptr,
398                                    value, datatype_uri,
399                                    (const unsigned char*)xml_language);
400   return librdf_node_normalize(world, n);
401 }
402 
403 
404 /**
405  * librdf_new_node_from_typed_counted_literal:
406  * @world: redland world object
407  * @value: literal UTF-8 encoded string value
408  * @value_len: literal string value length
409  * @xml_language: literal XML language (or NULL, empty string)
410  * @xml_language_len: literal XML language length (not used if @xml_language is NULL)
411  * @datatype_uri: URI of typed literal datatype or NULL
412  *
413  * Constructor - create a new typed literal #librdf_node object.
414  *
415  * Takes copies of the passed in @value, @datatype_uri and @xml_language.
416  *
417  * Only one of @xml_language or @datatype_uri may be given.  If both
418  * are given, NULL is returned.  If @xml_language is the empty string,
419  * it is the equivalent to NULL.
420  *
421  * Return value: new #librdf_node object or NULL on failure
422  **/
423 librdf_node*
librdf_new_node_from_typed_counted_literal(librdf_world * world,const unsigned char * value,size_t value_len,const char * xml_language,size_t xml_language_len,librdf_uri * datatype_uri)424 librdf_new_node_from_typed_counted_literal(librdf_world *world,
425                                            const unsigned char *value,
426                                            size_t value_len,
427                                            const char *xml_language,
428                                            size_t xml_language_len,
429                                            librdf_uri *datatype_uri)
430 {
431   librdf_node* n;
432 
433   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
434 
435   librdf_world_open(world);
436 
437   n = raptor_new_term_from_counted_literal(world->raptor_world_ptr,
438                                            value, value_len,
439                                            datatype_uri,
440                                            (const unsigned char*)xml_language,
441                                            (unsigned char)xml_language_len);
442   return librdf_node_normalize(world, n);
443 }
444 
445 
446 /**
447  * librdf_new_node_from_counted_blank_identifier:
448  * @world: redland world object
449  * @identifier: UTF-8 encoded blank node identifier or NULL
450  * @identifier_len: length of @identifier
451  *
452  * Constructor - create a new blank node #librdf_node object from a blank node counted length identifier.
453  *
454  * If no @identifier string is given (NULL) this creates a new
455  * internal identifier and uses it.
456  *
457  * Return value: new #librdf_node object or NULL on failure
458  **/
459 librdf_node*
librdf_new_node_from_counted_blank_identifier(librdf_world * world,const unsigned char * identifier,size_t identifier_len)460 librdf_new_node_from_counted_blank_identifier(librdf_world *world,
461                                               const unsigned char *identifier,
462                                               size_t identifier_len)
463 {
464   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
465 
466   librdf_world_open(world);
467 
468   return raptor_new_term_from_counted_blank(world->raptor_world_ptr,
469                                             identifier, identifier_len);
470 }
471 
472 
473 /**
474  * librdf_new_node_from_blank_identifier:
475  * @world: redland world object
476  * @identifier: UTF-8 encoded blank node identifier or NULL
477  *
478  * Constructor - create a new blank node #librdf_node object from a blank node identifier.
479  *
480  * If no @identifier string is given (NULL) this creates a new
481  * internal identifier and uses it.
482  *
483  * Return value: new #librdf_node object or NULL on failure
484  **/
485 librdf_node*
librdf_new_node_from_blank_identifier(librdf_world * world,const unsigned char * identifier)486 librdf_new_node_from_blank_identifier(librdf_world *world,
487                                       const unsigned char *identifier)
488 {
489   const unsigned char *blank = identifier;
490   librdf_node* node = NULL;
491 
492   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
493 
494   librdf_world_open(world);
495 
496   if(!identifier)
497     blank = librdf_world_get_genid(world);
498 
499   node = raptor_new_term_from_blank(world->raptor_world_ptr, blank);
500 
501   if(!identifier)
502     LIBRDF_FREE(char*, (char*)blank);
503 
504   return node;
505 }
506 
507 
508 /**
509  * librdf_new_node_from_node:
510  * @node: #librdf_node object to copy
511  *
512  * Copy constructor - create a new librdf_node object from an existing librdf_node object.
513  *
514  * Return value: a new #librdf_node object or NULL on failure
515  **/
516 librdf_node*
librdf_new_node_from_node(librdf_node * node)517 librdf_new_node_from_node(librdf_node *node)
518 {
519   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
520 
521   return raptor_term_copy(node);
522 }
523 
524 
525 /**
526  * librdf_free_node:
527  * @node: #librdf_node object
528  *
529  * Destructor - destroy an #librdf_node object.
530  *
531  **/
532 void
librdf_free_node(librdf_node * node)533 librdf_free_node(librdf_node *node)
534 {
535   if(!node)
536     return;
537 
538   raptor_free_term(node);
539 }
540 
541 
542 /* functions / methods */
543 
544 /**
545  * librdf_node_get_uri:
546  * @node: the node object
547  *
548  * Get the URI for a node object.
549  *
550  * Returns a pointer to the URI object held by the node, it must be
551  * copied if it is wanted to be used by the caller.
552  *
553  * Return value: URI object or NULL if node has no URI.
554  **/
555 librdf_uri*
librdf_node_get_uri(librdf_node * node)556 librdf_node_get_uri(librdf_node *node)
557 {
558   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
559 
560   if(node->type != RAPTOR_TERM_TYPE_URI)
561     return NULL;
562 
563   return node->value.uri;
564 }
565 
566 
567 /**
568  * librdf_node_get_type:
569  * @node: the node object
570  *
571  * Get the type of the node.
572  *
573  * See also librdf_node_is_resource(), librdf_node_is_literal() and
574  * librdf_node_is_blank() for testing individual types.
575  *
576  * Return value: the node type
577  **/
578 librdf_node_type
librdf_node_get_type(librdf_node * node)579 librdf_node_get_type(librdf_node *node)
580 {
581   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, LIBRDF_NODE_TYPE_UNKNOWN);
582 
583   return (librdf_node_type)node->type;
584 }
585 
586 
587 /**
588  * librdf_node_get_literal_value:
589  * @node: the node object
590  *
591  * Get the literal value of the node as a UTF-8 encoded string.
592  *
593  * Returns a pointer to the UTF-8 encoded literal value held by the
594  * node, it must be copied if it is wanted to be used by the caller.
595  *
596  * Return value: the UTF-8 encoded literal string or NULL if node is not a literal
597  **/
598 unsigned char*
librdf_node_get_literal_value(librdf_node * node)599 librdf_node_get_literal_value(librdf_node *node)
600 {
601   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
602 
603   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
604     return NULL;
605 
606   return node->value.literal.string;
607 }
608 
609 
610 /**
611  * librdf_node_get_literal_value_as_counted_string:
612  * @node: the node object
613  * @len_p: pointer to location to store the string length (or NULL)
614  *
615  * Get the literal value of the node as a counted UTF-8 encoded string.
616  *
617  * Returns a pointer to the UTF-8 encoded literal string value held
618  * by the node, it must be copied if it is wanted to be used by the
619  * caller.
620  *
621  * Return value: the UTF-8 encoded literal string or NULL if node is not a literal
622  **/
623 unsigned char*
librdf_node_get_literal_value_as_counted_string(librdf_node * node,size_t * len_p)624 librdf_node_get_literal_value_as_counted_string(librdf_node *node,
625                                                 size_t *len_p)
626 {
627   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
628 
629   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
630     return NULL;
631 
632   if(len_p)
633     *len_p = node->value.literal.string_len;
634 
635   return node->value.literal.string;
636 }
637 
638 
639 /**
640  * librdf_node_get_literal_value_as_latin1:
641  * @node: the node object
642  *
643  * Get the string literal value of the node as ISO Latin-1.
644  *
645  * Returns a newly allocated string containing the conversion of the
646  * node literal value held by the node into ISO Latin-1.  Discards
647  * characters outside the U+0000 to U+00FF range (inclusive).
648  *
649  * Return value: the Latin-1 literal string or NULL if node is not a literal
650  **/
651 char*
librdf_node_get_literal_value_as_latin1(librdf_node * node)652 librdf_node_get_literal_value_as_latin1(librdf_node *node)
653 {
654   size_t slen;
655   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
656 
657   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
658     return NULL;
659 
660   if(!node->value.literal.string)
661     return NULL;
662 
663   slen = LIBRDF_GOOD_CAST(size_t, node->value.literal.string_len);
664   return (char*)librdf_utf8_to_latin1_2((const unsigned char*)node->value.literal.string,
665                                         slen, '\0', NULL);
666 }
667 
668 
669 /**
670  * librdf_node_get_literal_value_language:
671  * @node: the node object
672  *
673  * Get the XML language of the node.
674  *
675  * Returns a pointer to the literal language value held by the node,
676  * it must be copied if it is wanted to be used by the caller.
677  * Language strings are ASCII, not UTF-8 encoded Unicode.
678  *
679  * Return value: the XML language string or NULL if node is not a literal
680  * or there is no XML language defined.
681  **/
682 char*
librdf_node_get_literal_value_language(librdf_node * node)683 librdf_node_get_literal_value_language(librdf_node *node)
684 {
685   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
686 
687   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
688     return NULL;
689 
690   return (char*)node->value.literal.language;
691 }
692 
693 
694 /**
695  * librdf_node_get_literal_value_is_wf_xml:
696  * @node: the node object
697  *
698  * Get the XML well-formness property of the node.
699  *
700  * Return value: 0 if the XML literal is NOT well formed XML content, or the node is not a literal
701  **/
702 int
librdf_node_get_literal_value_is_wf_xml(librdf_node * node)703 librdf_node_get_literal_value_is_wf_xml(librdf_node *node)
704 {
705   raptor_uri* rdf_xml_literal_uri;
706   int rc;
707 
708   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
709 
710   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
711     return 0;
712 
713   if(!node->value.literal.datatype)
714     return 0;
715 
716   rdf_xml_literal_uri = raptor_new_uri_for_rdf_concept(node->world,
717                                                        (const unsigned char *)"XMLLiteral");
718 
719   rc = librdf_uri_equals(node->value.literal.datatype, rdf_xml_literal_uri);
720   raptor_free_uri(rdf_xml_literal_uri);
721 
722   return rc;
723 }
724 
725 
726 /**
727  * librdf_node_get_literal_value_datatype_uri:
728  * @node: the node object
729  *
730  * Get the typed literal datatype URI of the literal node.
731  *
732  * Return value: shared URI of the datatyped literal or NULL if the node is not a literal, or has no datatype URI
733  **/
734 librdf_uri*
librdf_node_get_literal_value_datatype_uri(librdf_node * node)735 librdf_node_get_literal_value_datatype_uri(librdf_node *node)
736 {
737   if(node->type != RAPTOR_TERM_TYPE_LITERAL)
738     return NULL;
739 
740   return node->value.literal.datatype;
741 }
742 
743 
744 /**
745  * librdf_node_get_li_ordinal:
746  * @node: the node object
747  *
748  * Get the node li object ordinal value.
749  *
750  * Return value: the li ordinal value or < 1 on failure
751  **/
752 int
librdf_node_get_li_ordinal(librdf_node * node)753 librdf_node_get_li_ordinal(librdf_node *node)
754 {
755   unsigned char *uri_string;
756 
757   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
758 
759   if(node->type != RAPTOR_TERM_TYPE_URI)
760     return -1;
761 
762   uri_string = raptor_uri_as_string(node->value.uri);
763   if(strncmp((const char*)uri_string,
764              (const char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#_", 44))
765     return -1;
766 
767   return atoi((const char*)uri_string+44);
768 }
769 
770 
771 /**
772  * librdf_node_get_blank_identifier:
773  * @node: the node object
774  *
775  * Get the blank node identifier as a UTF-8 encoded string.
776  *
777  * Return value: the UTF-8 encoded blank node identifier value or NULL on failure
778  **/
779 unsigned char*
librdf_node_get_blank_identifier(librdf_node * node)780 librdf_node_get_blank_identifier(librdf_node *node)
781 {
782   return node->value.blank.string;
783 }
784 
785 
786 /**
787  * librdf_node_get_counted_blank_identifier:
788  * @node: the node object
789  * @len_p: pointer to variable to store length (or NULL)
790  *
791  * Get the blank node identifier as a counted UTF-8 encoded string.
792  *
793  * Return value: the UTF-8 encoded blank node identifier value or NULL on failure
794  **/
795 unsigned char*
librdf_node_get_counted_blank_identifier(librdf_node * node,size_t * len_p)796 librdf_node_get_counted_blank_identifier(librdf_node* node, size_t* len_p)
797 {
798   if(len_p)
799     *len_p = node->value.blank.string_len;
800   return node->value.blank.string;
801 }
802 
803 
804 /**
805  * librdf_node_is_resource:
806  * @node: the node object
807  *
808  * Check node is a resource.
809  *
810  * Return value: non-zero if the node is a resource (URI)
811  **/
812 int
librdf_node_is_resource(librdf_node * node)813 librdf_node_is_resource(librdf_node *node)
814 {
815   return (node->type == RAPTOR_TERM_TYPE_URI);
816 }
817 
818 
819 /**
820  * librdf_node_is_literal:
821  * @node: the node object
822  *
823  * Check node is a literal.
824  *
825  * Return value: non-zero if the node is a literal
826  **/
827 int
librdf_node_is_literal(librdf_node * node)828 librdf_node_is_literal(librdf_node *node)
829 {
830   return (node->type == RAPTOR_TERM_TYPE_LITERAL);
831 }
832 
833 
834 /**
835  * librdf_node_is_blank:
836  * @node: the node object
837  *
838  * Check node is a blank nodeID.
839  *
840  * Return value: non-zero if the node is a blank nodeID
841  **/
842 int
librdf_node_is_blank(librdf_node * node)843 librdf_node_is_blank(librdf_node *node)
844 {
845   return (node->type == RAPTOR_TERM_TYPE_BLANK);
846 }
847 
848 
849 /**
850  * librdf_node_encode:
851  * @node: the node to serialise
852  * @buffer: the buffer to use
853  * @length: buffer size
854  *
855  * Serialise a node into a buffer.
856  *
857  * Encodes the given node in the buffer, which must be of sufficient
858  * size.  If buffer is NULL, no work is done but the size of buffer
859  * required is returned.
860  *
861  * If the node cannot be encoded due to restrictions of the encoding
862  * format, a redland error is generated
863  *
864  * Return value: the number of bytes written or 0 on failure.
865  **/
866 size_t
librdf_node_encode(librdf_node * node,unsigned char * buffer,size_t length)867 librdf_node_encode(librdf_node *node,
868                    unsigned char *buffer, size_t length)
869 {
870   size_t total_length = 0;
871   unsigned char *string;
872   size_t string_length;
873   size_t language_length = 0;
874   unsigned char *datatype_uri_string = NULL;
875   size_t datatype_uri_length = 0;
876 
877   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
878 
879   switch(node->type) {
880     case RAPTOR_TERM_TYPE_URI:
881       string = (unsigned char*)librdf_uri_as_counted_string(node->value.uri,
882                                                             &string_length);
883 
884       total_length = 3 + string_length + 1; /* +1 for \0 at end */
885 
886       if(length && total_length > length)
887         return 0;
888 
889       if(string_length > 0xFFFF)
890         return 0;
891 
892       if(buffer) {
893         buffer[0] = 'R';
894         buffer[1] = (string_length & 0xff00) >> 8;
895         buffer[2] = (string_length & 0x00ff);
896         memcpy((char*)buffer + 3, string, string_length + 1);
897       }
898       break;
899 
900     case RAPTOR_TERM_TYPE_LITERAL:
901       string = (unsigned char*)node->value.literal.string;
902       string_length = node->value.literal.string_len;
903       if(node->value.literal.language)
904         language_length = LIBRDF_GOOD_CAST(size_t, node->value.literal.language_len);
905 
906       if(node->value.literal.datatype) {
907         datatype_uri_string = librdf_uri_as_counted_string(node->value.literal.datatype, &datatype_uri_length);
908       }
909 
910       total_length = 6 + string_length + 1; /* +1 for \0 at end */
911       if(string_length > 0xFFFF) /* for long literal - type 'N' */
912         total_length += 2;
913 
914       if(language_length)
915         total_length += language_length + 1;
916 
917       if(datatype_uri_length)
918         total_length += datatype_uri_length + 1;
919 
920       if(length && total_length > length)
921         return 0;
922 
923       if(datatype_uri_length > 0xFFFF)
924         return 0;
925 
926 
927       if(buffer) {
928         if(string_length > 0xFFFF) {
929           /* long literal type N (string length > 0x10000) */
930           buffer[0] = 'N';
931           buffer[1] = (string_length & 0xff000000) >> 24;
932           buffer[2] = (string_length & 0x00ff0000) >> 16;
933           buffer[3] = (string_length & 0x0000ff00) >> 8;
934           buffer[4] = (string_length & 0x000000ff);
935           buffer[5] = (datatype_uri_length & 0xff00) >> 8;
936           buffer[6] = (datatype_uri_length & 0x00ff);
937           buffer[7] = (language_length & 0x00ff);
938           buffer += 8;
939         } else {
940           /* short literal type M (string length <= 0xFFFF) */
941           buffer[0] = 'M';
942           buffer[1] = (string_length & 0xff00) >> 8;
943           buffer[2] = (string_length & 0x00ff);
944           buffer[3] = (datatype_uri_length & 0xff00) >> 8;
945           buffer[4] = (datatype_uri_length & 0x00ff);
946           buffer[5] = (language_length & 0x00ff);
947           buffer += 6;
948         }
949         memcpy(buffer, string, string_length + 1);
950         buffer += string_length + 1;
951 
952         if(datatype_uri_length) {
953           memcpy(buffer, datatype_uri_string, datatype_uri_length + 1);
954           buffer += datatype_uri_length + 1;
955         }
956 
957         if(language_length)
958           memcpy(buffer, node->value.literal.language, language_length + 1);
959       } /* end if buffer */
960 
961       break;
962 
963     case RAPTOR_TERM_TYPE_BLANK:
964       string = (unsigned char*)node->value.blank.string;
965       string_length = node->value.blank.string_len;
966 
967       total_length = 3 + string_length + 1; /* +1 for \0 at end */
968 
969       if(length && total_length > length)
970         return 0;
971 
972       if(string_length > 0xFFFF)
973         return 0;
974 
975       if(buffer) {
976         buffer[0] = 'B';
977         buffer[1] = (string_length & 0xff00) >> 8;
978         buffer[2] = (string_length & 0x00ff);
979         memcpy((char*)buffer + 3, string, string_length + 1);
980       }
981       break;
982 
983     case RAPTOR_TERM_TYPE_UNKNOWN:
984     default:
985       return 0;
986   }
987 
988   return total_length;
989 }
990 
991 
992 /**
993  * librdf_node_decode:
994  * @world: librdf_world
995  * @size_p: pointer to bytes used or NULL
996  * @buffer: the buffer to use
997  * @length: buffer size
998  *
999  * Deserialise a node from a buffer.
1000  *
1001  * Decodes the serialised node (as created by librdf_node_encode() )
1002  * from the given buffer.
1003  *
1004  * Return value: new node or NULL on failure (bad encoding, allocation failure)
1005  **/
1006 librdf_node*
librdf_node_decode(librdf_world * world,size_t * size_p,unsigned char * buffer,size_t length)1007 librdf_node_decode(librdf_world *world, size_t *size_p,
1008                    unsigned char *buffer, size_t length)
1009 {
1010   int is_wf_xml;
1011   size_t string_length;
1012   size_t total_length;
1013   size_t language_length;
1014   unsigned char *datatype_uri_string = NULL;
1015   size_t datatype_uri_length;
1016   librdf_uri* datatype_uri = NULL;
1017   unsigned char *language = NULL;
1018   int status = 0;
1019   librdf_node* node = NULL;
1020 
1021   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
1022 
1023   librdf_world_open(world);
1024 
1025   /* absolute minimum - first byte is type */
1026   if (length < 1)
1027     return NULL;
1028 
1029   switch(buffer[0]) {
1030     case 'R': /* URI / Resource */
1031       /* min */
1032       if(length < 3)
1033         return NULL;
1034 
1035       string_length = LIBRDF_GOOD_CAST(size_t, (buffer[1] << 8) | buffer[2]);
1036       total_length = 3 + string_length + 1;
1037 
1038       node = librdf_new_node_from_uri_string(world, buffer + 3);
1039 
1040       break;
1041 
1042     case 'L': /* Old encoding form for Literal */
1043       /* min */
1044       if(length < 6)
1045         return NULL;
1046 
1047       is_wf_xml = (buffer[1] & 0xf0)>>8;
1048       string_length = LIBRDF_GOOD_CAST(size_t, (buffer[2] << 8) | buffer[3]);
1049       language_length = LIBRDF_GOOD_CAST(size_t, buffer[5]);
1050 
1051       total_length = 6 + string_length + 1; /* +1 for \0 at end */
1052       if(language_length) {
1053         language = buffer + total_length;
1054         total_length += language_length + 1;
1055       }
1056 
1057       node = librdf_new_node_from_typed_counted_literal(world,
1058                                                         buffer + 6,
1059                                                         string_length,
1060                                                         (const char*)language,
1061                                                         LIBRDF_GOOD_CAST(unsigned char, language_length),
1062                                                         is_wf_xml ? LIBRDF_RS_XMLLiteral_URI(world) : NULL);
1063 
1064     break;
1065 
1066     case 'M': /* Literal for Redland 0.9.12+ */
1067       /* min */
1068       if(length < 6)
1069         return NULL;
1070 
1071       string_length = LIBRDF_GOOD_CAST(size_t, (buffer[1] << 8) | buffer[2]);
1072       datatype_uri_length = LIBRDF_GOOD_CAST(size_t, (buffer[3] << 8) | buffer[4]);
1073       language_length = buffer[5];
1074 
1075       total_length = 6 + string_length + 1; /* +1 for \0 at end */
1076       if(datatype_uri_length) {
1077         datatype_uri_string = buffer + total_length;
1078         total_length += datatype_uri_length + 1;
1079       }
1080       if(language_length) {
1081         language = buffer + total_length;
1082         total_length += language_length + 1;
1083       }
1084 
1085       if(datatype_uri_string)
1086         datatype_uri = librdf_new_uri(world, datatype_uri_string);
1087 
1088       node = librdf_new_node_from_typed_counted_literal(world,
1089                                                         buffer + 6,
1090                                                         string_length,
1091                                                         (const char*)language,
1092                                                         LIBRDF_GOOD_CAST(unsigned char, language_length),
1093                                                         datatype_uri);
1094       if(datatype_uri)
1095         librdf_free_uri(datatype_uri);
1096 
1097       if(status)
1098         return NULL;
1099 
1100     break;
1101 
1102     case 'N': /* Literal for redland 1.0.5+ (long literal) */
1103       /* min */
1104       if(length < 8)
1105         return NULL;
1106 
1107       string_length = LIBRDF_GOOD_CAST(size_t, (buffer[1] << 24) | (buffer[2] << 16) | (buffer[3] << 8) | buffer[4]);
1108       datatype_uri_length = LIBRDF_GOOD_CAST(size_t, (buffer[5] << 8) | buffer[6]);
1109       language_length = buffer[7];
1110 
1111       total_length = 8 + string_length + 1; /* +1 for \0 at end */
1112       if(datatype_uri_length) {
1113         datatype_uri_string = buffer + total_length;
1114         total_length += datatype_uri_length + 1;
1115       }
1116       if(language_length) {
1117         language = buffer + total_length;
1118         total_length += language_length + 1;
1119       }
1120 
1121       if(datatype_uri_string)
1122         datatype_uri = librdf_new_uri(world, datatype_uri_string);
1123 
1124       node = librdf_new_node_from_typed_counted_literal(world,
1125                                                         buffer + 8,
1126                                                         string_length,
1127                                                         (const char*)language,
1128                                                         LIBRDF_GOOD_CAST(size_t, language_length),
1129                                                         datatype_uri);
1130       if(datatype_uri)
1131         librdf_free_uri(datatype_uri);
1132 
1133       if(status)
1134         return NULL;
1135 
1136     break;
1137 
1138     case 'B': /* RAPTOR_TERM_TYPE_BLANK */
1139       /* min */
1140       if(length < 3)
1141         return NULL;
1142 
1143       string_length = LIBRDF_GOOD_CAST(size_t, (buffer[1] << 8) | buffer[2]);
1144 
1145       total_length = 3 + string_length + 1; /* +1 for \0 at end */
1146 
1147       node = librdf_new_node_from_blank_identifier(world, buffer+3);
1148 
1149     break;
1150 
1151   default:
1152     return NULL;
1153   }
1154 
1155   if(size_p)
1156     *size_p = total_length;
1157 
1158   return node;
1159 }
1160 
1161 
1162 #ifndef REDLAND_DISABLE_DEPRECATED
1163 /**
1164  * librdf_node_to_string:
1165  * @node: the node object
1166  *
1167  * Format the node as a string in a debugging format.
1168  *
1169  * Note a new string is allocated which must be freed by the caller.
1170  *
1171  * @Deprecated: Use librdf_node_write() to write to #raptor_iostream
1172  * which can be made to write to a string.  Use a #librdf_serializer
1173  * to write proper syntax formats.
1174  *
1175  * Return value: a string value representing the node or NULL on failure
1176  **/
1177 unsigned char*
librdf_node_to_string(librdf_node * node)1178 librdf_node_to_string(librdf_node *node)
1179 {
1180   raptor_iostream* iostr;
1181   unsigned char *s;
1182   int rc;
1183 
1184   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
1185 
1186   iostr = raptor_new_iostream_to_string(node->world,
1187                                         (void**)&s, NULL, malloc);
1188   if(!iostr)
1189     return NULL;
1190 
1191   rc = librdf_node_write(node, iostr);
1192   raptor_free_iostream(iostr);
1193   if(rc) {
1194     raptor_free_memory(s);
1195     s = NULL;
1196   }
1197 
1198   return s;
1199 }
1200 #endif
1201 
1202 
1203 #ifndef REDLAND_DISABLE_DEPRECATED
1204 /**
1205  * librdf_node_to_counted_string:
1206  * @node: the node object
1207  * @len_p: pointer to location to store length
1208  *
1209  * Format the node as a counted string in a debugging format.
1210  *
1211  * Note a new string is allocated which must be freed by the caller.
1212  *
1213  * @Deprecated: Use librdf_node_write() to write to #raptor_iostream
1214  * which can be made to write to a string.  Use a #librdf_serializer
1215  * to write proper syntax formats.
1216  *
1217  * Return value: a string value representing the node or NULL on failure
1218  **/
1219 unsigned char*
librdf_node_to_counted_string(librdf_node * node,size_t * len_p)1220 librdf_node_to_counted_string(librdf_node *node, size_t *len_p)
1221 {
1222   raptor_iostream* iostr;
1223   unsigned char *s;
1224   int rc;
1225 
1226   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
1227 
1228   iostr = raptor_new_iostream_to_string(node->world,
1229                                         (void**)&s, len_p, malloc);
1230   if(!iostr)
1231     return NULL;
1232 
1233   rc = librdf_node_write(node, iostr);
1234   raptor_free_iostream(iostr);
1235 
1236   if(rc) {
1237     raptor_free_memory(s);
1238     s = NULL;
1239   }
1240 
1241   return s;
1242 }
1243 #endif
1244 
1245 
1246 /**
1247  * librdf_node_print:
1248  * @node: the node
1249  * @fh: file handle
1250  *
1251  * Pretty print the node to a file descriptor.
1252  *
1253  * This method is for debugging and the format of the output should
1254  * not be relied on.
1255  *
1256  **/
1257 void
librdf_node_print(librdf_node * node,FILE * fh)1258 librdf_node_print(librdf_node *node, FILE *fh)
1259 {
1260   raptor_iostream *iostr;
1261 
1262   LIBRDF_ASSERT_OBJECT_POINTER_RETURN(node, librdf_node);
1263   LIBRDF_ASSERT_OBJECT_POINTER_RETURN(fh, FILE*);
1264 
1265   if(!node)
1266     return;
1267 
1268   iostr = raptor_new_iostream_to_file_handle(node->world, fh);
1269   if(!iostr)
1270     return;
1271 
1272   librdf_node_write(node, iostr);
1273 
1274   raptor_free_iostream(iostr);
1275 }
1276 
1277 
1278 /**
1279  * librdf_node_equals:
1280  * @first_node: first #librdf_node node
1281  * @second_node: second #librdf_node node
1282  *
1283  * Compare two librdf_node objects for equality.
1284  *
1285  * Note - for literal nodes, XML language, XML space and well-formness are
1286  * presently ignored in the comparison.
1287  *
1288  * Return value: non 0 if nodes are equal.  0 if not-equal or failure
1289  **/
1290 int
librdf_node_equals(librdf_node * first_node,librdf_node * second_node)1291 librdf_node_equals(librdf_node *first_node, librdf_node *second_node)
1292 {
1293   return raptor_term_equals(first_node, second_node);
1294 }
1295 
1296 
1297 /**
1298  * librdf_node_static_iterator_create:
1299  * @nodes: static array of #librdf_node objects
1300  * @size: size of array
1301  *
1302  * Create an iterator over an array of nodes (ALWAYS FAILS)
1303  *
1304  * This legacy method used to create an iterator for an existing
1305  * static array of librdf_node objects.  It was intended for testing
1306  * iterator code.
1307  *
1308  * @deprecated: always returns NULL. Use
1309  * librdf_node_new_static_node_iterator()
1310  *
1311  * Return value: NULL
1312  **/
1313 librdf_iterator*
librdf_node_static_iterator_create(librdf_node ** nodes,int size)1314 librdf_node_static_iterator_create(librdf_node **nodes, int size)
1315 {
1316   return NULL;
1317 }
1318 
1319 
1320 /**
1321  * librdf_node_write:
1322  * @node: the node
1323  * @iostr: iostream to write to
1324  *
1325  * Write the node to an iostream in N-Triples format.
1326  *
1327  * This method can be used to write a node in a relatively
1328  * readable format.  To write more compact formats use a
1329  * serializer to pick a syntax and serialize triples to it.
1330  *
1331  * Return value: non-0 on failure
1332  **/
1333 int
librdf_node_write(librdf_node * node,raptor_iostream * iostr)1334 librdf_node_write(librdf_node* node, raptor_iostream *iostr)
1335 {
1336   const unsigned char* term;
1337   size_t len;
1338 
1339 #define NULL_STRING_LENGTH 6
1340   static const unsigned char * const null_string = (const unsigned char *)"(null)";
1341 
1342   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(iostr, raptor_iostream, 1);
1343 
1344   if(!node) {
1345     raptor_iostream_counted_string_write(null_string, NULL_STRING_LENGTH, iostr);
1346     return 0;
1347   }
1348 
1349   switch(node->type) {
1350     case RAPTOR_TERM_TYPE_LITERAL:
1351       raptor_iostream_write_byte('"', iostr);
1352       raptor_string_ntriples_write(node->value.literal.string,
1353                                    node->value.literal.string_len,
1354                                    '"',
1355                                    iostr);
1356       raptor_iostream_write_byte('"', iostr);
1357       if(node->value.literal.language) {
1358         raptor_iostream_write_byte('@', iostr);
1359         raptor_iostream_string_write(node->value.literal.language, iostr);
1360       }
1361       if(node->value.literal.datatype) {
1362         raptor_iostream_counted_string_write("^^<", 3, iostr);
1363         term = librdf_uri_as_counted_string(node->value.literal.datatype,
1364                                             &len);
1365         raptor_string_ntriples_write(term, len, '>', iostr);
1366         raptor_iostream_write_byte('>', iostr);
1367       }
1368 
1369       break;
1370 
1371     case RAPTOR_TERM_TYPE_BLANK:
1372       raptor_iostream_counted_string_write("_:", 2, iostr);
1373       term = (unsigned char*)node->value.blank.string;
1374       len = node->value.blank.string_len;
1375       raptor_iostream_counted_string_write(term, len, iostr);
1376       break;
1377 
1378     case RAPTOR_TERM_TYPE_URI:
1379       raptor_iostream_write_byte('<', iostr);
1380       term = librdf_uri_as_counted_string(node->value.uri, &len);
1381       raptor_string_ntriples_write(term, len, '>', iostr);
1382       raptor_iostream_write_byte('>', iostr);
1383       break;
1384 
1385     case RAPTOR_TERM_TYPE_UNKNOWN:
1386     default:
1387       /*LIBRDF_FATAL1(node->world, LIBRDF_FROM_NODE, "Unknown node type");*/
1388       return 1;
1389   }
1390 
1391   return 0;
1392 }
1393 
1394 #endif /* STANDALONE */
1395 
1396 
1397 /* TEST CODE */
1398 
1399 
1400 #ifdef STANDALONE
1401 
1402 /* one more prototype */
1403 int main(int argc, char *argv[]);
1404 
1405 
1406 static void
dump_node_as_C(FILE * fh,const char * var,void * buffer,int size)1407 dump_node_as_C(FILE* fh, const char* var, void *buffer, int size) {
1408   int i;
1409   unsigned char* p=(unsigned char*)buffer;
1410 
1411   fprintf(fh, "const unsigned char %s[%d] = {", var, size);
1412   for (i=0; i < size; i++) {
1413     if(i)
1414       fputs(", ", fh);
1415     fprintf(fh, "0x%02x", p[i]);
1416   }
1417   fputs("};\n", fh);
1418 }
1419 
1420 
1421 static int
check_node(const char * program,const unsigned char * expected,void * buffer,size_t size)1422 check_node(const char* program, const unsigned char *expected,
1423            void *buffer, size_t size) {
1424   unsigned int i;
1425   for(i=0; i< size; i++) {
1426     unsigned char c=((unsigned char*)buffer)[i];
1427     if(c != expected[i]) {
1428       fprintf(stderr, "%s: Encoding node byte %d: 0x%02x expected 0x%02x\n",
1429               program, i, c, expected[i]);
1430       return(1);
1431     }
1432   }
1433   return(0);
1434 }
1435 
1436 
1437 static const char *hp_string1="http://purl.org/net/dajobe/";
1438 static const char *hp_string2="http://purl.org/net/dajobe/";
1439 static const char *lit_string="Dave Beckett";
1440 static const char *genid="genid42";
1441 static const char *datatype_lit_string="Datatyped literal value";
1442 static const char *datatype_uri_string="http://example.org/datatypeURI";
1443 
1444 /* Node Encoded (type R) version of hp_string1 */
1445 static const unsigned char hp_uri_encoded[31] = {0x52, 0x00, 0x1b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x61, 0x6a, 0x6f, 0x62, 0x65, 0x2f, 0x00};
1446 
1447 /* Node Encoded (type M) version of typed literal with literal value
1448  * datatype_lit_string and datatype URI datatype_uri_string */
1449 static const unsigned char datatyped_literal_M_encoded[61] = {0x4d, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x44, 0x61, 0x74, 0x61, 0x74, 0x79, 0x70, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x74, 0x79, 0x70, 0x65, 0x55, 0x52, 0x49, 0x00};
1450 
1451 /* Node Encoded (type N) version of big 100,000-length literal
1452  * (just the first 32 bytes, the rest are 0x58 'X')
1453  */
1454 const unsigned char big_literal_N_encoded[32] = {0x4e, 0x00, 0x01, 0x86, 0xa0, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58};
1455 
1456 
1457 int
main(int argc,char * argv[])1458 main(int argc, char *argv[])
1459 {
1460   librdf_node *node, *node2, *node3, *node4, *node5, *node6, *node7, *node8, *node9;
1461   librdf_uri *uri, *uri2;
1462   int size, size2;
1463   unsigned char *buffer;
1464   librdf_world *world;
1465   size_t big_literal_length;
1466   unsigned char *big_literal;
1467   unsigned int i;
1468 
1469   const char *program=librdf_basename((const char*)argv[0]);
1470 
1471   world=librdf_new_world();
1472   librdf_world_open(world);
1473 
1474   fprintf(stderr, "%s: Creating home page node from string\n", program);
1475   node=librdf_new_node_from_uri_string(world, (const unsigned char*)hp_string1);
1476   if(!node) {
1477     fprintf(stderr, "%s: librdf_new_node_from_uri_string failed\n", program);
1478     return(1);
1479   }
1480 
1481   fprintf(stdout, "%s: Home page URI is ", program);
1482   librdf_uri_print(librdf_node_get_uri(node), stdout);
1483   fputc('\n', stdout);
1484 
1485   fprintf(stdout, "%s: Creating URI from string '%s'\n", program,
1486           hp_string2);
1487   uri=librdf_new_uri(world, (const unsigned char*)hp_string2);
1488   fprintf(stdout, "%s: Setting node URI to new URI ", program);
1489   librdf_uri_print(uri, stdout);
1490   fputc('\n', stdout);
1491   librdf_free_uri(uri);
1492 
1493   fprintf(stdout, "%s: Node is: ", program);
1494   librdf_node_print(node, stdout);
1495   fputc('\n', stdout);
1496 
1497   size=librdf_node_encode(node, NULL, 0);
1498   fprintf(stdout, "%s: Encoding node requires %d bytes\n", program, size);
1499   buffer = LIBRDF_MALLOC(unsigned char*, size);
1500 
1501   fprintf(stdout, "%s: Encoding node in buffer\n", program);
1502   size2=librdf_node_encode(node, buffer, size);
1503   if(size2 != size) {
1504     fprintf(stderr, "%s: Encoding node used %d bytes, expected it to use %d\n", program, size2, size);
1505     return(1);
1506   }
1507 
1508   if(0)
1509     dump_node_as_C(stdout, "hp_uri_encoded", buffer, size);
1510   if(check_node(program, hp_uri_encoded, buffer, size))
1511     return(1);
1512 
1513 
1514   fprintf(stdout, "%s: Creating new node\n", program);
1515 
1516   fprintf(stdout, "%s: Decoding node from buffer\n", program);
1517   if(!(node2=librdf_node_decode(world, NULL, buffer, size))) {
1518     fprintf(stderr, "%s: Decoding node failed\n", program);
1519     return(1);
1520   }
1521   LIBRDF_FREE(char*, buffer);
1522 
1523   fprintf(stdout, "%s: New node is: ", program);
1524   librdf_node_print(node2, stdout);
1525   fputc('\n', stdout);
1526 
1527 
1528   fprintf(stdout, "%s: Creating new literal string node\n", program);
1529   node3=librdf_new_node_from_literal(world, (const unsigned char*)lit_string, NULL, 0);
1530   if(!node3) {
1531     fprintf(stderr, "%s: librdf_new_node_from_literal failed\n", program);
1532     return(1);
1533   }
1534 
1535   buffer=(unsigned char*)librdf_node_get_literal_value_as_latin1(node3);
1536   if(!buffer) {
1537     fprintf(stderr, "%s: Failed to get literal string value as Latin-1\n", program);
1538     return(1);
1539   }
1540   fprintf(stdout, "%s: Node literal string value (Latin-1) is: '%s'\n",
1541           program, buffer);
1542   LIBRDF_FREE(char*, buffer);
1543 
1544   fprintf(stdout, "%s: Creating new blank node with identifier %s\n", program, genid);
1545   node4=librdf_new_node_from_blank_identifier(world, (const unsigned char*)genid);
1546   if(!node4) {
1547     fprintf(stderr, "%s: librdf_new_node_from_blank_identifier failed\n", program);
1548     return(1);
1549   }
1550 
1551   buffer=librdf_node_get_blank_identifier(node4);
1552   if(!buffer) {
1553     fprintf(stderr, "%s: Failed to get blank node identifier\n", program);
1554     return(1);
1555   }
1556   fprintf(stdout, "%s: Node identifier is: '%s'\n", program, buffer);
1557 
1558   node5=librdf_new_node_from_node(node4);
1559   if(!node5) {
1560     fprintf(stderr, "%s: Failed to make new blank node from old one\n", program);
1561     return(1);
1562   }
1563 
1564   buffer=librdf_node_get_blank_identifier(node5);
1565   if(!buffer) {
1566     fprintf(stderr, "%s: Failed to get copied blank node identifier\n", program);
1567     return(1);
1568   }
1569   fprintf(stdout, "%s: Copied node identifier is: '%s'\n", program, buffer);
1570 
1571   fprintf(stdout, "%s: Creating a new blank node with a generated identifier\n", program);
1572   node6=librdf_new_node(world);
1573   if(!node6) {
1574     fprintf(stderr, "%s: librdf_new_node failed\n", program);
1575     return(1);
1576   }
1577 
1578   buffer=librdf_node_get_blank_identifier(node6);
1579   if(!buffer) {
1580     fprintf(stderr, "%s: Failed to get blank node identifier\n", program);
1581     return(1);
1582   }
1583   fprintf(stdout, "%s: Generated node identifier is: '%s'\n", program, buffer);
1584 
1585   uri2=librdf_new_uri(world, (const unsigned char*)datatype_uri_string);
1586   node7=librdf_new_node_from_typed_literal(world,
1587                                            (const unsigned char*)datatype_lit_string,
1588                                            NULL, uri2);
1589   librdf_free_uri(uri2);
1590 
1591   size=librdf_node_encode(node7, NULL, 0);
1592   fprintf(stdout, "%s: Encoding typed node requires %d bytes\n", program, size);
1593   buffer = LIBRDF_MALLOC(unsigned char*, size);
1594 
1595   fprintf(stdout, "%s: Encoding typed node in buffer\n", program);
1596   size2=librdf_node_encode(node7, (unsigned char*)buffer, size);
1597   if(size2 != size) {
1598     fprintf(stderr, "%s: Encoding typed node used %d bytes, expected it to use %d\n", program, size2, size);
1599     return(1);
1600   }
1601 
1602   if(0)
1603     dump_node_as_C(stdout, "datatyped_literal_M_encoded", buffer, size);
1604   if(check_node(program, datatyped_literal_M_encoded, buffer, size))
1605     return(1);
1606 
1607   fprintf(stdout, "%s: Decoding typed node from buffer\n", program);
1608   if(!(node8=librdf_node_decode(world, NULL, (unsigned char*)buffer, size))) {
1609     fprintf(stderr, "%s: Decoding typed node failed\n", program);
1610     return(1);
1611   }
1612   LIBRDF_FREE(char*, buffer);
1613 
1614   if(librdf_new_node_from_typed_literal(world,
1615                                         (const unsigned char*)"Datatyped literal value",
1616                                         "en-GB", uri2)) {
1617     fprintf(stderr, "%s: Unexpected success allowing a datatyped literal with a language\n", program);
1618     return(1);
1619   }
1620 
1621   if(librdf_new_node_from_literal(world,
1622                                   (const unsigned char*)"XML literal value",
1623                                   "en-GB", 1)) {
1624     fprintf(stderr, "%s: Unexpected success allowing an XML literal with a language\n", program);
1625     return(1);
1626   }
1627 
1628   big_literal_length=100000;
1629   big_literal = LIBRDF_MALLOC(unsigned char*, big_literal_length + 1);
1630   for(i=0; i<big_literal_length; i++)
1631      big_literal[i]='X';
1632 
1633   node9=librdf_new_node_from_typed_counted_literal(world,
1634                                                    big_literal, big_literal_length,
1635                                                    NULL, 0, NULL);
1636   if(!node9) {
1637     fprintf(stderr, "%s: Failed to make big %d byte literal\n", program,
1638             (int)big_literal_length);
1639     return(1);
1640   }
1641   LIBRDF_FREE(char*, big_literal);
1642 
1643   size=librdf_node_encode(node9, NULL, 0);
1644   fprintf(stdout, "%s: Encoding big literal node requires %d bytes\n", program, size);
1645   buffer = LIBRDF_MALLOC(unsigned char*, size);
1646   fprintf(stdout, "%s: Encoding big literal node in buffer\n", program);
1647   size2=librdf_node_encode(node9, (unsigned char*)buffer, size);
1648   if(size2 != size) {
1649     fprintf(stderr, "%s: Encoding big literal node used %d bytes, expected it to use %d\n", program, size2, size);
1650     return(1);
1651   }
1652 
1653   /* Just check first 32 bytes */
1654   if(0)
1655     dump_node_as_C(stdout, "big_literal_N_encoded", buffer, 32);
1656   if(check_node(program, big_literal_N_encoded, buffer, 32))
1657     return(1);
1658   LIBRDF_FREE(char*, buffer);
1659 
1660 
1661   fprintf(stdout, "%s: Freeing nodes\n", program);
1662   librdf_free_node(node9);
1663   librdf_free_node(node8);
1664   librdf_free_node(node7);
1665   librdf_free_node(node6);
1666   librdf_free_node(node5);
1667   librdf_free_node(node4);
1668   librdf_free_node(node3);
1669   librdf_free_node(node2);
1670   librdf_free_node(node);
1671 
1672   librdf_free_world(world);
1673 
1674   /* keep gcc -Wall happy */
1675   return(0);
1676 }
1677 
1678 #endif
1679