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