1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_general.c - Rasqal library startup, shutdown and factories
4 *
5 * Copyright (C) 2004-2014, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
7 *
8 * This package is Free Software and part of Redland http://librdf.org/
9 *
10 * It is licensed under the following three licenses as alternatives:
11 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12 * 2. GNU General Public License (GPL) V2 or any newer version
13 * 3. Apache License, V2.0 or any newer version
14 *
15 * You may not use this file except in compliance with at least one of
16 * the above three licenses.
17 *
18 * See LICENSE.html or LICENSE.txt at the top of this package for the
19 * complete terms and further detail along with the license texts for
20 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21 *
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <rasqal_config.h>
27 #endif
28
29 #ifdef WIN32
30 #include <win32_rasqal_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 #include <stdarg.h>
39
40 #include "rasqal.h"
41 #include "rasqal_internal.h"
42
43 #ifdef MAINTAINER_MODE
44 #include <git-version.h>
45 #endif
46
47 /* prototypes for helper functions */
48 static void rasqal_delete_query_language_factories(rasqal_world*);
49 static void rasqal_free_query_language_factory(rasqal_query_language_factory *factory);
50
51
52 /* statics */
53
54 const char * const rasqal_short_copyright_string = "Copyright 2003-2014 David Beckett. Copyright 2003-2005 University of Bristol";
55
56 const char * const rasqal_copyright_string = "Copyright (C) 2003-2014 David Beckett - http://www.dajobe.org/\nCopyright (C) 2003-2005 University of Bristol - http://www.bristol.ac.uk/";
57
58 const char * const rasqal_license_string = "LGPL 2.1 or newer, GPL 2 or newer, Apache 2.0 or newer.\nSee http://librdf.org/rasqal/LICENSE.html for full terms.";
59
60 const char * const rasqal_home_url_string = "http://librdf.org/rasqal/";
61
62 /**
63 * rasqal_version_string:
64 *
65 * Library full version as a string.
66 *
67 * See also #rasqal_version_decimal.
68 */
69 const char * const rasqal_version_string = RASQAL_VERSION_STRING
70 #ifdef GIT_VERSION
71 " GIT " GIT_VERSION
72 #endif
73 ;
74
75 /**
76 * rasqal_version_major:
77 *
78 * Library major version number as a decimal integer.
79 */
80 const unsigned int rasqal_version_major = RASQAL_VERSION_MAJOR;
81
82 /**
83 * rasqal_version_minor:
84 *
85 * Library minor version number as a decimal integer.
86 */
87 const unsigned int rasqal_version_minor = RASQAL_VERSION_MINOR;
88
89 /**
90 * rasqal_version_release:
91 *
92 * Library release version number as a decimal integer.
93 */
94 const unsigned int rasqal_version_release = RASQAL_VERSION_RELEASE;
95
96 /**
97 * rasqal_version_decimal:
98 *
99 * Library full version as a decimal integer.
100 *
101 * See also #rasqal_version_string.
102 */
103 const unsigned int rasqal_version_decimal = RASQAL_VERSION;
104
105
106 /**
107 * rasqal_new_world:
108 *
109 * Allocate a new rasqal_world object.
110 *
111 * The rasqal_world is initialized with rasqal_world_open().
112 * Allocation and initialization are decoupled to allow
113 * changing settings on the world object before init.
114 *
115 * Return value: rasqal_world object or NULL on failure
116 **/
117 rasqal_world*
rasqal_new_world(void)118 rasqal_new_world(void)
119 {
120 rasqal_world* world;
121
122 world = RASQAL_CALLOC(rasqal_world*, 1, sizeof(*world));
123 if(!world)
124 return NULL;
125
126 world->warning_level = RASQAL_WARNING_LEVEL_DEFAULT;
127
128 world->genid_counter = 1;
129
130 return world;
131 }
132
133
134 /**
135 * rasqal_world_open:
136 * @world: rasqal_world object
137 *
138 * Initialise the rasqal library.
139 *
140 * Initializes a #rasqal_world object created by rasqal_new_world().
141 * Allocation and initialization are decoupled to allow
142 * changing settings on the world object before init.
143 * These settings include e.g. the raptor library instance set with
144 * rasqal_world_set_raptor().
145 *
146 * The initialized world object is used with subsequent rasqal API calls.
147 *
148 * Return value: non-0 on failure
149 **/
150 int
rasqal_world_open(rasqal_world * world)151 rasqal_world_open(rasqal_world *world)
152 {
153 int rc;
154
155 if(!world)
156 return -1;
157
158 if(world->opened++)
159 return 0; /* not an error */
160
161 /* Create and init a raptor_world unless one is provided externally with rasqal_world_set_raptor() */
162 if(!world->raptor_world_ptr) {
163 world->raptor_world_ptr = raptor_new_world();
164 if(!world->raptor_world_ptr)
165 return -1;
166 world->raptor_world_allocated_here = 1;
167 rc = raptor_world_open(world->raptor_world_ptr);
168 if(rc)
169 return rc;
170 }
171
172 rc = rasqal_uri_init(world);
173 if(rc)
174 return rc;
175
176 rc = rasqal_xsd_init(world);
177 if(rc)
178 return rc;
179
180 world->query_languages = raptor_new_sequence((raptor_data_free_handler)rasqal_free_query_language_factory, NULL);
181 if(!world->query_languages)
182 return 1;
183
184 /* first query language declared is the default */
185
186 #ifdef RASQAL_QUERY_SPARQL
187 rc = rasqal_init_query_language_sparql(world);
188 if(rc)
189 return rc;
190
191 rc = rasqal_init_query_language_sparql11(world);
192 if(rc)
193 return rc;
194 #endif
195
196 #ifdef RASQAL_QUERY_LAQRS
197 rc = rasqal_init_query_language_laqrs(world);
198 if(rc)
199 return rc;
200 #endif
201
202 rc = rasqal_raptor_init(world);
203 if(rc)
204 return rc;
205
206 rc = rasqal_init_query_results();
207 if(rc)
208 return rc;
209
210 rc = rasqal_init_result_formats(world);
211 if(rc)
212 return rc;
213
214 return 0;
215 }
216
217
218 /**
219 * rasqal_free_world:
220 * @world: rasqal_world object
221 *
222 * Terminate the rasqal library.
223 *
224 * Destroys a rasqal_world object and all static information.
225 *
226 **/
227 void
rasqal_free_world(rasqal_world * world)228 rasqal_free_world(rasqal_world* world)
229 {
230 if(!world)
231 return;
232
233 rasqal_finish_result_formats(world);
234 rasqal_finish_query_results();
235
236 rasqal_delete_query_language_factories(world);
237
238 #ifdef RAPTOR_TRIPLES_SOURCE_REDLAND
239 rasqal_redland_finish();
240 #endif
241
242 rasqal_xsd_finish(world);
243
244 rasqal_uri_finish(world);
245
246 if(world->raptor_world_ptr && world->raptor_world_allocated_here)
247 raptor_free_world(world->raptor_world_ptr);
248
249 RASQAL_FREE(rasqal_world, world);
250 }
251
252
253 /**
254 * rasqal_world_set_raptor:
255 * @world: rasqal_world object
256 * @raptor_world_ptr: raptor_world object
257 *
258 * Set the #raptor_world instance to be used with this #rasqal_world.
259 *
260 * If no raptor_world instance is set with this function,
261 * rasqal_world_open() creates a new instance.
262 *
263 * Ownership of the raptor_world is not taken. If the raptor library
264 * instance is set with this function, rasqal_free_world() will not
265 * free it.
266 *
267 **/
268 void
rasqal_world_set_raptor(rasqal_world * world,raptor_world * raptor_world_ptr)269 rasqal_world_set_raptor(rasqal_world* world, raptor_world* raptor_world_ptr)
270 {
271 RASQAL_ASSERT_OBJECT_POINTER_RETURN(world, rasqal_world);
272 world->raptor_world_ptr = raptor_world_ptr;
273 }
274
275
276 /**
277 * rasqal_world_get_raptor:
278 * @world: rasqal_world object
279 *
280 * Get the #raptor_world instance used by this #rasqal_world.
281 *
282 * Return value: raptor_world object or NULL on failure (e.g. not initialized)
283 **/
284 raptor_world*
rasqal_world_get_raptor(rasqal_world * world)285 rasqal_world_get_raptor(rasqal_world* world)
286 {
287 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
288 return world->raptor_world_ptr;
289 }
290
291
292 /**
293 * rasqal_world_set_log_handler:
294 * @world: rasqal_world object
295 * @user_data: user data for log handler function
296 * @handler: log handler function
297 *
298 * Set the log handler for this rasqal_world.
299 *
300 * Also sets the raptor log handler to the same @user_data and
301 * @handler via raptor_world_set_log_handler(). (Rasqal 0.9.26+)
302 **/
303 void
rasqal_world_set_log_handler(rasqal_world * world,void * user_data,raptor_log_handler handler)304 rasqal_world_set_log_handler(rasqal_world* world, void *user_data,
305 raptor_log_handler handler)
306 {
307 RASQAL_ASSERT_OBJECT_POINTER_RETURN(world, rasqal_world);
308
309 world->log_handler = handler;
310 world->log_handler_user_data = user_data;
311
312 raptor_world_set_log_handler(world->raptor_world_ptr, user_data, handler);
313 }
314
315
316 /* helper functions */
317
318 /*
319 * rasqal_free_query_language_factory - delete a query language factory
320 */
321 static void
rasqal_free_query_language_factory(rasqal_query_language_factory * factory)322 rasqal_free_query_language_factory(rasqal_query_language_factory *factory)
323 {
324 if(!factory)
325 return;
326
327 if(factory->finish_factory)
328 factory->finish_factory(factory);
329
330 RASQAL_FREE(rasqal_query_language_factory, factory);
331 }
332
333
334 /*
335 * rasqal_delete_query_language_factories - helper function to delete all the registered query language factories
336 */
337 static void
rasqal_delete_query_language_factories(rasqal_world * world)338 rasqal_delete_query_language_factories(rasqal_world *world)
339 {
340 if(world->query_languages) {
341 raptor_free_sequence(world->query_languages);
342 world->query_languages = NULL;
343 }
344 }
345
346
347 /* class methods */
348
349 /*
350 * rasqal_query_language_register_factory:
351 * @factory: pointer to function to call to register the factory
352 *
353 * INTERNAL - Register a query language syntax handled by a query factory
354 *
355 * Return value: new factory or NULL on failure
356 **/
357 RASQAL_EXTERN_C
358 rasqal_query_language_factory*
rasqal_query_language_register_factory(rasqal_world * world,int (* factory)(rasqal_query_language_factory *))359 rasqal_query_language_register_factory(rasqal_world *world,
360 int (*factory) (rasqal_query_language_factory*))
361 {
362 rasqal_query_language_factory *query = NULL;
363
364 query = RASQAL_CALLOC(rasqal_query_language_factory*, 1, sizeof(*query));
365 if(!query)
366 goto tidy;
367
368 query->world = world;
369
370 if(raptor_sequence_push(world->query_languages, query))
371 return NULL; /* on error, query is already freed by the sequence */
372
373 /* Call the query registration function on the new object */
374 if(factory(query))
375 return NULL; /* query is owned and freed by the query_languages sequence */
376
377 if(raptor_syntax_description_validate(&query->desc)) {
378 rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, NULL,
379 "Query language format description failed to validate\n");
380 goto tidy;
381 }
382
383 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
384 RASQAL_DEBUG3("Registered query language %s with context size %d\n",
385 query->desc.names[0], query->context_length);
386 #endif
387
388 return query;
389
390 /* Clean up on failure */
391 tidy:
392 if(query)
393 rasqal_free_query_language_factory(query);
394
395 return NULL;
396 }
397
398
399 /**
400 * rasqal_get_query_language_factory:
401 * @name: the factory name or NULL for the default factory
402 * @uri: the query syntax URI or NULL
403 *
404 * Get a query factory by name.
405 *
406 * Return value: the factory object or NULL if there is no such factory
407 **/
408 rasqal_query_language_factory*
rasqal_get_query_language_factory(rasqal_world * world,const char * name,const unsigned char * uri)409 rasqal_get_query_language_factory(rasqal_world *world, const char *name,
410 const unsigned char *uri)
411 {
412 rasqal_query_language_factory *factory = NULL;
413
414 /* return 1st query language if no particular one wanted - why? */
415 if(!name) {
416 factory = (rasqal_query_language_factory*)raptor_sequence_get_at(world->query_languages, 0);
417 if(!factory) {
418 RASQAL_DEBUG1("No (default) query languages registered\n");
419 return NULL;
420 }
421 } else {
422 int i;
423
424 for(i = 0;
425 (factory = (rasqal_query_language_factory*)raptor_sequence_get_at(world->query_languages, i));
426 i++) {
427 int namei;
428 const char* fname;
429
430 for(namei = 0; (fname = factory->desc.names[namei]); namei++) {
431 if(!strcmp(fname, name))
432 break;
433 }
434 if(fname)
435 break;
436 }
437 }
438
439 return factory;
440 }
441
442
443 /**
444 * rasqal_world_get_query_language_description:
445 * @world: world object
446 * @counter: index into the list of query languages
447 *
448 * Get query language descriptive information
449 *
450 * Return value: description or NULL if counter is out of range
451 **/
452 const raptor_syntax_description*
rasqal_world_get_query_language_description(rasqal_world * world,unsigned int counter)453 rasqal_world_get_query_language_description(rasqal_world* world,
454 unsigned int counter)
455 {
456 rasqal_query_language_factory *factory;
457
458 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
459
460 rasqal_world_open(world);
461
462 factory = (rasqal_query_language_factory *)raptor_sequence_get_at(world->query_languages,
463 RASQAL_GOOD_CAST(int, counter));
464 if(!factory)
465 return NULL;
466
467 return &factory->desc;
468 }
469
470
471 #ifndef RASQAL_DISABLE_DEPRECATED
472 /**
473 * rasqal_languages_enumerate:
474 * @world: rasqal_world object
475 * @counter: index into the list of syntaxes
476 * @name: pointer to store the name of the syntax (or NULL)
477 * @label: pointer to store syntax readable label (or NULL)
478 * @uri_string: pointer to store syntax URI string (or NULL)
479 *
480 * @deprecated: Use rasqal_world_get_query_language_description() instead.
481 *
482 * Get information on query languages.
483 *
484 * Return value: non 0 on failure of if counter is out of range
485 **/
486 int
rasqal_languages_enumerate(rasqal_world * world,unsigned int counter,const char ** name,const char ** label,const unsigned char ** uri_string)487 rasqal_languages_enumerate(rasqal_world *world,
488 unsigned int counter,
489 const char **name, const char **label,
490 const unsigned char **uri_string)
491 {
492 rasqal_query_language_factory *factory;
493
494 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 1);
495 if(!name && !label && !uri_string)
496 return 1;
497
498 /* for compatibility with old API that does not call this - FIXME Remove V2 */
499 rasqal_world_open(world);
500
501 factory = (rasqal_query_language_factory*)raptor_sequence_get_at(world->query_languages,
502 RASQAL_GOOD_CAST(int, counter));
503 if(!factory)
504 return 1;
505
506 if(name)
507 *name = factory->desc.names[0];
508
509 if(label)
510 *label = factory->desc.label;
511
512 if(uri_string && factory->desc.uri_strings)
513 *uri_string = RASQAL_GOOD_CAST(const unsigned char*, factory->desc.uri_strings[0]);
514
515 return 0;
516 }
517 #endif
518
519 /**
520 * rasqal_language_name_check:
521 * @world: rasqal_world object
522 * @name: the query language name
523 *
524 * Check name of a query language.
525 *
526 * Return value: non 0 if name is a known query language
527 */
528 int
rasqal_language_name_check(rasqal_world * world,const char * name)529 rasqal_language_name_check(rasqal_world* world, const char *name)
530 {
531 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 0);
532
533 return (rasqal_get_query_language_factory(world, name, NULL) != NULL);
534 }
535
536
537 static const char* const rasqal_log_level_labels[RAPTOR_LOG_LEVEL_LAST+1]={
538 "none",
539 "trace",
540 "debug",
541 "info",
542 "warn",
543 "error",
544 "fatal"
545 };
546
547
548
549 /* internal */
550 void
rasqal_log_error_simple(rasqal_world * world,raptor_log_level level,raptor_locator * locator,const char * message,...)551 rasqal_log_error_simple(rasqal_world* world, raptor_log_level level,
552 raptor_locator* locator, const char* message, ...)
553 {
554 va_list arguments;
555
556 if(level == RAPTOR_LOG_LEVEL_NONE)
557 return;
558
559 va_start(arguments, message);
560 rasqal_log_error_varargs(world, level, locator, message, arguments);
561 va_end(arguments);
562 }
563
564
565 /* internal */
566 void
rasqal_log_warning_simple(rasqal_world * world,rasqal_warning_level warn_level,raptor_locator * locator,const char * message,...)567 rasqal_log_warning_simple(rasqal_world* world,
568 rasqal_warning_level warn_level,
569 raptor_locator* locator, const char* message, ...)
570 {
571 va_list arguments;
572
573 if(warn_level > world->warning_level)
574 return;
575
576 va_start(arguments, message);
577 rasqal_log_error_varargs(world, RAPTOR_LOG_LEVEL_WARN,
578 locator, message, arguments);
579 va_end(arguments);
580 }
581
582
583 void
rasqal_log_error_varargs(rasqal_world * world,raptor_log_level level,raptor_locator * locator,const char * message,va_list arguments)584 rasqal_log_error_varargs(rasqal_world* world, raptor_log_level level,
585 raptor_locator* locator,
586 const char* message, va_list arguments)
587 {
588 char *buffer;
589 size_t length;
590 raptor_log_message logmsg;
591 raptor_log_handler handler = world->log_handler;
592 void* handler_data = world->log_handler_user_data;
593
594 if(level == RAPTOR_LOG_LEVEL_NONE)
595 return;
596
597 buffer = NULL;
598 if(raptor_vasprintf(&buffer, message, arguments) < 0)
599 buffer = NULL;
600
601 if(!buffer) {
602 if(locator) {
603 raptor_locator_print(locator, stderr);
604 fputc(' ', stderr);
605 }
606 fputs("rasqal ", stderr);
607 fputs(rasqal_log_level_labels[level], stderr);
608 fputs(" - ", stderr);
609 vfprintf(stderr, message, arguments);
610 fputc('\n', stderr);
611 return;
612 }
613
614 length=strlen(buffer);
615 if(buffer[length-1]=='\n')
616 buffer[length-1]='\0';
617
618 if(handler) {
619 /* This is the single place in rasqal that the user error handler
620 * functions are called.
621 */
622 /* raptor2 raptor_log_handler */
623 logmsg.code = -1; /* no information to put as code */
624 logmsg.level = level;
625 logmsg.locator = locator;
626 logmsg.text = buffer;
627 handler(handler_data, &logmsg);
628 } else {
629 if(locator) {
630 raptor_locator_print(locator, stderr);
631 fputc(' ', stderr);
632 }
633 fputs("rasqal ", stderr);
634 fputs(rasqal_log_level_labels[level], stderr);
635 fputs(" - ", stderr);
636 fputs(buffer, stderr);
637 fputc('\n', stderr);
638 }
639
640 RASQAL_FREE(char*, buffer);
641 }
642
643
644 /*
645 * rasqal_query_simple_error - Error from a query - Internal
646 *
647 * Matches the raptor_simple_message_handler API but same as
648 * rasqal_query_error
649 */
650 void
rasqal_query_simple_error(void * user_data,const char * message,...)651 rasqal_query_simple_error(void* user_data, const char *message, ...)
652 {
653 rasqal_query* query=(rasqal_query*)user_data;
654
655 va_list arguments;
656
657 va_start(arguments, message);
658
659 query->failed=1;
660 rasqal_log_error_varargs(query->world,
661 RAPTOR_LOG_LEVEL_ERROR, NULL,
662 message, arguments);
663
664 va_end(arguments);
665 }
666
667
668 /*
669 * rasqal_world_simple_error:
670 *
671 * INTERNAL - Handle a simple error
672 *
673 * Matches the raptor_simple_message_handler API but with a world object
674 */
675 void
rasqal_world_simple_error(void * user_data,const char * message,...)676 rasqal_world_simple_error(void* user_data, const char *message, ...)
677 {
678 rasqal_world* world = (rasqal_world*)user_data;
679
680 va_list arguments;
681
682 va_start(arguments, message);
683
684 rasqal_log_error_varargs(world,
685 RAPTOR_LOG_LEVEL_ERROR, NULL,
686 message, arguments);
687
688 va_end(arguments);
689 }
690
691
692 /* wrapper */
693 const char*
rasqal_basename(const char * name)694 rasqal_basename(const char *name)
695 {
696 const char *p;
697 if((p = strrchr(name, '/')))
698 name = p+1;
699 else if((p = strrchr(name, '\\')))
700 name = p+1;
701
702 return name;
703 }
704
705
706 const raptor_unichar rasqal_unicode_max_codepoint = 0x10FFFF;
707
708 /**
709 * rasqal_escaped_name_to_utf8_string:
710 * @src: source name string
711 * @len: length of source name string
712 * @dest_lenp: pointer to store result string (or NULL)
713 * @error_handler: error handling function
714 * @error_data: data for error handle
715 *
716 * Get a UTF-8 and/or \u-escaped name as UTF-8.
717 *
718 * If dest_lenp is not NULL, the length of the resulting string is
719 * stored at the pointed size_t.
720 *
721 * Return value: new UTF-8 string or NULL on failure.
722 */
723 unsigned char*
rasqal_escaped_name_to_utf8_string(const unsigned char * src,size_t len,size_t * dest_lenp,int (* error_handler)(rasqal_query * error_data,const char * message,...),rasqal_query * error_data)724 rasqal_escaped_name_to_utf8_string(const unsigned char *src, size_t len,
725 size_t *dest_lenp,
726 int (*error_handler)(rasqal_query *error_data, const char *message, ...),
727 rasqal_query* error_data)
728 {
729 const unsigned char *p=src;
730 size_t ulen=0;
731 unsigned long unichar=0;
732 unsigned char *result;
733 unsigned char *dest;
734 unsigned char *endp;
735 int n;
736
737 result = RASQAL_MALLOC(unsigned char*, len + 1);
738 if(!result)
739 return NULL;
740
741 dest = result;
742 endp = result + len;
743
744 /* find end of string, fixing backslashed characters on the way */
745 while(len > 0) {
746 unsigned char c=*p;
747
748 if(c > 0x7f) {
749 /* just copy the UTF-8 bytes through */
750 size_t unichar_len = RASQAL_GOOD_CAST(size_t, raptor_unicode_utf8_string_get_char(RASQAL_GOOD_CAST(const unsigned char*, p), len + 1, NULL));
751 if(unichar_len > len) {
752 if(error_handler)
753 error_handler(error_data, "UTF-8 encoding error at character %d (0x%02X) found.", c, c);
754 /* UTF-8 encoding had an error or ended in the middle of a string */
755 RASQAL_FREE(char*, result);
756 return NULL;
757 }
758 memcpy(dest, p, unichar_len);
759 dest+= unichar_len;
760 p += unichar_len;
761 len -= unichar_len;
762 continue;
763 }
764
765 p++; len--;
766
767 if(c != '\\') {
768 /* not an escape - store and move on */
769 *dest++=c;
770 continue;
771 }
772
773 if(!len) {
774 RASQAL_FREE(char*, result);
775 return NULL;
776 }
777
778 c = *p++; len--;
779
780 switch(c) {
781 case '"':
782 case '\\':
783 *dest++=c;
784 break;
785 case 'u':
786 case 'U':
787 ulen=(c == 'u') ? 4 : 8;
788
789 if(len < ulen) {
790 if(error_handler)
791 error_handler(error_data, "%c over end of line", c);
792 RASQAL_FREE(char*, result);
793 return 0;
794 }
795
796 n = sscanf(RASQAL_GOOD_CAST(const char*, p), ((ulen == 4) ? "%04lx" : "%08lx"), &unichar);
797 if(n != 1) {
798 if(error_handler)
799 error_handler(error_data, "Bad %c escape", c);
800 break;
801 }
802
803 p+=ulen;
804 len-=ulen;
805
806 if(unichar > 0x10ffff) {
807 if(error_handler)
808 error_handler(error_data, "Illegal Unicode character with code point #x%lX.", unichar);
809 break;
810 }
811
812 dest += raptor_unicode_utf8_string_put_char(unichar, dest,
813 RASQAL_GOOD_CAST(size_t, endp - dest));
814 break;
815
816 default:
817 if(error_handler)
818 error_handler(error_data, "Illegal string escape \\%c in \"%s\"", c, src);
819 RASQAL_FREE(char*, result);
820 return 0;
821 }
822
823 } /* end while */
824
825
826 /* terminate dest, can be shorter than source */
827 *dest='\0';
828
829 if(dest_lenp)
830 *dest_lenp = RASQAL_GOOD_CAST(size_t, dest - result);
831
832 return result;
833 }
834
835
836 int
rasqal_uri_init(rasqal_world * world)837 rasqal_uri_init(rasqal_world* world)
838 {
839 world->rdf_namespace_uri = raptor_new_uri(world->raptor_world_ptr, raptor_rdf_namespace_uri);
840 if(!world->rdf_namespace_uri)
841 goto oom;
842
843 world->rdf_first_uri = raptor_new_uri_from_uri_local_name(world->raptor_world_ptr, world->rdf_namespace_uri, RASQAL_GOOD_CAST(const unsigned char*, "first"));
844 world->rdf_rest_uri = raptor_new_uri_from_uri_local_name(world->raptor_world_ptr, world->rdf_namespace_uri, RASQAL_GOOD_CAST(const unsigned char*, "rest"));
845 world->rdf_nil_uri = raptor_new_uri_from_uri_local_name(world->raptor_world_ptr, world->rdf_namespace_uri, RASQAL_GOOD_CAST(const unsigned char*, "nil"));
846 if(!world->rdf_first_uri || !world->rdf_rest_uri || !world->rdf_nil_uri)
847 goto oom;
848
849 return 0;
850
851 oom:
852 rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_FATAL,
853 NULL,
854 "Out of memory in rasqal_uri_init()");
855 return 1;
856 }
857
858
859 void
rasqal_uri_finish(rasqal_world * world)860 rasqal_uri_finish(rasqal_world* world)
861 {
862 if(world->rdf_first_uri) {
863 raptor_free_uri(world->rdf_first_uri);
864 world->rdf_first_uri=NULL;
865 }
866 if(world->rdf_rest_uri) {
867 raptor_free_uri(world->rdf_rest_uri);
868 world->rdf_rest_uri=NULL;
869 }
870 if(world->rdf_nil_uri) {
871 raptor_free_uri(world->rdf_nil_uri);
872 world->rdf_nil_uri=NULL;
873 }
874 if(world->rdf_namespace_uri) {
875 raptor_free_uri(world->rdf_namespace_uri);
876 world->rdf_namespace_uri=NULL;
877 }
878 }
879
880
881 /**
882 * rasqal_world_set_default_generate_bnodeid_parameters:
883 * @world: #rasqal_world object
884 * @prefix: prefix string
885 * @base: integer base identifier
886 *
887 * Set default bnodeid generation parameters
888 *
889 * Sets the parameters for the default algorithm used to generate
890 * blank node IDs. The default algorithm uses both @prefix and @base
891 * to generate a new identifier. The exact identifier generated is
892 * not guaranteed to be a strict concatenation of @prefix and @base
893 * but will use both parts.
894 *
895 * For finer control of the generated identifiers, use
896 * rasqal_world_set_generate_bnodeid_handler()
897 *
898 * If prefix is NULL, the default prefix is used (currently "bnodeid")
899 * If base is less than 1, it is initialised to 1.
900 *
901 * Return value: non-0 on failure
902 **/
903 int
rasqal_world_set_default_generate_bnodeid_parameters(rasqal_world * world,char * prefix,int base)904 rasqal_world_set_default_generate_bnodeid_parameters(rasqal_world* world,
905 char *prefix, int base)
906 {
907 char *prefix_copy = NULL;
908 size_t length = 0;
909
910 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 1);
911
912 if(--base < 0)
913 base = 0;
914
915 if(prefix) {
916 length = strlen(prefix);
917
918 prefix_copy = RASQAL_MALLOC(char*, length + 1);
919 if(!prefix_copy)
920 return 1;
921 memcpy(prefix_copy, prefix, length + 1);
922 }
923
924 if(world->default_generate_bnodeid_handler_prefix)
925 RASQAL_FREE(char*, world->default_generate_bnodeid_handler_prefix);
926
927 world->default_generate_bnodeid_handler_prefix = prefix_copy;
928 world->default_generate_bnodeid_handler_prefix_length = length;
929 world->default_generate_bnodeid_handler_base = base;
930
931 return 0;
932 }
933
934
935 /**
936 * rasqal_world_set_generate_bnodeid_handler:
937 * @world: #rasqal_world object
938 * @user_data: user data pointer for callback
939 * @handler: generate blank ID callback function
940 *
941 * Set the generate blank node ID handler function
942 *
943 * Sets the function to generate blank node IDs.
944 * The handler is called with a pointer to the rasqal_world, the
945 * @user_data pointer and a user_bnodeid which is the value of
946 * a user-provided blank node identifier (may be NULL).
947 * It can either be returned directly as the generated value when present or
948 * modified. The passed in value must be free()d if it is not used.
949 *
950 * If handler is NULL, the default method is used
951 *
952 * Return value: non-0 on failure
953 **/
954 int
rasqal_world_set_generate_bnodeid_handler(rasqal_world * world,void * user_data,rasqal_generate_bnodeid_handler handler)955 rasqal_world_set_generate_bnodeid_handler(rasqal_world* world,
956 void *user_data,
957 rasqal_generate_bnodeid_handler handler)
958 {
959 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 1);
960
961 world->generate_bnodeid_handler_user_data = user_data;
962 world->generate_bnodeid_handler = handler;
963
964 return 0;
965 }
966
967
968 unsigned char*
rasqal_world_default_generate_bnodeid_handler(void * user_data,unsigned char * user_bnodeid)969 rasqal_world_default_generate_bnodeid_handler(void *user_data,
970 unsigned char *user_bnodeid)
971 {
972 rasqal_world *world = (rasqal_world*)user_data;
973 int id;
974 unsigned char *buffer;
975 size_t length;
976 int tmpid;
977
978 if(user_bnodeid)
979 return user_bnodeid;
980
981 id = ++world->default_generate_bnodeid_handler_base;
982
983 tmpid = id;
984 length = 2; /* min length 1 + \0 */
985 while(tmpid /= 10)
986 length++;
987
988 if(world->default_generate_bnodeid_handler_prefix)
989 length += world->default_generate_bnodeid_handler_prefix_length;
990 else
991 length += 7; /* bnodeid */
992
993 buffer = RASQAL_MALLOC(unsigned char*, length);
994 if(!buffer)
995 return NULL;
996 if(world->default_generate_bnodeid_handler_prefix) {
997 memcpy(buffer, world->default_generate_bnodeid_handler_prefix,
998 world->default_generate_bnodeid_handler_prefix_length);
999 sprintf(RASQAL_GOOD_CAST(char*, buffer) + world->default_generate_bnodeid_handler_prefix_length,
1000 "%d", id);
1001 } else
1002 sprintf(RASQAL_GOOD_CAST(char*, buffer), "bnodeid%d", id);
1003
1004 return buffer;
1005 }
1006
1007
1008 /*
1009 * rasqal_generate_bnodeid:
1010 *
1011 * Internal - Default generate ID
1012 */
1013 unsigned char*
rasqal_world_generate_bnodeid(rasqal_world * world,unsigned char * user_bnodeid)1014 rasqal_world_generate_bnodeid(rasqal_world* world,
1015 unsigned char *user_bnodeid)
1016 {
1017 if(world->generate_bnodeid_handler)
1018 return world->generate_bnodeid_handler(world,
1019 world->generate_bnodeid_handler_user_data, user_bnodeid);
1020 else
1021 return rasqal_world_default_generate_bnodeid_handler(world, user_bnodeid);
1022 }
1023
1024
1025 /**
1026 * rasqal_world_reset_now:
1027 * @world: world
1028 *
1029 * Internal - Mark current now value as invalid
1030 *
1031 * Intended to be run before starting a query so that the
1032 * value is recalculated.
1033 *
1034 * Return value: non-0 on failure
1035 */
1036 int
rasqal_world_reset_now(rasqal_world * world)1037 rasqal_world_reset_now(rasqal_world* world)
1038 {
1039 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 1);
1040
1041 world->now_set = 0;
1042
1043 return 0;
1044 }
1045
1046 #ifndef HAVE_GETTIMEOFDAY
1047 #define gettimeofday(x,y) rasqal_gettimeofday(x,y)
1048 #endif
1049
1050 /**
1051 * rasqal_world_get_now_timeval:
1052 * @world: world
1053 *
1054 * Internal - Get current now timeval
1055 *
1056 * Return value: pointer to timeval or NULL on failure
1057 */
1058 struct timeval*
rasqal_world_get_now_timeval(rasqal_world * world)1059 rasqal_world_get_now_timeval(rasqal_world* world)
1060 {
1061 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1062
1063 if(!world->now_set) {
1064 if(gettimeofday(&world->now, NULL))
1065 return NULL;
1066
1067 world->now_set = 1;
1068 }
1069
1070 return &world->now;
1071 }
1072
1073
1074 /**
1075 * rasqal_world_set_warning_level:
1076 * @world: world
1077 * @warning_level: warning level 0..100
1078 *
1079 * Set the rasqal warning reporting level
1080 *
1081 * The warning levels used are as follows:
1082 * <orderedlist>
1083 * <listitem><para>Level 10 is used for serious warnings that may be errors.
1084 * </para></listitem>
1085 * <listitem><para>Level 30 is used for moderate style warnings.
1086 * </para></listitem>
1087 * <listitem><para>Level 90 is used for strict conformance warnings.
1088 * </para></listitem>
1089 * </orderedlist>
1090 *
1091 * When this method is called to set a warning level, only warnings
1092 * of less than @warning_level are reported. The default warning
1093 * level is 50.
1094 *
1095 * Return value: non-0 on failure
1096 */
1097 int
rasqal_world_set_warning_level(rasqal_world * world,unsigned int warning_level)1098 rasqal_world_set_warning_level(rasqal_world* world,
1099 unsigned int warning_level)
1100 {
1101 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, 1);
1102
1103 if(warning_level > RASQAL_WARNING_LEVEL_MAX)
1104 return 1;
1105
1106 world->warning_level = (rasqal_warning_level)warning_level;
1107
1108 return 0;
1109 }
1110
1111
1112 /**
1113 * rasqal_free_memory:
1114 * @ptr: memory pointer
1115 *
1116 * Free memory allocated inside rasqal.
1117 *
1118 * Some systems require memory allocated in a library to
1119 * be deallocated in that library. This function allows
1120 * memory allocated by rasqal to be freed.
1121 *
1122 **/
1123 void
rasqal_free_memory(void * ptr)1124 rasqal_free_memory(void *ptr)
1125 {
1126 if(!ptr)
1127 return;
1128
1129 RASQAL_FREE(void, ptr);
1130 }
1131
1132
1133 /**
1134 * rasqal_alloc_memory:
1135 * @size: size of memory to allocate
1136 *
1137 * Allocate memory inside rasqal.
1138 *
1139 * Some systems require memory allocated in a library to
1140 * be deallocated in that library. This function allows
1141 * memory to be allocated inside the rasqal shared library
1142 * that can be freed inside rasqal either internally or via
1143 * rasqal_free_memory().
1144 *
1145 * Return value: the address of the allocated memory or NULL on failure
1146 *
1147 **/
1148 void*
rasqal_alloc_memory(size_t size)1149 rasqal_alloc_memory(size_t size)
1150 {
1151 return RASQAL_MALLOC(void*, size);
1152 }
1153
1154
1155 /**
1156 * rasqal_calloc_memory:
1157 * @nmemb: number of members
1158 * @size: size of item
1159 *
1160 * Allocate zeroed array of items inside rasqal.
1161 *
1162 * Some systems require memory allocated in a library to
1163 * be deallocated in that library. This function allows
1164 * memory to be allocated inside the rasqal shared library
1165 * that can be freed inside rasqal either internally or via
1166 * rasqal_free_memory().
1167 *
1168 * Return value: the address of the allocated memory or NULL on failure
1169 *
1170 **/
1171 void*
rasqal_calloc_memory(size_t nmemb,size_t size)1172 rasqal_calloc_memory(size_t nmemb, size_t size)
1173 {
1174 return RASQAL_CALLOC(void*, nmemb, size);
1175 }
1176
1177
1178 #if defined (RASQAL_DEBUG) && defined(RASQAL_MEMORY_SIGN)
1179 void*
rasqal_sign_malloc(size_t size)1180 rasqal_sign_malloc(size_t size)
1181 {
1182 int *p;
1183
1184 size += sizeof(int);
1185
1186 p=(int*)malloc(size);
1187 *p++ = RASQAL_SIGN_KEY;
1188 return p;
1189 }
1190
1191 void*
rasqal_sign_calloc(size_t nmemb,size_t size)1192 rasqal_sign_calloc(size_t nmemb, size_t size)
1193 {
1194 int *p;
1195
1196 /* turn into bytes */
1197 size = nmemb*size + sizeof(int);
1198
1199 p=(int*)calloc(1, size);
1200 *p++ = RASQAL_SIGN_KEY;
1201 return p;
1202 }
1203
1204 void*
rasqal_sign_realloc(void * ptr,size_t size)1205 rasqal_sign_realloc(void *ptr, size_t size)
1206 {
1207 int *p;
1208
1209 if(!ptr)
1210 return rasqal_sign_malloc(size);
1211
1212 p=(int*)ptr;
1213 p--;
1214
1215 if(*p != RASQAL_SIGN_KEY)
1216 RASQAL_FATAL3("memory signature %08X != %08X", *p, RASQAL_SIGN_KEY);
1217
1218 size += sizeof(int);
1219
1220 p=(int*)realloc(p, size);
1221 *p++= RASQAL_SIGN_KEY;
1222 return p;
1223 }
1224
1225 void
rasqal_sign_free(void * ptr)1226 rasqal_sign_free(void *ptr)
1227 {
1228 int *p;
1229
1230 if(!ptr)
1231 return;
1232
1233 p=(int*)ptr;
1234 p--;
1235
1236 if(*p != RASQAL_SIGN_KEY)
1237 RASQAL_FATAL3("memory signature %08X != %08X", *p, RASQAL_SIGN_KEY);
1238
1239 free(p);
1240 }
1241 #endif
1242