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