1 /*
2 ##############################################################################
3 # Copyright (c) 2000-2006 All rights reserved
4 # Alberto Reggiori <areggiori@webweaving.org>
5 # Dirk-Willem van Gulik <dirkx@webweaving.org>
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # 1. Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 #
14 # 2. Redistributions in binary form must reproduce the above copyright
15 # notice, this list of conditions and the following disclaimer in
16 # the documentation and/or other materials provided with the
17 # distribution.
18 #
19 # 3. The end-user documentation included with the redistribution,
20 # if any, must include the following acknowledgment:
21 # "This product includes software developed by
22 # Alberto Reggiori <areggiori@webweaving.org> and
23 # Dirk-Willem van Gulik <dirkx@webweaving.org>."
24 # Alternately, this acknowledgment may appear in the software itself,
25 # if and wherever such third-party acknowledgments normally appear.
26 #
27 # 4. All advertising materials mentioning features or use of this software
28 # must display the following acknowledgement:
29 # This product includes software developed by the University of
30 # California, Berkeley and its contributors.
31 #
32 # 5. Neither the name of the University nor the names of its contributors
33 # may be used to endorse or promote products derived from this software
34 # without specific prior written permission.
35 #
36 # 6. Products derived from this software may not be called "RDFStore"
37 # nor may "RDFStore" appear in their names without prior written
38 # permission.
39 #
40 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41 # ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44 # FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 # OF THE POSSIBILITY OF SUCH DAMAGE.
52 #
53 # ====================================================================
54 #
55 # This software consists of work developed by Alberto Reggiori and
56 # Dirk-Willem van Gulik. The RDF specific part is based based on public
57 # domain software written at the Stanford University Database Group by
58 # Sergey Melnik. For more information on the RDF API Draft work,
59 # please see <http://www-db.stanford.edu/~melnik/rdf/api.html>
60 # The DBMS TCP/IP server part is based on software originally written
61 # by Dirk-Willem van Gulik for Web Weaving Internet Engineering m/v Enschede,
62 # The Netherlands.
63 #
64 ##############################################################################
65 #
66 # $Id: rdfstore_serializer.c,v 1.9 2006/06/19 10:10:22 areggiori Exp $
67 #
68 */
69
70 #if !defined(WIN32)
71 #include <sys/param.h>
72 #endif
73
74 #include <sys/types.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <errno.h>
78 #include <strings.h>
79 #include <fcntl.h>
80 #include <ctype.h>
81
82 #include <time.h>
83 #include <sys/stat.h>
84
85 #include "rdfstore_log.h"
86 #include "rdfstore.h"
87 #include "rdfstore_serializer.h"
88 #include "rdfstore_digest.h"
89 #include "rdfstore_utf8.h"
90
91 /*
92 #define RDFSTORE_DEBUG
93 */
94
95 /*
96 See also:
97
98 o-> N-Triples http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
99 o-> Quads http://robustai.net/sailor/grammar/Quads.html
100
101 */
102
103 int rdfstore_ntriples_hex2c(const char *x);
104 void rdfstore_ntriples_c2hex(int ch, char *x);
105
106 char *
rdfstore_get_localname(char * uri)107 rdfstore_get_localname ( char * uri ) {
108 char * nc=NULL;
109 char * localname=NULL;
110
111 if ( uri == NULL )
112 return NULL;
113
114 /* try to get out XML QName LocalName from resource identifier */
115 nc = uri + strlen(uri)-1;
116 while( nc >= uri ) {
117 if( rdfstore_is_xml_name( nc ) )
118 localname = nc;
119 nc--;
120 };
121
122 if( !localname ) {
123 localname = uri; /* we can not split it up; so we default to the whole uri - correct? */
124 };
125
126 return localname;
127 };
128
129 int
rdfstore_get_namespace(char * uri)130 rdfstore_get_namespace ( char * uri ) {
131 char * nc=NULL;
132
133 if ( uri == NULL )
134 return 0;
135
136 nc = rdfstore_get_localname( uri );
137 if ( nc == NULL ) {
138 return ( uri != NULL ) ? strlen(uri) : 0;
139 } else {
140 return (int)( nc - uri );
141 };
142 };
143
144 /* see http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName */
145 int
rdfstore_is_xml_name(char * name_char)146 rdfstore_is_xml_name( char *name_char ) {
147
148 if ( ( ! isalpha((int)*name_char) ) &&
149 ( *name_char != '_' ) )
150 return 0;
151
152 name_char++;
153 while( *name_char ) {
154 if ( ( ! isalnum((int)*name_char) ) &&
155 ( *name_char != '_' ) &&
156 ( *name_char != '-' ) &&
157 ( *name_char != '.' ) )
158 return 0;
159 name_char++;
160 };
161
162 return 1;
163 };
164
165 int
rdfstore_statement_getLabel(RDF_Statement * statement,char * label)166 rdfstore_statement_getLabel( RDF_Statement * statement, char * label ) {
167 if ( statement->node != NULL ) { /* use the statement as resource identifier if possible */
168 /* XXX is the following copy to char * (string) correct????? */
169 memcpy( label, statement->node->value.resource.identifier, statement->node->value.resource.identifier_len );
170 memcpy( label+statement->node->value.resource.identifier_len, "\0", 1);
171 return statement->node->value.resource.identifier_len;
172 } else {
173 int i=0,status=0;
174 unsigned char dd[RDFSTORE_SHA_DIGESTSIZE];
175
176 /* e.g. urn:rdf:SHA-1-d2619b606c7ecac3dcf9151dae104c4ae7554786 */
177 sprintf( label, "urn:rdf:%s-", rdfstore_digest_get_digest_algorithm() );
178 status = rdfstore_digest_get_statement_digest( statement, NULL, dd );
179 if ( status != 0 )
180 return 0;
181
182 for ( i=0; i< RDFSTORE_SHA_DIGESTSIZE ; i++ ) {
183 char cc[2];
184 sprintf( cc, "%02X", dd[i] );
185 strncat(label, cc, 2);
186 };
187 return 9 + strlen( rdfstore_digest_get_digest_algorithm() ) + (RDFSTORE_SHA_DIGESTSIZE*2);
188 };
189 };
190
rdfstore_ntriples_statement(RDF_Statement * statement,RDF_Node * given_context)191 char * rdfstore_ntriples_statement (
192 RDF_Statement * statement,
193 RDF_Node * given_context
194 ) {
195 RDF_Node * context = NULL;
196 int i=0;
197 char * buff=NULL;
198 char * buff1=NULL;
199 int s_len=0,p_len=0,o_len=0,c_len=0, reification_len=0;
200
201 buff=NULL;
202
203 if ( ( statement == NULL ) ||
204 ( statement->subject == NULL ) ||
205 ( statement->predicate == NULL ) ||
206 ( statement->subject->value.resource.identifier == NULL ) ||
207 ( statement->predicate->value.resource.identifier == NULL ) ||
208 ( statement->object == NULL ) ||
209 ( ( statement->object->type != 1 ) &&
210 ( statement->object->value.resource.identifier == NULL ) ) ||
211 ( ( context != NULL ) &&
212 ( context->value.resource.identifier == NULL ) ) ||
213 ( ( statement->node != NULL ) &&
214 ( statement->node->value.resource.identifier == NULL ) ) )
215 return NULL;
216
217 if (given_context == NULL) {
218 if (statement->context != NULL)
219 context = statement->context;
220 } else {
221 /* use given context instead */
222 context = given_context;
223 };
224
225 /* try to allocate just the necessary - see http://www.w3.org/TR/rdf-testcases/#ntriples */
226 if ( statement->subject->type == 0 ) {
227 s_len = statement->subject->value.resource.identifier_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 4;
228 } else {
229 s_len = statement->subject->value.resource.identifier_len + 4;
230 };
231 if ( statement->predicate->type == 0 ) {
232 p_len = statement->predicate->value.resource.identifier_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 4;
233 } else {
234 p_len = statement->predicate->value.resource.identifier_len + 4;
235 };
236 if ( statement->object->type == 0 ) {
237 o_len = statement->object->value.resource.identifier_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 4;
238 } else if ( statement->object->type == 2 ) {
239 o_len = statement->object->value.resource.identifier_len + 4;
240 } else {
241 o_len = ( statement->object->value.literal.string != NULL ) ?
242 statement->object->value.literal.string_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 3 : 0;
243 if ( (statement->object->value.literal.lang != NULL) &&
244 (strlen(statement->object->value.literal.lang) > 0) )
245 o_len += strlen(statement->object->value.literal.lang) + 1;
246 /* we propably should croak or warn the user if something is fishy with the rdf:dataType property */
247 if ( statement->object->value.literal.parseType == 1 )
248 o_len += strlen(RDFSTORE_RDF_PARSETYPE_LITERAL) + 4;
249 else if ( statement->object->value.literal.dataType != NULL )
250 o_len += strlen(statement->object->value.literal.dataType) + 4;
251 o_len++;
252 };
253 if ( context != NULL )
254 c_len = context->value.resource.identifier_len + 4;
255
256 if ( (statement->isreified) &&
257 (statement->node != NULL) ) {
258 reification_len = ( statement->node->value.resource.identifier_len + 4 ) * 4;
259 reification_len += strlen(RDFMS_type) + 4;
260 reification_len += strlen(RDFMS_Statement) + 4;
261 reification_len += strlen(RDFMS_subject) + 4;
262 reification_len += s_len;
263 reification_len += strlen(RDFMS_predicate) + 4;
264 reification_len += p_len;
265 reification_len += strlen(RDFMS_object) + 4;
266 reification_len += o_len;
267 };
268
269 buff = (char *) RDFSTORE_MALLOC( sizeof(char) * ( s_len + p_len + o_len + c_len + 3 + reification_len ) );
270
271 if ( buff == NULL )
272 return NULL;
273
274 /* try to generate an N-Triples/Quads like string here */
275
276 i=0;
277
278 buff1=NULL;
279 if( (buff1=rdfstore_ntriples_node( statement->subject )) == NULL ) {
280 RDFSTORE_FREE( buff );
281 return NULL;
282 };
283 memcpy(buff+i, buff1, strlen(buff1));
284 i+=strlen(buff1);
285 RDFSTORE_FREE( buff1 );
286 memcpy(buff+i," ",1);
287 i++;
288
289 buff1=NULL;
290 if( (buff1=rdfstore_ntriples_node( statement->predicate )) == NULL ) {
291 RDFSTORE_FREE( buff );
292 return NULL;
293 };
294 memcpy(buff+i, buff1, strlen(buff1));
295 i+=strlen(buff1);
296 RDFSTORE_FREE( buff1 );
297 memcpy(buff+i," ",1);
298 i++;
299
300 buff1=NULL;
301 if( (buff1=rdfstore_ntriples_node( statement->object )) == NULL ) {
302 RDFSTORE_FREE( buff );
303 return NULL;
304 };
305 memcpy(buff+i, buff1, strlen(buff1));
306 i+=strlen(buff1);
307 RDFSTORE_FREE( buff1 );
308 memcpy(buff+i," ",1);
309 i++;
310
311 if ( context != NULL ) {
312 buff1=NULL;
313 if( (buff1=rdfstore_ntriples_node( context )) == NULL ) {
314 RDFSTORE_FREE( buff );
315 return NULL;
316 };
317 memcpy(buff+i, buff1, strlen(buff1));
318 i+=strlen(buff1);
319 RDFSTORE_FREE( buff1 );
320 memcpy(buff+i," ",1);
321 i++;
322 };
323
324 memcpy(buff+i,". ",2); /* not cr/lf */
325 i+=2;
326
327 /* add the reification triples if necessary */
328 if ( (statement->isreified) &&
329 (statement->node != NULL) ) {
330 memcpy(buff+i,"\n",1);
331 i++;
332
333 buff1=NULL;
334 if( (buff1=rdfstore_ntriples_node( statement->node )) == NULL ) {
335 RDFSTORE_FREE( buff );
336 return NULL;
337 };
338 memcpy(buff+i, buff1, strlen(buff1));
339 i+=strlen(buff1);
340 RDFSTORE_FREE( buff1 );
341 memcpy(buff+i," ",1);
342 i++;
343
344 memcpy(buff+i,"<",1);
345 i++;
346 memcpy(buff+i, RDFMS_type, strlen(RDFMS_type));
347 i+=strlen(RDFMS_type);
348 memcpy(buff+i,">",1);
349 i++;
350 memcpy(buff+i," ",1);
351 i++;
352
353 memcpy(buff+i,"<",1);
354 i++;
355 memcpy(buff+i, RDFMS_Statement, strlen(RDFMS_Statement));
356 i+=strlen(RDFMS_Statement);
357 memcpy(buff+i,">",1);
358 i++;
359 memcpy(buff+i," ",1);
360 i++;
361
362 memcpy(buff+i,". ",2); /* not cr/lf */
363 i+=2;
364 memcpy(buff+i,"\n",1);
365 i++;
366
367 buff1=NULL;
368 if( (buff1=rdfstore_ntriples_node( statement->node )) == NULL ) {
369 RDFSTORE_FREE( buff );
370 return NULL;
371 };
372 memcpy(buff+i, buff1, strlen(buff1));
373 i+=strlen(buff1);
374 RDFSTORE_FREE( buff1 );
375 memcpy(buff+i," ",1);
376 i++;
377
378 memcpy(buff+i,"<",1);
379 i++;
380 memcpy(buff+i, RDFMS_subject, strlen(RDFMS_subject));
381 i+=strlen(RDFMS_subject);
382 memcpy(buff+i,">",1);
383 i++;
384 memcpy(buff+i," ",1);
385 i++;
386
387 buff1=NULL;
388 if( (buff1=rdfstore_ntriples_node( statement->subject )) == NULL ) {
389 RDFSTORE_FREE( buff );
390 return NULL;
391 };
392 memcpy(buff+i, buff1, strlen(buff1));
393 i+=strlen(buff1);
394 RDFSTORE_FREE( buff1 );
395 memcpy(buff+i," ",1);
396 i++;
397
398 memcpy(buff+i,". ",2); /* not cr/lf */
399 i+=2;
400 memcpy(buff+i,"\n",1);
401 i++;
402
403 buff1=NULL;
404 if( (buff1=rdfstore_ntriples_node( statement->node )) == NULL ) {
405 RDFSTORE_FREE( buff );
406 return NULL;
407 };
408 memcpy(buff+i, buff1, strlen(buff1));
409 i+=strlen(buff1);
410 RDFSTORE_FREE( buff1 );
411 memcpy(buff+i," ",1);
412 i++;
413
414 memcpy(buff+i,"<",1);
415 i++;
416 memcpy(buff+i, RDFMS_predicate, strlen(RDFMS_predicate));
417 i+=strlen(RDFMS_predicate);
418 memcpy(buff+i,">",1);
419 i++;
420 memcpy(buff+i," ",1);
421 i++;
422
423 buff1=NULL;
424 if( (buff1=rdfstore_ntriples_node( statement->predicate )) == NULL ) {
425 RDFSTORE_FREE( buff );
426 return NULL;
427 };
428 memcpy(buff+i, buff1, strlen(buff1));
429 i+=strlen(buff1);
430 RDFSTORE_FREE( buff1 );
431 memcpy(buff+i," ",1);
432 i++;
433
434 memcpy(buff+i,". ",2); /* not cr/lf */
435 i+=2;
436 memcpy(buff+i,"\n",1);
437 i++;
438
439 buff1=NULL;
440 if( (buff1=rdfstore_ntriples_node( statement->node )) == NULL ) {
441 RDFSTORE_FREE( buff );
442 return NULL;
443 };
444 memcpy(buff+i, buff1, strlen(buff1));
445 i+=strlen(buff1);
446 RDFSTORE_FREE( buff1 );
447 memcpy(buff+i," ",1);
448 i++;
449
450 memcpy(buff+i,"<",1);
451 i++;
452 memcpy(buff+i, RDFMS_object, strlen(RDFMS_object));
453 i+=strlen(RDFMS_object);
454 memcpy(buff+i,">",1);
455 i++;
456 memcpy(buff+i," ",1);
457 i++;
458
459 buff1=NULL;
460 if( (buff1=rdfstore_ntriples_node( statement->object )) == NULL ) {
461 RDFSTORE_FREE( buff );
462 return NULL;
463 };
464 memcpy(buff+i, buff1, strlen(buff1));
465 i+=strlen(buff1);
466 RDFSTORE_FREE( buff1 );
467 memcpy(buff+i," ",1);
468 i++;
469
470 memcpy(buff+i,". ",2); /* not cr/lf */
471 i+=2;
472 };
473
474 memcpy(buff+i,"\0",1);
475 i++;
476
477 return buff;
478 };
479
rdfstore_ntriples_node(RDF_Node * node)480 char * rdfstore_ntriples_node (
481 RDF_Node * node
482 ) {
483 int j=0,len=0;
484 char * buff=NULL;
485 register unsigned int i=0;
486 unsigned int utf8_size=0;
487
488 if ( ( node == NULL ) ||
489 ( ( node->type != 1 ) &&
490 ( node->value.resource.identifier == NULL ) ) )
491 return NULL;
492
493 if ( node->type == 0 ) {
494 len = node->value.resource.identifier_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 3;
495 } else if ( node->type == 2 ) {
496 len = node->value.resource.identifier_len + 3;
497 } else {
498 len = (node->value.literal.string != NULL ) ?
499 node->value.literal.string_len*(RDFSTORE_UTF8_MAXLEN+1+2) + 3 : 0;
500 if ( (node->value.literal.lang != NULL) &&
501 (strlen(node->value.literal.lang) > 0) )
502 len += strlen(node->value.literal.lang) + 1;
503 /* we propably should croak or warn the user if something is fishy with the rdf:dataType property */
504 if ( node->value.literal.parseType == 1 )
505 len += strlen(RDFSTORE_RDF_PARSETYPE_LITERAL) + 4;
506 else if ( node->value.literal.dataType != NULL )
507 len += strlen(node->value.literal.dataType) + 4;
508 };
509
510 buff = (char *) RDFSTORE_MALLOC( sizeof(char) * len );
511 if ( buff == NULL )
512 return NULL;
513
514 j=0;
515
516 /* NOTE: we should check that all the absoluteURI generated would be properly escaped accordingly to http://www.w3.org/TR/rdf-testcases/#sec-uri-encoding */
517
518 if ( node->type == 2 ) {
519 memcpy(buff+j,"_:",2);
520 j+=2;
521 memcpy(buff+j,node->value.resource.identifier,node->value.resource.identifier_len);
522 j+=node->value.resource.identifier_len;
523 } else if ( node->type == 0 ) {
524 int uri_len = 0;
525 memcpy(buff+j,"<",1);
526 j++;
527 uri_len = node->value.resource.identifier_len;
528 for(i=0; i < uri_len; ) {
529 if( node->value.resource.identifier[i] == 0x09 ) {
530 memcpy(buff+j,"\\t",2);
531 j+=2;
532 i++;
533 continue;
534 } else if( node->value.resource.identifier[i] == 0x0a ) {
535 memcpy(buff+j,"\\n",2);
536 j+=2;
537 i++;
538 continue;
539 } else if( node->value.resource.identifier[i] == 0x0d ) {
540 memcpy(buff+j,"\\r",2);
541 j+=2;
542 i++;
543 continue;
544 } else if( node->value.resource.identifier[i] == 0x5c ) {
545 memcpy(buff+j,"\\\\",2);
546 j+=2;
547 i++;
548 continue;
549 } else if( node->value.resource.identifier[i] == 0x22 ) {
550 memcpy(buff+j,"\\\"",2);
551 j+=2;
552 i++;
553 continue;
554 };
555 if ( ( rdfstore_utf8_is_utf8( node->value.resource.identifier+i, &utf8_size ) ) && ( utf8_size > 1 ) ) {
556 unsigned long cp=0;
557 unsigned char es[8];
558
559 if ( rdfstore_utf8_utf8_to_cp( utf8_size, node->value.resource.identifier+i, &cp ) ) {
560 RDFSTORE_FREE( buff );
561 return NULL;
562 };
563
564 if(utf8_size<=4) {
565 sprintf(es, "\\u%04lX", cp);
566 } else {
567 sprintf(es, "\\U%08lX", cp);
568 };
569 memcpy(buff+j,es,strlen(es));
570 j+=strlen(es);
571 i+=utf8_size;
572 } else {
573 memcpy(buff+j,node->value.resource.identifier+i,utf8_size);
574 j+=utf8_size;
575 i++;
576 };
577 };
578 memcpy(buff+j,">",1);
579 j++;
580 } else if ( node->type == 1 ) {
581 memcpy(buff+j,"\"",1);
582 j++;
583
584 if ( node->value.literal.string != NULL ) {
585
586 /* here we convert the string to RDFSTORE_UTF8 and then escape it accordingly to http://www.w3.org/TR/rdf-testcases/#ntrip_strings */
587 for(i=0; i < node->value.literal.string_len; ) {
588 if( node->value.literal.string[i] == 0x09 ) {
589 memcpy(buff+j,"\\t",2);
590 j+=2;
591 i++;
592 continue;
593 } else if( node->value.literal.string[i] == 0x0a ) {
594 memcpy(buff+j,"\\n",2);
595 j+=2;
596 i++;
597 continue;
598 } else if( node->value.literal.string[i] == 0x0d ) {
599 memcpy(buff+j,"\\r",2);
600 j+=2;
601 i++;
602 continue;
603 } else if( node->value.literal.string[i] == 0x5c ) {
604 memcpy(buff+j,"\\\\",2);
605 j+=2;
606 i++;
607 continue;
608 } else if( node->value.literal.string[i] == 0x22 ) {
609 memcpy(buff+j,"\\\"",2);
610 j+=2;
611 i++;
612 continue;
613 };
614 if ( ( rdfstore_utf8_is_utf8( node->value.literal.string+i, &utf8_size ) ) && ( utf8_size > 1 ) ) {
615 unsigned long cp=0;
616 unsigned char es[8];
617
618 if ( rdfstore_utf8_utf8_to_cp( utf8_size, node->value.literal.string+i, &cp ) ) {
619 RDFSTORE_FREE( buff );
620 return NULL;
621 };
622
623 if(utf8_size<=4) {
624 sprintf(es, "\\u%04lX", cp);
625 } else {
626 sprintf(es, "\\U%08lX", cp);
627 };
628 memcpy(buff+j,es,strlen(es));
629 j+=strlen(es);
630 i+=utf8_size;
631 } else {
632 memcpy(buff+j,node->value.literal.string+i,utf8_size);
633 j+=utf8_size;
634 i++;
635 };
636 };
637 };
638
639 memcpy(buff+j,"\"",1);
640 j++;
641
642 if( (node->value.literal.lang != NULL) &&
643 (strlen(node->value.literal.lang) > 0) ) {
644 memcpy(buff+j,"@",1);
645 j++;
646 /* we should check that the language tag is also well-formed and escaped */
647 memcpy(buff+j,node->value.literal.lang,strlen(node->value.literal.lang));
648 j+=strlen(node->value.literal.lang);
649 };
650
651 if( node->value.literal.parseType == 1 ) {
652 memcpy(buff+j,"^^",2);
653 j+=2;
654 memcpy(buff+j,"<",1);
655 j++;
656 memcpy(buff+j,RDFSTORE_RDF_PARSETYPE_LITERAL,strlen(RDFSTORE_RDF_PARSETYPE_LITERAL));
657 j+=strlen(RDFSTORE_RDF_PARSETYPE_LITERAL);
658 memcpy(buff+j,">",1);
659 j++;
660 } else if ( node->value.literal.dataType != NULL ) {
661 memcpy(buff+j,"^^",2);
662 j+=2;
663 memcpy(buff+j,"<",1);
664 j++;
665 /* we should check that the data type URI ref is a valid XMLSchema data type perhpas */
666 memcpy(buff+j,node->value.literal.dataType,strlen(node->value.literal.dataType));
667 j+=strlen(node->value.literal.dataType);
668 memcpy(buff+j,">",1);
669 j++;
670 };
671 } else {
672 RDFSTORE_FREE( buff );
673 perror("rdfstore_ntriples_node");
674 fprintf(stderr,"Could not generate ntriple for node: unknown node type\n");
675 return NULL;
676 };
677
678 memcpy(buff+j,"\0",1);
679 j++;
680
681 return buff;
682 };
683
684 /* the following two subroutines do not consider EBCDIC codes still! */
rdfstore_ntriples_hex2c(const char * x)685 int rdfstore_ntriples_hex2c(const char *x) {
686 int i;
687 int ch;
688
689 ch = x[0];
690
691 if (isdigit( ((unsigned char)(ch)) ))
692 i = ch - '0';
693 else if (isupper( ((unsigned char)(ch)) ))
694 i = ch - ('A' - 10);
695 else
696 i = ch - ('a' - 10);
697
698 i <<= 4;
699
700 ch = x[1];
701 if (isdigit( ((unsigned char)(ch)) ))
702 i += ch - '0';
703 else if (isupper( ((unsigned char)(ch)) ))
704 i += ch - ('A' - 10);
705 else
706 i += ch - ('a' - 10);
707
708 return i;
709 };
710
rdfstore_ntriples_c2hex(int ch,char * x)711 void rdfstore_ntriples_c2hex(int ch, char *x) {
712 int i;
713
714 x[0] = '%';
715 i = (ch & 0xF0) >> 4;
716
717 if (i >= 10)
718 x[1] = ('A' - 10) + i;
719 else
720 x[1] = '0' + i;
721
722 i = ch & 0x0F;
723
724 if (i >= 10)
725 x[2] = ('A' - 10) + i;
726 else
727 x[2] = '0' + i;
728 };
729