1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * raptor_abbrev.c - Code common to abbreviating serializers (ttl/rdfxmla)
4  *
5  * Copyright (C) 2006, Dave Robillard
6  * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
7  * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
8  * Copyright (C) 2005, Steve Shepard steveshep@gmail.com
9  *
10  * This package is Free Software and part of Redland http://librdf.org/
11  *
12  * It is licensed under the following three licenses as alternatives:
13  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
14  *   2. GNU General Public License (GPL) V2 or any newer version
15  *   3. Apache License, V2.0 or any newer version
16  *
17  * You may not use this file except in compliance with at least one of
18  * the above three licenses.
19  *
20  * See LICENSE.html or LICENSE.txt at the top of this package for the
21  * complete terms and further detail along with the license texts for
22  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <raptor_config.h>
28 #endif
29 
30 #ifdef WIN32
31 #include <win32_raptor_config.h>
32 #endif
33 
34 
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <stdarg.h>
39 #ifdef HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 
46 /* Raptor includes */
47 #include "raptor.h"
48 #include "raptor_internal.h"
49 
50 
51 /*
52  * raptor_abbrev_node implementation.
53  *
54  * FIXME Duplicate code
55  *
56  * Parts of this is taken from redland librdf_node.h and librdf_node.c
57  *
58  **/
59 
60 raptor_abbrev_node*
raptor_new_abbrev_node(raptor_world * world,raptor_identifier_type node_type,const void * node_data,raptor_uri * datatype,const unsigned char * language)61 raptor_new_abbrev_node(raptor_world* world,
62                        raptor_identifier_type node_type, const void *node_data,
63                        raptor_uri *datatype, const unsigned char *language)
64 {
65   unsigned char *string;
66   raptor_abbrev_node* node=NULL;
67 
68   if(node_type == RAPTOR_IDENTIFIER_TYPE_UNKNOWN)
69     return NULL;
70 
71   node = (raptor_abbrev_node*)RAPTOR_CALLOC(raptor_abbrev_node, 1,
72                                             sizeof(raptor_abbrev_node));
73 
74   if(node) {
75     node->world = world;
76     node->ref_count = 1;
77     node->type = node_type;
78 
79     switch (node_type) {
80         case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
81           node->type = RAPTOR_IDENTIFIER_TYPE_RESOURCE;
82           /* intentional fall through */
83         case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
84           node->value.resource.uri = raptor_uri_copy_v2(world, (raptor_uri*)node_data);
85           break;
86 
87         case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
88           string=(unsigned char*)RAPTOR_MALLOC(blank,
89                                                strlen((char*)node_data)+1);
90           if(!string)
91             goto oom;
92           strcpy((char*)string, (const char*) node_data);
93           node->value.blank.string = string;
94           break;
95 
96         case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
97           node->value.ordinal.ordinal = *(int *)node_data;
98           break;
99 
100         case RAPTOR_IDENTIFIER_TYPE_LITERAL:
101         case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
102           string = (unsigned char*)RAPTOR_MALLOC(literal,
103                                                  strlen((char*)node_data)+1);
104           if(!string)
105             goto oom;
106           strcpy((char*)string, (const char*)node_data);
107           node->value.literal.string = string;
108 
109           if(datatype) {
110             node->value.literal.datatype = raptor_uri_copy_v2(world, datatype);
111           }
112 
113           if(language) {
114             unsigned char *lang;
115             lang=(unsigned char*)RAPTOR_MALLOC(language,
116                                                strlen((const char*)language)+1);
117             if(!lang) {
118               RAPTOR_FREE(literal, string);
119               goto oom;
120             }
121             strcpy((char*)lang, (const char*)language);
122             node->value.literal.language = lang;
123           }
124           break;
125 
126         case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
127         default:
128           RAPTOR_FREE(raptor_abbrev_node, node);
129     }
130 
131   }
132 
133   return node;
134 
135   /* out of memory - clean up and return NULL */
136   oom:
137   RAPTOR_FREE(raptor_abbrev_node, node);
138   return NULL;
139 }
140 
141 
142 void
raptor_free_abbrev_node(raptor_abbrev_node * node)143 raptor_free_abbrev_node(raptor_abbrev_node* node)
144 {
145   RAPTOR_ASSERT_OBJECT_POINTER_RETURN(node, raptor_abbrev_node);
146 
147   if(--node->ref_count)
148     return;
149 
150   switch (node->type) {
151       case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
152       case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
153         raptor_free_uri_v2(node->world, node->value.resource.uri);
154         break;
155 
156       case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
157         RAPTOR_FREE(blank, node->value.blank.string);
158         break;
159 
160       case RAPTOR_IDENTIFIER_TYPE_LITERAL:
161       case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
162         RAPTOR_FREE(literal, node->value.literal.string);
163 
164         if(node->value.literal.datatype)
165           raptor_free_uri_v2(node->world, node->value.literal.datatype);
166 
167         if(node->value.literal.language)
168           RAPTOR_FREE(language, node->value.literal.language);
169 
170         break;
171 
172       case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
173       case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
174       default:
175         /* Nothing to do */
176         break;
177   }
178 
179   RAPTOR_FREE(raptor_abbrev_node, node);
180 }
181 
182 
183 /**
184  * raptor_abbrev_node_cmp:
185  * @node1: node 1
186  * @node2: node 2
187  *
188  * INTERNAL -compare two raptor_abbrev_nodes.
189  *
190  * This needs to be a strong ordering for use by raptor_avltree.
191  * This is very performance critical, anything to make it faster is worth it.
192  *
193  * Return value: <0, 0 or 1 if @node1 less than, equal or greater
194  * than @node2 respectively
195  */
196 int
raptor_abbrev_node_cmp(raptor_abbrev_node * node1,raptor_abbrev_node * node2)197 raptor_abbrev_node_cmp(raptor_abbrev_node* node1, raptor_abbrev_node* node2)
198 {
199   int rv = 0;
200 
201   if(node1 == node2) {
202     return 0;
203   } else if(node1->type < node2->type) {
204     return -1;
205   } else if(node1->type > node2->type) {
206     return 1;
207   }
208 
209   switch (node1->type) {
210       case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
211       case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
212         rv = raptor_uri_compare_v2(node1->world,
213                                    node1->value.resource.uri,
214                                    node2->value.resource.uri);
215         break;
216 
217       case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
218         rv = strcmp((const char*)node1->value.blank.string,
219                     (const char*)node2->value.blank.string);
220         break;
221 
222       case RAPTOR_IDENTIFIER_TYPE_LITERAL:
223       case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
224 
225         if((char *)node1->value.literal.string != NULL &&
226             (char *)node2->value.literal.string != NULL) {
227 
228           /* string */
229           rv = strcmp((const char*)node1->value.literal.string,
230                        (const char*)node2->value.literal.string);
231           if(rv != 0)
232             break;
233 
234           /* if strings are equal, compare language */
235           if(node1->value.literal.language == NULL &&
236              node2->value.literal.language == NULL) {
237             rv = 0;
238           } else if(node1->value.literal.language != NULL &&
239                     node2->value.literal.language != NULL) {
240             rv = strcmp((const char*)node1->value.literal.language,
241                         (const char*)node2->value.literal.language);
242           } else if(node1->value.literal.language == NULL) {
243             rv = -1;
244           } else {
245             rv = 1;
246           }
247           if(rv != 0)
248             break;
249 
250           /* if string and language are equal, compare datatype */
251           if(node1->value.literal.datatype == NULL &&
252              node2->value.literal.datatype == NULL ) {
253             rv = 0;
254           } else if(node1->value.literal.datatype != NULL &&
255                     node2->value.literal.datatype != NULL) {
256             rv = strcmp((char*)node1->value.literal.datatype,
257                   (char*)node2->value.literal.datatype);
258           } else if(node1->value.literal.datatype == NULL) {
259             rv = -1;
260           } else {
261             rv = 1;
262           }
263 
264           /* if rv = 0 here then the nodes are completely equal */
265 
266         } else {
267           RAPTOR_FATAL1("string must be non-NULL for literal or xml literal\n");
268           rv = 0;
269         }
270 
271         break;
272 
273       case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
274         if(node1->value.ordinal.ordinal == node2->value.ordinal.ordinal)
275           rv = 0;
276         else if(node1->value.ordinal.ordinal < node2->value.ordinal.ordinal)
277           rv = -1;
278         else
279           rv = 1;
280 
281         break;
282 
283       case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
284       default:
285         /* Nothing to do */
286         break;
287   }
288 
289   return rv;
290 
291 }
292 
293 int
raptor_abbrev_node_equals(raptor_abbrev_node * node1,raptor_abbrev_node * node2)294 raptor_abbrev_node_equals(raptor_abbrev_node* node1, raptor_abbrev_node* node2)
295 {
296   return raptor_abbrev_node_cmp(node1, node2) == 0;
297 }
298 
299 
300 /**
301  * raptor_abbrev_node_lookup:
302  * @nodes: Tree of nodes to search
303  * @node_type: Raptor identifier type
304  * @node_value: Node value to search for
305  * @datatype: Literal datatype or NULL
306  * @language: Literal language or NULL
307  * @created_p: (output parameter) set to non-0 if a node was created
308  *
309  * INTERNAL - Look in an avltree of nodes for a node described by parameters
310  *   and if present create it, add it and return it
311  *
312  * Return value: the node found/created or NULL on failure
313  */
314 raptor_abbrev_node*
raptor_abbrev_node_lookup(raptor_avltree * nodes,raptor_identifier_type node_type,const void * node_value,raptor_uri * datatype,const unsigned char * language,int * created_p)315 raptor_abbrev_node_lookup(raptor_avltree* nodes,
316                           raptor_identifier_type node_type,
317                           const void *node_value, raptor_uri *datatype,
318                           const unsigned char *language, int* created_p)
319 {
320   raptor_abbrev_node *lookup_node;
321   raptor_abbrev_node *rv_node;
322 
323   /* Create a temporary node for search comparison. */
324   lookup_node = raptor_new_abbrev_node(nodes->world, node_type, node_value, datatype, language);
325 
326   if(!lookup_node)
327     return NULL;
328 
329   rv_node=(raptor_abbrev_node*)raptor_avltree_search(nodes, lookup_node);
330 
331   if(created_p)
332     *created_p=(!rv_node);
333 
334   /* If not found, insert/return a new one */
335   if(!rv_node) {
336 
337     if(raptor_avltree_add(nodes, lookup_node))
338       return NULL;
339     else
340       return lookup_node;
341 
342   /* Found */
343   } else {
344     raptor_free_abbrev_node(lookup_node);
345     return rv_node;
346   }
347 }
348 
349 
350 static raptor_abbrev_node**
raptor_new_abbrev_po(raptor_abbrev_node * predicate,raptor_abbrev_node * object)351 raptor_new_abbrev_po(raptor_abbrev_node* predicate, raptor_abbrev_node* object)
352 {
353   raptor_abbrev_node** nodes=NULL;
354   nodes = (raptor_abbrev_node**)RAPTOR_CALLOC(raptor_abbrev_nodes, 2,
355                                               sizeof(raptor_abbrev_node*));
356   if(!nodes)
357     return NULL;
358 
359   nodes[0]=predicate;
360   nodes[1]=object;
361 
362   return nodes;
363 }
364 
365 
366 static void
raptor_free_abbrev_po(raptor_abbrev_node ** nodes)367 raptor_free_abbrev_po(raptor_abbrev_node** nodes)
368 {
369   RAPTOR_ASSERT_OBJECT_POINTER_RETURN(nodes, raptor_abbrev_node_pair);
370 
371   if(nodes[0])
372     raptor_free_abbrev_node(nodes[0]);
373   if(nodes[1])
374     raptor_free_abbrev_node(nodes[1]);
375 
376   RAPTOR_FREE(raptor_abbrev_nodes, nodes);
377 }
378 
379 
380 static int
raptor_compare_abbrev_po(raptor_abbrev_node ** nodes1,raptor_abbrev_node ** nodes2)381 raptor_compare_abbrev_po(raptor_abbrev_node** nodes1,
382                          raptor_abbrev_node** nodes2)
383 {
384   int d;
385   d=raptor_abbrev_node_cmp(nodes1[0], nodes2[0]);
386   if(!d)
387     d=raptor_abbrev_node_cmp(nodes1[1], nodes2[1]);
388 
389   return d;
390 }
391 
392 
393 #ifdef RAPTOR_DEBUG
394 static void
raptor_print_abbrev_po(FILE * handle,raptor_abbrev_node ** nodes)395 raptor_print_abbrev_po(FILE* handle, raptor_abbrev_node** nodes)
396 {
397   raptor_abbrev_node* p = nodes[0];
398   raptor_abbrev_node* o = nodes[1];
399 
400   if(p && o) {
401     unsigned char *pred;
402     unsigned char *obj;
403 
404     pred = raptor_statement_part_as_string_v2(p->world,
405                                               p->value.resource.uri, p->type,
406                                               NULL, NULL);
407     obj = raptor_statement_part_as_string_v2(o->world,
408                                              o->value.literal.string,
409                                              o->type,
410                                              o->value.literal.datatype,
411                                              o->value.literal.language);
412     fprintf(handle, "[%s : %s]\n", pred, obj);
413     RAPTOR_FREE(cstring, pred);
414     RAPTOR_FREE(cstring, obj);
415   }
416 }
417 #endif
418 
419 
420 /*
421  * raptor_abbrev_subject implementation
422  *
423  * The subject of triples, with all predicates and values
424  * linked from them.
425  *
426  **/
427 
428 
429 raptor_abbrev_subject*
raptor_new_abbrev_subject(raptor_abbrev_node * node)430 raptor_new_abbrev_subject(raptor_abbrev_node* node)
431 {
432   raptor_abbrev_subject* subject;
433 
434   if(!(node->type == RAPTOR_IDENTIFIER_TYPE_RESOURCE ||
435         node->type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS ||
436         node->type == RAPTOR_IDENTIFIER_TYPE_ORDINAL)) {
437     RAPTOR_FATAL1("Subject node must be a resource, blank, or ordinal\n");
438     return NULL;
439   }
440 
441   subject = (raptor_abbrev_subject*)RAPTOR_CALLOC(raptor_subject, 1,
442                                                   sizeof(raptor_abbrev_subject));
443 
444   if (subject) {
445     subject->node = node;
446     subject->node->ref_count++;
447     subject->node->count_as_subject++;
448 
449     subject->node_type = NULL;
450 
451     subject->valid = 1;
452 
453     subject->properties =
454       raptor_new_avltree(node->world,
455                          (raptor_data_compare_function)raptor_compare_abbrev_po,
456                          (raptor_data_free_function)raptor_free_abbrev_po,
457                          0);
458 #ifdef RAPTOR_DEBUG
459     raptor_avltree_set_print_handler(subject->properties,
460                                      (raptor_data_print_function)raptor_print_abbrev_po);
461 #endif
462 
463     subject->list_items =
464       raptor_new_sequence((raptor_sequence_free_handler *)raptor_free_abbrev_node, NULL);
465 
466     if(!subject->node || !subject->properties || !subject->list_items) {
467       raptor_free_abbrev_subject(subject);
468       subject = NULL;
469     }
470 
471   }
472 
473   return subject;
474 }
475 
476 
477 void
raptor_free_abbrev_subject(raptor_abbrev_subject * subject)478 raptor_free_abbrev_subject(raptor_abbrev_subject* subject)
479 {
480   RAPTOR_ASSERT_OBJECT_POINTER_RETURN(subject, raptor_abbrev_subject);
481 
482   if(subject->node)
483     raptor_free_abbrev_node(subject->node);
484 
485   if(subject->node_type)
486     raptor_free_abbrev_node(subject->node_type);
487 
488   if(subject->properties)
489     raptor_free_avltree(subject->properties);
490 
491   if(subject->list_items)
492     raptor_free_sequence(subject->list_items);
493 
494   RAPTOR_FREE(raptor_subject, subject);
495 }
496 
497 
498 int
raptor_abbrev_subject_valid(raptor_abbrev_subject * subject)499 raptor_abbrev_subject_valid(raptor_abbrev_subject *subject)
500 {
501   return subject->valid;
502 }
503 
504 
505 int
raptor_abbrev_subject_invalidate(raptor_abbrev_subject * subject)506 raptor_abbrev_subject_invalidate(raptor_abbrev_subject *subject)
507 {
508   subject->valid = 0;
509   return 0;
510 }
511 
512 
513 
514 
515 /**
516  * raptor_subject_add_property:
517  * @subject: subject node to add to
518  * @predicate: predicate node
519  * @object: object node
520  *
521  * INTERNAL - Add predicate/object pair into properties array of a subject node.
522  *
523  * The subject node takes ownership of the predicate/object nodes.
524  * On error, predicate/object are freed immediately.
525  *
526  * Return value: <0 on failure, >0 if pair is a duplicate and it was not added
527  **/
528 int
raptor_abbrev_subject_add_property(raptor_abbrev_subject * subject,raptor_abbrev_node * predicate,raptor_abbrev_node * object)529 raptor_abbrev_subject_add_property(raptor_abbrev_subject* subject,
530                                    raptor_abbrev_node* predicate,
531                                    raptor_abbrev_node* object)
532 {
533   int err;
534   raptor_abbrev_node** nodes;
535 
536   nodes=raptor_new_abbrev_po(predicate, object);
537   if(!nodes)
538     return -1;
539 
540   predicate->ref_count++;
541   object->ref_count++;
542 
543   if(raptor_avltree_search(subject->properties, nodes)) {
544     /* Already present - do not add a duplicate triple (s->[p o]) */
545     raptor_free_abbrev_po(nodes);
546     return 1;
547   }
548 
549 #if 0
550   fprintf(stderr, "Adding P,O ");
551   raptor_print_abbrev_po(stderr, nodes);
552 
553   raptor_avltree_dump(subject->properties, stderr);
554 #endif
555   err = raptor_avltree_add(subject->properties, nodes);
556   if(err)
557     return -1;
558 #if 0
559   fprintf(stderr, "Result ");
560   raptor_avltree_print(subject->properties, stderr);
561 
562   raptor_avltree_dump(subject->properties, stderr);
563 
564   raptor_avltree_check(subject->properties);
565 
566   fprintf(stderr, "\n\n");
567 #endif
568 
569   return 0;
570 }
571 
572 
573 /**
574  * raptor_abbrev_subject_add_list_element:
575  * @subject: subject node to add to
576  * @ordinal: ordinal index
577  * @object: object node
578  *
579  * INTERNAL - Add rdf:li into list element array of a #raptor_abbrev_subject node.
580  *
581  * Return value: non-0 on failure
582  **/
583 int
raptor_abbrev_subject_add_list_element(raptor_abbrev_subject * subject,int ordinal,raptor_abbrev_node * object)584 raptor_abbrev_subject_add_list_element(raptor_abbrev_subject* subject,
585                                        int ordinal,
586                                        raptor_abbrev_node* object)
587 {
588   int rv = 1;
589   raptor_abbrev_node* node;
590 
591   node = (raptor_abbrev_node*)raptor_sequence_get_at(subject->list_items,
592                                                      ordinal);
593   if(!node) {
594     /* If there isn't already an entry */
595     rv = raptor_sequence_set_at(subject->list_items, ordinal, object);
596     if(!rv) {
597       object->ref_count++;
598       object->count_as_subject++;
599     }
600   }
601 
602   return rv;
603 }
604 
605 
606 int
raptor_abbrev_subject_cmp(raptor_abbrev_subject * subject1,raptor_abbrev_subject * subject2)607 raptor_abbrev_subject_cmp(raptor_abbrev_subject* subject1,
608 			  raptor_abbrev_subject* subject2)
609 {
610   return raptor_abbrev_node_cmp(subject1->node, subject2->node);
611 }
612 
613 
614 raptor_abbrev_subject*
raptor_abbrev_subject_find(raptor_avltree * subjects,raptor_identifier_type node_type,const void * node_data)615 raptor_abbrev_subject_find(raptor_avltree *subjects,
616                            raptor_identifier_type node_type,
617                            const void *node_data)
618 {
619   raptor_abbrev_subject* rv_subject = NULL;
620   raptor_abbrev_node* lookup_node = NULL;
621   raptor_abbrev_subject* lookup = NULL;
622 
623   /* datatype and language both null for a subject node */
624 
625   lookup_node = raptor_new_abbrev_node(subjects->world,
626                                        node_type, node_data, NULL, NULL);
627   if(!lookup_node)
628     return NULL;
629 
630   lookup = raptor_new_abbrev_subject(lookup_node);
631   if(!lookup) {
632     raptor_free_abbrev_node(lookup_node);
633     return NULL;
634   }
635 
636   rv_subject = (raptor_abbrev_subject*) raptor_avltree_search(subjects, lookup);
637 
638   raptor_free_abbrev_subject(lookup);
639   raptor_free_abbrev_node(lookup_node);
640 
641   return rv_subject;
642 }
643 
644 
645 raptor_abbrev_subject*
raptor_abbrev_subject_lookup(raptor_avltree * nodes,raptor_avltree * subjects,raptor_avltree * blanks,raptor_identifier_type node_type,const void * node_data,int * created_p)646 raptor_abbrev_subject_lookup(raptor_avltree* nodes,
647                              raptor_avltree* subjects,
648                              raptor_avltree* blanks,
649                              raptor_identifier_type node_type,
650                              const void *node_data,
651                              int* created_p)
652 {
653   raptor_avltree *tree;
654   raptor_abbrev_subject* rv_subject;
655 
656   /* Search for specified resource.
657    */
658   tree = (node_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) ?
659             blanks : subjects;
660   rv_subject= raptor_abbrev_subject_find(tree, node_type, node_data);
661 
662   if(created_p)
663     *created_p=(!rv_subject);
664 
665   /* If not found, create one and insert it */
666   if(!rv_subject) {
667 
668     raptor_abbrev_node* node = raptor_abbrev_node_lookup(nodes, node_type,
669                                                          node_data, NULL, NULL,
670                                                          NULL);
671     if(node) {
672       rv_subject = raptor_new_abbrev_subject(node);
673       if(rv_subject) {
674         if(raptor_avltree_add(tree, rv_subject)) {
675           rv_subject = NULL;
676         }
677       }
678     }
679   }
680 
681   return rv_subject;
682 }
683 
684 
685 #ifdef ABBREV_DEBUG
686 void
raptor_print_subject(raptor_abbrev_subject * subject)687 raptor_print_subject(raptor_abbrev_subject* subject)
688 {
689   int i;
690   unsigned char *subj;
691   unsigned char *pred;
692   unsigned char *obj;
693   raptor_avltree_iterator* iter=NULL;
694 
695   /* Note: The raptor_abbrev_node field passed as the first argument for
696    * raptor_statement_part_as_string() is somewhat arbitrary, since as
697    * the data structure is designed, the first word in the value union
698    * is what was passed as the subject/predicate/object of the
699    * statement.
700    */
701   subj = raptor_statement_part_as_string(subject->node->value.resource.uri,
702                                          subject->node->type, NULL, NULL);
703 
704   if(subject->type) {
705       obj=raptor_statement_part_as_string(subject->type->value.resource.uri,
706                                           subject->type->type,
707                                           subject->type->value.literal.datatype,
708                                           subject->type->value.literal.language);
709       fprintf(stderr,"[%s, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, %s]\n", subj, obj);
710       RAPTOR_FREE(cstring, obj);
711   }
712 
713   for(i=0; i < raptor_sequence_size(subject->elements); i++) {
714 
715     raptor_abbrev_node* o = raptor_sequence_get_at(subject->elements, i);
716     if(o) {
717       obj = raptor_statement_part_as_string(o->value.literal.string,
718                                             o->type,
719                                             o->value.literal.datatype,
720                                             o->value.literal.language);
721       fprintf(stderr,"[%s, [rdf:_%d], %s]\n", subj, i, obj);
722       RAPTOR_FREE(cstring, obj);
723     }
724 
725   }
726 
727 
728   iter=raptor_new_avltree_iterator(subject->properties, NULL, NULL, 1);
729   while(iter) {
730     raptor_abbrev_node** nodes;
731     nodes=(raptor_abbrev_node**)raptor_avltree_iterator_get(iter);
732     if(!nodes)
733       break;
734     raptor_print_abbrev_po(stderr, nodes);
735 
736     if(raptor_avltree_iterator_next(iter))
737       break;
738   }
739   if(iter)
740     raptor_free_avltree_iterator(iter);
741 
742   RAPTOR_FREE(cstring, subj);
743 
744 }
745 #endif
746 
747 
748 /* helper functions */
749 
750 /**
751  * raptor_unique_id:
752  * @base: base ID
753  *
754  * INTERNAL - Generate a node ID for serializing
755  *
756  * Raptor doesn't check that blank IDs it generates are unique from
757  * any specified by rdf:nodeID. Here, we need to emit IDs that are
758  * different from the ones the parser generates so that there is no
759  * collision. For now, just prefix a '_' to the parser generated
760  * name.
761  *
762  * Return value: new node ID
763  **/
764 unsigned char*
raptor_unique_id(unsigned char * base)765 raptor_unique_id(unsigned char *base)
766 {
767   const char *prefix = "_";
768   int prefix_len = strlen(prefix);
769   int base_len = strlen((const char*)base);
770   int len = prefix_len + base_len + 1;
771   unsigned char *unique_id;
772 
773   unique_id= (unsigned char *)RAPTOR_MALLOC(cstring, len);
774   strncpy((char*)unique_id, prefix, prefix_len);
775   strncpy((char*)unique_id+prefix_len, (char *)base, base_len);
776   unique_id[len-1]='\0';
777 
778   return unique_id;
779 }
780 
781 
782 /**
783  * raptor_new_qname_from_resource:
784  * @namespaces: sequence of namespaces (corresponding to nstack)
785  * @nstack: #raptor_namespace_stack to use/update
786  * @namespace_count: size of nstack (may be modified)
787  * @node: #raptor_abbrev_node to use
788  *
789  * INTERNAL - Make an XML QName from the URI associated with the node.
790  *
791  * Return value: the QName or NULL on failure
792  **/
793 raptor_qname*
raptor_new_qname_from_resource(raptor_sequence * namespaces,raptor_namespace_stack * nstack,int * namespace_count,raptor_abbrev_node * node)794 raptor_new_qname_from_resource(raptor_sequence* namespaces,
795                                raptor_namespace_stack* nstack,
796                                int* namespace_count,
797                                raptor_abbrev_node* node)
798 {
799   unsigned char* name=NULL;  /* where to split predicate name */
800   size_t name_len=1;
801   unsigned char *uri_string;
802   size_t uri_len;
803   unsigned char c;
804   unsigned char *p;
805   raptor_uri *ns_uri;
806   raptor_namespace *ns;
807   raptor_qname *qname;
808 
809   if(node->type != RAPTOR_IDENTIFIER_TYPE_RESOURCE) {
810     RAPTOR_FATAL1("Node must be a resource\n");
811     return NULL;
812   }
813 
814   qname=raptor_namespaces_qname_from_uri(nstack,
815                                          node->value.resource.uri, 10);
816   if(qname)
817     return qname;
818 
819   uri_string = raptor_uri_as_counted_string_v2(node->world, node->value.resource.uri, &uri_len);
820 
821   p= uri_string;
822   name_len=uri_len;
823   while(name_len >0) {
824     if(raptor_xml_name_check(p, name_len, 10)) {
825       name=p;
826       break;
827     }
828     p++; name_len--;
829   }
830 
831   if(!name || (name == uri_string))
832     return NULL;
833 
834   c=*name; *name='\0';
835   ns_uri=raptor_new_uri_v2(node->world, uri_string);
836   if(!ns_uri)
837     return NULL;
838 
839   *name=c;
840 
841   ns = raptor_namespaces_find_namespace_by_uri(nstack, ns_uri);
842   if(!ns) {
843     /* The namespace was not declared, so create one */
844     unsigned char prefix[2 + MAX_ASCII_INT_SIZE + 1];
845       *namespace_count = *namespace_count + 1;
846     sprintf((char *)prefix, "ns%d", *namespace_count);
847 
848     ns = raptor_new_namespace_from_uri(nstack, prefix, ns_uri, 0);
849 
850     /* We'll most likely need this namespace again. Push it on our
851      * stack.  It will be deleted in raptor_rdfxmla_serialize_terminate()
852      */
853     if(raptor_sequence_push(namespaces, ns)) {
854       /* namespaces sequence has no free handler so we have to free
855        * the ns ourselves on error
856        */
857       raptor_free_namespace(ns);
858       raptor_free_uri_v2(node->world, ns_uri);
859       return NULL;
860     }
861   }
862 
863   qname = raptor_new_qname_from_namespace_local_name_v2(node->world, ns, name,  NULL);
864 
865   raptor_free_uri_v2(node->world, ns_uri);
866 
867   return qname;
868 }
869