1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_literal.c - Rasqal literals
4 *
5 * Copyright (C) 2003-2010, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2003-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 /* for strtof() and round() prototypes */
34 #define _ISOC99_SOURCE 1
35
36 #include <stdio.h>
37 #include <string.h>
38 #ifdef HAVE_STRINGS_H
39 #include <strings.h>
40 #endif
41 #include <ctype.h>
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 /* for ptrdiff_t */
46 #ifdef HAVE_STDDEF_H
47 #include <stddef.h>
48 #endif
49 #include <stdarg.h>
50 /* for isnan() */
51 #ifdef HAVE_MATH_H
52 #include <math.h>
53 #endif
54 /* for INT_MIN and INT_MAX */
55 #ifdef HAVE_LIMITS_H
56 #include <limits.h>
57 #endif
58 #ifdef HAVE_ERRNO_H
59 #include <errno.h>
60 #endif
61 #ifdef HAVE_FLOAT_H
62 #include <float.h>
63 #endif
64
65 #include "rasqal.h"
66 #include "rasqal_internal.h"
67
68 #define DEBUG_FH stderr
69
70
71 #ifndef STANDALONE
72
73 /* prototypes */
74 static rasqal_literal_type rasqal_literal_promote_numerics(rasqal_literal* l1, rasqal_literal* l2, int flags);
75 static int rasqal_literal_set_typed_value(rasqal_literal* l, rasqal_literal_type type, const unsigned char* string, int canonicalize);
76
77
78 const unsigned char* rasqal_xsd_boolean_true = (const unsigned char*)"true";
79 const unsigned char* rasqal_xsd_boolean_false = (const unsigned char*)"false";
80
81
82 /**
83 * rasqal_new_integer_literal:
84 * @world: rasqal world object
85 * @type: Type of literal such as RASQAL_LITERAL_INTEGER or RASQAL_LITERAL_BOOLEAN
86 * @integer: int value
87 *
88 * Constructor - Create a new Rasqal integer literal.
89 *
90 * The integer decimal number is turned into a rasqal integer literal
91 * and given a datatype of xsd:integer
92 *
93 * Return value: New #rasqal_literal or NULL on failure
94 **/
95 rasqal_literal*
rasqal_new_integer_literal(rasqal_world * world,rasqal_literal_type type,int integer)96 rasqal_new_integer_literal(rasqal_world* world, rasqal_literal_type type,
97 int integer)
98 {
99 raptor_uri* dt_uri;
100 rasqal_literal* l;
101
102 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
103
104 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
105 if(l) {
106 l->valid = 1;
107 l->usage = 1;
108 l->world = world;
109 l->type = type;
110 l->value.integer = integer;
111 if(type == RASQAL_LITERAL_BOOLEAN) {
112 /* static l->string for boolean, does not need freeing */
113 l->string = integer ? rasqal_xsd_boolean_true : rasqal_xsd_boolean_false;
114 l->string_len = integer ? RASQAL_XSD_BOOLEAN_TRUE_LEN : RASQAL_XSD_BOOLEAN_FALSE_LEN;
115 } else {
116 size_t slen = 0;
117 l->string = rasqal_xsd_format_integer(integer, &slen);
118 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
119 if(!l->string) {
120 rasqal_free_literal(l);
121 return NULL;
122 }
123 }
124 dt_uri = rasqal_xsd_datatype_type_to_uri(world, l->type);
125 if(!dt_uri) {
126 rasqal_free_literal(l);
127 return NULL;
128 }
129 l->datatype = raptor_uri_copy(dt_uri);
130 l->parent_type = rasqal_xsd_datatype_parent_type(type);
131 }
132 return l;
133 }
134
135
136 /**
137 * rasqal_new_numeric_literal_from_long:
138 * @world: rasqal world object
139 * @type: Type of literal such as RASQAL_LITERAL_INTEGER or RASQAL_LITERAL_BOOLEAN
140 * @value: long value
141 *
142 * Constructor - Create a new Rasqal numeric literal from a long.
143 *
144 * The value is turned into a rasqal integer or decimal literal and
145 * given a datatype of xsd:integer
146 *
147 * Return value: New #rasqal_literal or NULL on failure
148 **/
149 rasqal_literal*
rasqal_new_numeric_literal_from_long(rasqal_world * world,rasqal_literal_type type,long value)150 rasqal_new_numeric_literal_from_long(rasqal_world* world,
151 rasqal_literal_type type,
152 long value)
153 {
154 rasqal_xsd_decimal* d;
155 unsigned char *string;
156
157 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
158
159 /* boolean values should always be in range */
160 if(type == RASQAL_LITERAL_BOOLEAN) {
161 int ivalue = value ? 1 : 0;
162 return rasqal_new_integer_literal(world, type, ivalue);
163 }
164
165 /* For other types, if in int range, make an integer literal */
166 if(value >= INT_MIN && value <= INT_MAX) {
167 return rasqal_new_integer_literal(world, type, RASQAL_GOOD_CAST(int, value));
168 }
169
170 /* Otherwise turn it into a decimal */
171 d = rasqal_new_xsd_decimal(world);
172 rasqal_xsd_decimal_set_long(d, value);
173 string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_decimal_as_counted_string(d, NULL));
174
175 return rasqal_new_decimal_literal_from_decimal(world, string, d);
176 }
177
178
179 /**
180 * rasqal_new_typed_literal:
181 * @world: rasqal world object
182 * @type: Type of literal such as RASQAL_LITERAL_INTEGER or RASQAL_LITERAL_BOOLEAN
183 * @string: lexical form - ownership not taken
184 *
185 * Constructor - Create a new Rasqal integer literal from a string
186 *
187 * The integer decimal number is turned into a rasqal integer literal
188 * and given a datatype of xsd:integer
189 *
190 * Return value: New #rasqal_literal or NULL on failure
191 **/
192 rasqal_literal*
rasqal_new_typed_literal(rasqal_world * world,rasqal_literal_type type,const unsigned char * string)193 rasqal_new_typed_literal(rasqal_world* world, rasqal_literal_type type,
194 const unsigned char* string)
195 {
196 rasqal_literal* l;
197
198 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
199
200 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
201 if(!l)
202 return NULL;
203
204 l->valid = 1;
205 l->usage = 1;
206 l->world = world;
207 l->type = type;
208
209 if(!rasqal_xsd_datatype_check(type, string, 0)) {
210 rasqal_free_literal(l);
211 return NULL;
212 }
213
214 if(rasqal_literal_set_typed_value(l, type, string, 0)) {
215 rasqal_free_literal(l);
216 l = NULL;
217 }
218
219 return l;
220 }
221
222
223 /**
224 * rasqal_new_floating_literal:
225 * @world: rasqal world object
226 * @type: type - #RASQAL_LITERAL_FLOAT or #RASQAL_LITERAL_DOUBLE
227 * @d: floating literal (double)
228 *
229 * Constructor - Create a new Rasqal float literal from a double.
230 *
231 * Return value: New #rasqal_literal or NULL on failure
232 **/
233 rasqal_literal*
rasqal_new_floating_literal(rasqal_world * world,rasqal_literal_type type,double d)234 rasqal_new_floating_literal(rasqal_world *world,
235 rasqal_literal_type type, double d)
236 {
237 raptor_uri* dt_uri;
238 rasqal_literal* l;
239
240 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
241
242 if(type != RASQAL_LITERAL_FLOAT && type != RASQAL_LITERAL_DOUBLE)
243 return NULL;
244
245 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
246 if(l) {
247 size_t slen = 0;
248 l->valid = 1;
249 l->usage = 1;
250 l->world = world;
251 l->type = type;
252 l->value.floating = d;
253 l->string = rasqal_xsd_format_double(d, &slen);
254 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
255 if(!l->string) {
256 rasqal_free_literal(l);
257 return NULL;
258 }
259 dt_uri = rasqal_xsd_datatype_type_to_uri(world, l->type);
260 if(!dt_uri) {
261 rasqal_free_literal(l);
262 return NULL;
263 }
264 l->datatype = raptor_uri_copy(dt_uri);
265 }
266 return l;
267 }
268
269
270 /**
271 * rasqal_new_double_literal:
272 * @world: rasqal world object
273 * @d: double literal
274 *
275 * Constructor - Create a new Rasqal double literal.
276 *
277 * Return value: New #rasqal_literal or NULL on failure
278 **/
279 rasqal_literal*
rasqal_new_double_literal(rasqal_world * world,double d)280 rasqal_new_double_literal(rasqal_world* world, double d)
281 {
282 return rasqal_new_floating_literal(world, RASQAL_LITERAL_DOUBLE, d);
283 }
284
285
286 #ifndef RASQAL_DISABLE_DEPRECATED
287 /**
288 * rasqal_new_float_literal:
289 * @world: rasqal world object
290 * @f: float literal
291 *
292 * Constructor - Create a new Rasqal float literal.
293 *
294 * @Deprecated: Use rasqal_new_floating_literal() with type
295 * #RASQAL_LITERAL_FLOAT and double value.
296 *
297 * Return value: New #rasqal_literal or NULL on failure
298 **/
299 rasqal_literal*
rasqal_new_float_literal(rasqal_world * world,float f)300 rasqal_new_float_literal(rasqal_world *world, float f)
301 {
302 return rasqal_new_floating_literal(world, RASQAL_LITERAL_FLOAT, (double)f);
303 }
304 #endif
305
306 /**
307 * rasqal_new_uri_literal:
308 * @world: rasqal world object
309 * @uri: #raptor_uri uri
310 *
311 * Constructor - Create a new Rasqal URI literal from a raptor URI.
312 *
313 * The uri is an input parameter and is stored in the literal, not copied.
314 * The uri is freed also on failure.
315 *
316 * Return value: New #rasqal_literal or NULL on failure
317 **/
318 rasqal_literal*
rasqal_new_uri_literal(rasqal_world * world,raptor_uri * uri)319 rasqal_new_uri_literal(rasqal_world* world, raptor_uri *uri)
320 {
321 rasqal_literal* l;
322
323 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
324
325 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
326 if(l) {
327 l->valid = 1;
328 l->usage = 1;
329 l->world = world;
330 l->type = RASQAL_LITERAL_URI;
331 l->value.uri = uri;
332 } else {
333 raptor_free_uri(uri);
334 }
335 return l;
336 }
337
338
339 /**
340 * rasqal_new_pattern_literal:
341 * @world: rasqal world object
342 * @pattern: regex pattern
343 * @flags: regex flags
344 *
345 * Constructor - Create a new Rasqal pattern literal.
346 *
347 * The pattern and flags are input parameters and are stored in the
348 * literal, not copied. They are freed also on failure.
349 * The set of flags recognised depends on the regex library and the query
350 * language.
351 *
352 * Return value: New #rasqal_literal or NULL on failure
353 **/
354 rasqal_literal*
rasqal_new_pattern_literal(rasqal_world * world,const unsigned char * pattern,const char * flags)355 rasqal_new_pattern_literal(rasqal_world* world,
356 const unsigned char *pattern,
357 const char *flags)
358 {
359 rasqal_literal* l;
360
361 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
362 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(pattern, char*, NULL);
363
364 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
365 if(l) {
366 l->valid = 1;
367 l->usage = 1;
368 l->world = world;
369 l->type = RASQAL_LITERAL_PATTERN;
370 l->string = pattern;
371 l->string_len = RASQAL_BAD_CAST(unsigned int, strlen(RASQAL_GOOD_CAST(const char*, pattern)));
372 l->flags = RASQAL_GOOD_CAST(const unsigned char*, flags);
373 } else {
374 if(flags)
375 RASQAL_FREE(char*, flags);
376 RASQAL_FREE(char*, pattern);
377 }
378 return l;
379 }
380
381
382 /**
383 * rasqal_new_decimal_literal:
384 * @world: rasqal world object
385 * @string: decimal literal
386 *
387 * Constructor - Create a new Rasqal decimal literal.
388 *
389 * Return value: New #rasqal_literal or NULL on failure
390 **/
391 rasqal_literal*
rasqal_new_decimal_literal(rasqal_world * world,const unsigned char * string)392 rasqal_new_decimal_literal(rasqal_world* world, const unsigned char *string)
393 {
394 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
395 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, char*, NULL);
396
397 return rasqal_new_decimal_literal_from_decimal(world, string, NULL);
398 }
399
400
401 /**
402 * rasqal_new_decimal_literal_from_decimal:
403 * @world: rasqal world object
404 * @string: decimal literal string
405 * @decimal: rasqal XSD Decimal
406 *
407 * Constructor - Create a new Rasqal decimal literal.
408 *
409 * Return value: New #rasqal_literal or NULL on failure
410 **/
411 rasqal_literal*
rasqal_new_decimal_literal_from_decimal(rasqal_world * world,const unsigned char * string,rasqal_xsd_decimal * decimal)412 rasqal_new_decimal_literal_from_decimal(rasqal_world* world,
413 const unsigned char *string,
414 rasqal_xsd_decimal* decimal)
415 {
416 rasqal_literal* l;
417 raptor_uri *dt_uri;
418
419 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
420 /* string and decimal NULLness are checked below */
421
422 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
423 if(!l)
424 return NULL;
425
426 l->valid = 1;
427 l->usage = 1;
428 l->world = world;
429 l->type = RASQAL_LITERAL_DECIMAL;
430 if(string) {
431 if(!rasqal_xsd_datatype_check(l->type, string, 0)) {
432 rasqal_free_literal(l);
433 return NULL;
434 }
435
436 if(rasqal_literal_set_typed_value(l, l->type, string, 0)) {
437 rasqal_free_literal(l);
438 l = NULL;
439 }
440 } else if(decimal) {
441 dt_uri = rasqal_xsd_datatype_type_to_uri(world, l->type);
442 if(!dt_uri) {
443 rasqal_free_literal(l);
444 l = NULL;
445 } else {
446 size_t slen = 0;
447 l->datatype = raptor_uri_copy(dt_uri);
448 l->value.decimal = decimal;
449 /* string is owned by l->value.decimal */
450 l->string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_decimal_as_counted_string(l->value.decimal, &slen));
451 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
452 if(!l->string) {
453 rasqal_free_literal(l);
454 l = NULL;
455 }
456 }
457 } else {
458 /* no string or decimal was given */
459 rasqal_free_literal(l);
460 l = NULL;
461 }
462
463 return l;
464 }
465
466
467 /*
468 * rasqal_new_numeric_literal:
469 * @world: rasqal world object
470 * @type: datatype
471 * @double: double
472 *
473 * INTERNAL - Make a numeric datatype from a double
474 *
475 * Return value: new literal or NULL on failure
476 **/
477 rasqal_literal*
rasqal_new_numeric_literal(rasqal_world * world,rasqal_literal_type type,double d)478 rasqal_new_numeric_literal(rasqal_world* world, rasqal_literal_type type,
479 double d)
480 {
481 char buffer[30];
482
483 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
484
485 switch(type) {
486 case RASQAL_LITERAL_DOUBLE:
487 case RASQAL_LITERAL_FLOAT:
488 return rasqal_new_floating_literal(world, type, d);
489
490 case RASQAL_LITERAL_INTEGER:
491 case RASQAL_LITERAL_INTEGER_SUBTYPE:
492 if(d >= (double)INT_MIN && d <= (double)INT_MAX)
493 return rasqal_new_integer_literal(world, type, RASQAL_GOOD_CAST(int, d));
494
495 /* otherwise FALLTHROUGH and make it a decimal */
496
497 case RASQAL_LITERAL_DECIMAL:
498 sprintf(buffer, "%g", d);
499 return rasqal_new_decimal_literal(world, RASQAL_GOOD_CAST(unsigned char*, buffer));
500
501 case RASQAL_LITERAL_XSD_STRING:
502 case RASQAL_LITERAL_BOOLEAN:
503 case RASQAL_LITERAL_DATE:
504 case RASQAL_LITERAL_DATETIME:
505 case RASQAL_LITERAL_UNKNOWN:
506 case RASQAL_LITERAL_BLANK:
507 case RASQAL_LITERAL_URI:
508 case RASQAL_LITERAL_STRING:
509 case RASQAL_LITERAL_PATTERN:
510 case RASQAL_LITERAL_QNAME:
511 case RASQAL_LITERAL_VARIABLE:
512 case RASQAL_LITERAL_UDT:
513 RASQAL_FATAL2("Unexpected numeric type %u", type);
514 }
515
516 return NULL;
517 }
518
519
520 /**
521 * rasqal_new_datetime_literal_from_datetime:
522 * @world: rasqal world object
523 * @dt: rasqal XSD Datetime
524 *
525 * Constructor - Create a new Rasqal datetime literal from an existing datetime.
526 *
527 * Takes ownership of @dt
528 *
529 * Return value: New #rasqal_literal or NULL on failure
530 **/
531 rasqal_literal*
rasqal_new_datetime_literal_from_datetime(rasqal_world * world,rasqal_xsd_datetime * dt)532 rasqal_new_datetime_literal_from_datetime(rasqal_world* world,
533 rasqal_xsd_datetime* dt)
534 {
535 rasqal_literal* l;
536 raptor_uri *dt_uri;
537 size_t slen = 0;
538
539 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
540 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(dt, rasqal_xsd_datetime, NULL);
541
542 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
543 if(!l)
544 goto failed;
545
546 l->valid = 1;
547 l->usage = 1;
548 l->world = world;
549 l->type = RASQAL_LITERAL_DATETIME;
550
551 dt_uri = rasqal_xsd_datatype_type_to_uri(world, l->type);
552 if(!dt_uri)
553 goto failed;
554
555 l->datatype = raptor_uri_copy(dt_uri);
556
557 l->value.datetime = dt;
558
559 l->string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_datetime_to_counted_string(l->value.datetime, &slen));
560 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
561 if(!l->string)
562 goto failed;
563
564 return l;
565
566 failed:
567 if(l)
568 rasqal_free_literal(l);
569 if(dt)
570 rasqal_free_xsd_datetime(dt);
571
572 return NULL;
573 }
574
575
576
577 /*
578 * rasqal_literal_set_typed_value:
579 * @l: literal
580 * @type: type
581 * @string: string or NULL to use existing literal string
582 * @canonicalize: non-0 to canonicalize the existing string
583 *
584 * INTERNAL - Set a literal typed value
585 *
586 * Return value: non-0 on failure
587 **/
588 static int
rasqal_literal_set_typed_value(rasqal_literal * l,rasqal_literal_type type,const unsigned char * string,int canonicalize)589 rasqal_literal_set_typed_value(rasqal_literal* l, rasqal_literal_type type,
590 const unsigned char* string,
591 int canonicalize)
592 {
593 char *eptr;
594 raptor_uri* dt_uri;
595 int i;
596 double d;
597 rasqal_literal_type original_type = l->type;
598
599 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 1);
600
601 retype:
602 l->valid = rasqal_xsd_datatype_check(type, string ? string : l->string,
603 0 /* no flags set */);
604 if(!l->valid) {
605 RASQAL_DEBUG3("Invalid type %s string '%s' - setting to type UDT\n",
606 rasqal_xsd_datatype_label(type), string ? string : l->string);
607 type = RASQAL_LITERAL_UDT;
608 }
609
610 if(l->language) {
611 RASQAL_FREE(char*, l->language);
612 l->language = NULL;
613 }
614 l->type = type;
615
616 if(string && l->type != RASQAL_LITERAL_DECIMAL) {
617 if(l->string)
618 RASQAL_FREE(char*, l->string);
619
620 l->string_len = RASQAL_BAD_CAST(unsigned int, strlen(RASQAL_GOOD_CAST(const char*, string)));
621 l->string = RASQAL_MALLOC(unsigned char*, l->string_len + 1);
622 if(!l->string)
623 return 1;
624 memcpy((void*)l->string, string, l->string_len + 1);
625 }
626
627 if(l->type <= RASQAL_LITERAL_LAST_XSD) {
628 dt_uri = rasqal_xsd_datatype_type_to_uri(l->world, l->type);
629 if(!dt_uri)
630 return 1;
631
632 if(l->datatype)
633 raptor_free_uri(l->datatype);
634 l->datatype = raptor_uri_copy(dt_uri);
635
636 l->parent_type = rasqal_xsd_datatype_parent_type(type);
637 }
638
639 switch(type) {
640 case RASQAL_LITERAL_INTEGER:
641 case RASQAL_LITERAL_INTEGER_SUBTYPE:
642 if(1) {
643 long long_i;
644
645 eptr = NULL;
646 errno = 0;
647 long_i = strtol(RASQAL_GOOD_CAST(const char*, l->string), &eptr, 10);
648 if(*eptr)
649 return 1;
650
651 if(errno == ERANGE) {
652 /* under or overflow of strtol() so fallthrough to DECIMAL */
653
654 } else if(long_i >= INT_MIN && long_i <= INT_MAX) {
655 l->value.integer = RASQAL_GOOD_CAST(int, long_i);
656 break;
657 }
658 }
659
660 /* Will not fit in an int so turn it into a decimal */
661 type = RASQAL_LITERAL_DECIMAL;
662 goto retype;
663
664 case RASQAL_LITERAL_DOUBLE:
665 case RASQAL_LITERAL_FLOAT:
666 if(1) {
667 size_t slen = 0;
668 d = 0.0;
669 (void)sscanf(RASQAL_GOOD_CAST(char*, l->string), "%lf", &d);
670 l->value.floating = d;
671 if(canonicalize) {
672 RASQAL_FREE(char*, l->string);
673 l->string = rasqal_xsd_format_double(d, &slen);
674 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
675 }
676 }
677 break;
678
679 case RASQAL_LITERAL_DECIMAL:
680 if(1) {
681 size_t slen = 0;
682 rasqal_xsd_decimal* new_d;
683
684 new_d = rasqal_new_xsd_decimal(l->world);
685 if(!new_d)
686 return 1;
687
688 if(!string)
689 /* use existing literal decimal object (SHARED) string */
690 string = l->string;
691
692 if(rasqal_xsd_decimal_set_string(new_d,
693 RASQAL_GOOD_CAST(const char*, string))) {
694 rasqal_free_xsd_decimal(new_d);
695 return 1;
696 }
697 if(l->value.decimal) {
698 rasqal_free_xsd_decimal(l->value.decimal);
699 }
700 l->value.decimal = new_d;
701
702 /* old l->string is now invalid and MAY need to be freed */
703 if(l->string && original_type != RASQAL_LITERAL_DECIMAL)
704 RASQAL_FREE(char*, l->string);
705
706 /* new l->string is owned by l->value.decimal and will be
707 * freed on literal destruction
708 */
709 l->string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_decimal_as_counted_string(l->value.decimal, &slen));
710 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
711 if(!l->string)
712 return 1;
713 }
714 break;
715
716 case RASQAL_LITERAL_XSD_STRING:
717 case RASQAL_LITERAL_UDT:
718 /* No change - kept as same type - xsd:string or user defined */
719 break;
720
721 case RASQAL_LITERAL_BOOLEAN:
722 i = rasqal_xsd_boolean_value_from_string(l->string);
723 /* Free passed in string if it is not our static objects */
724 if(l->string != rasqal_xsd_boolean_true &&
725 l->string != rasqal_xsd_boolean_false)
726 RASQAL_FREE(char*, l->string);
727 /* and replace with a static string */
728 l->string = i ? rasqal_xsd_boolean_true : rasqal_xsd_boolean_false;
729 l->string_len = i ? RASQAL_XSD_BOOLEAN_TRUE_LEN : RASQAL_XSD_BOOLEAN_FALSE_LEN;
730
731 l->value.integer = i;
732 break;
733
734 case RASQAL_LITERAL_STRING:
735 /* No change - kept as a string */
736 break;
737
738 case RASQAL_LITERAL_DATE:
739 if(1) {
740 size_t slen = 0;
741
742 if(l->value.date)
743 rasqal_free_xsd_date(l->value.date);
744
745 l->value.date = rasqal_new_xsd_date(l->world, RASQAL_GOOD_CAST(const char*, l->string));
746 if(!l->value.date) {
747 RASQAL_FREE(char*, l->string);
748 return 1;
749 }
750 RASQAL_FREE(char*, l->string);
751 l->string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_date_to_counted_string(l->value.date, &slen));
752 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
753 if(!l->string)
754 return 1;
755 }
756 break;
757
758 case RASQAL_LITERAL_DATETIME:
759 if(1) {
760 size_t slen = 0;
761
762 if(l->value.datetime)
763 rasqal_free_xsd_datetime(l->value.datetime);
764
765 l->value.datetime = rasqal_new_xsd_datetime(l->world,
766 RASQAL_GOOD_CAST(const char*, l->string));
767 if(!l->value.datetime) {
768 RASQAL_FREE(char*, l->string);
769 return 1;
770 }
771 RASQAL_FREE(char*, l->string);
772 l->string = RASQAL_GOOD_CAST(unsigned char*, rasqal_xsd_datetime_to_counted_string(l->value.datetime, &slen));
773 l->string_len = RASQAL_BAD_CAST(unsigned int, slen);
774 if(!l->string)
775 return 1;
776 }
777 break;
778
779 case RASQAL_LITERAL_UNKNOWN:
780 case RASQAL_LITERAL_BLANK:
781 case RASQAL_LITERAL_URI:
782 case RASQAL_LITERAL_PATTERN:
783 case RASQAL_LITERAL_QNAME:
784 case RASQAL_LITERAL_VARIABLE:
785 RASQAL_FATAL2("Unexpected native type %u", type);
786 break;
787
788 default:
789 RASQAL_FATAL2("Unknown native type %u", type);
790 }
791
792 return 0;
793 }
794
795
796
797 /*
798 * rasqal_literal_string_to_native:
799 * @l: #rasqal_literal to operate on inline
800 * @flags: flags for literal checking. 1 to canonicalize string
801 *
802 * INTERNAL - Upgrade a datatyped literal string to an internal typed literal
803 *
804 * At present this promotes datatyped literals
805 * xsd:integer to RASQAL_LITERAL_INTEGER
806 * xsd:double to RASQAL_LITERAL_DOUBLE
807 * xsd:float to RASQAL_LITERAL_FLOAT
808 * xsd:boolean to RASQAL_LITERAL_BOOLEAN
809 * xsd:decimal to RASQAL_LITERAL_DECIMAL
810 * xsd:dateTime to RASQAL_LITERAL_DATETIME
811 * xsd:date to RASQAL_LITERAL_DATE
812 *
813 * Return value: non-0 on failure
814 **/
815 int
rasqal_literal_string_to_native(rasqal_literal * l,int flags)816 rasqal_literal_string_to_native(rasqal_literal *l, int flags)
817 {
818 rasqal_literal_type native_type = RASQAL_LITERAL_UNKNOWN;
819 int rc = 0;
820 int canonicalize = (flags & 1 );
821
822 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 1);
823
824 /* RDF literal with no datatype (plain literal) */
825 if(!l->datatype)
826 return 0;
827
828 native_type = rasqal_xsd_datatype_uri_to_type(l->world, l->datatype);
829 /* plain literal - nothing to do */
830 if(native_type == RASQAL_LITERAL_STRING)
831 return 0;
832
833 /* xsd:string - mark and return */
834 if(native_type == RASQAL_LITERAL_XSD_STRING) {
835 l->type = native_type;
836 return 0;
837 }
838
839 /* If a user defined type - update the literal */
840 if(native_type == RASQAL_LITERAL_UNKNOWN) {
841 l->type = RASQAL_LITERAL_UDT;
842 return 0;
843 }
844
845 rc = rasqal_literal_set_typed_value(l, native_type,
846 NULL /* existing string */,
847 canonicalize);
848
849 if(!rasqal_xsd_datatype_check(native_type, l->string, 1))
850 return 0;
851
852 return rc;
853 }
854
855
856 /*
857 * rasqal_new_string_literal_common:
858 * @world: rasqal world object
859 * @string: UTF-8 string lexical form
860 * @language: RDF language (xml:lang) (or NULL)
861 * @datatype: datatype URI (or NULL for plain literal)
862 * @datatype_qname: datatype qname string (or NULL for plain literal)
863 * @flags: bitflags - 1 to do native type promotion; 2 to canonicalize string
864 *
865 * INTERNAL Constructor - Create a new Rasqal string literal.
866 *
867 * All parameters are input parameters and if present are stored in
868 * the literal, not copied. They are freed also on failure.
869 *
870 * The datatype and datatype_qname parameters are alternatives; the
871 * qname is a datatype that cannot be resolved till later since the
872 * prefixes have not yet been declared or checked.
873 *
874 * If the string literal is datatyped and of certain types recognised
875 * it may be converted to a different literal type by
876 * rasqal_literal_string_to_native() only if @flags has bit 1 set.
877 * If bit 2 is set AS WELL, literals will have their string converted
878 * to the canonical format.
879 *
880 * Return value: New #rasqal_literal or NULL on failure
881 **/
882 static rasqal_literal*
rasqal_new_string_literal_common(rasqal_world * world,const unsigned char * string,const char * language,raptor_uri * datatype,const unsigned char * datatype_qname,int flags)883 rasqal_new_string_literal_common(rasqal_world* world,
884 const unsigned char *string,
885 const char *language,
886 raptor_uri *datatype,
887 const unsigned char *datatype_qname,
888 int flags)
889 {
890 rasqal_literal* l;
891 int native_type_promotion = (flags & 1);
892 int canonicalize = (flags & 2) >> 1;
893
894 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
895 if(l) {
896 rasqal_literal_type datatype_type = RASQAL_LITERAL_STRING;
897
898 l->valid = 1;
899 l->usage = 1;
900 l->world = world;
901
902 if(datatype && language) {
903 /* RDF typed literal but this is not allowed so delete language */
904 RASQAL_FREE(char*, language);
905 language = NULL;
906 }
907
908 l->type = RASQAL_LITERAL_STRING;
909 l->string = string;
910 l->string_len = RASQAL_BAD_CAST(unsigned int, strlen(RASQAL_GOOD_CAST(const char*, string)));
911 if(language) {
912 /* Normalize language to lowercase on construction */
913 size_t lang_len = strlen(language);
914 unsigned int i;
915
916 l->language = RASQAL_MALLOC(char*, lang_len + 1);
917 for(i = 0; i < lang_len; i++) {
918 char c = language[i];
919 if(isupper(RASQAL_GOOD_CAST(int, c)))
920 c = RASQAL_GOOD_CAST(char, tolower(RASQAL_GOOD_CAST(int, c)));
921 l->language[i] = c;
922 }
923 l->language[i] = '\0';
924 RASQAL_FREE(char*, language);
925 }
926 l->datatype = datatype;
927 l->flags = datatype_qname;
928
929 if(datatype)
930 datatype_type = rasqal_xsd_datatype_uri_to_type(world, datatype);
931 l->parent_type = rasqal_xsd_datatype_parent_type(datatype_type);
932
933 if(native_type_promotion &&
934 rasqal_literal_string_to_native(l, canonicalize)) {
935 rasqal_free_literal(l);
936 l = NULL;
937 }
938 } else {
939 if(language)
940 RASQAL_FREE(char*, language);
941 if(datatype)
942 raptor_free_uri(datatype);
943 if(datatype_qname)
944 RASQAL_FREE(char*, datatype_qname);
945 RASQAL_FREE(char*, string);
946 }
947
948 return l;
949 }
950
951
952 /**
953 * rasqal_new_string_literal:
954 * @world: rasqal world object
955 * @string: UTF-8 string lexical form
956 * @language: RDF language (xml:lang) (or NULL)
957 * @datatype: datatype URI (or NULL for plain literal)
958 * @datatype_qname: datatype qname string (or NULL for plain literal)
959 *
960 * Constructor - Create a new Rasqal string literal.
961 *
962 * All parameters are input parameters and if present are stored in
963 * the literal, not copied. They are freed also on failure.
964 *
965 * The datatype and datatype_qname parameters are alternatives; the
966 * qname is a datatype that cannot be resolved till later since the
967 * prefixes have not yet been declared or checked.
968 *
969 * If the string literal is datatyped and of certain types recognised
970 * it may be converted to a different literal type.
971 *
972 * Return value: New #rasqal_literal or NULL on failure
973 **/
974 rasqal_literal*
rasqal_new_string_literal(rasqal_world * world,const unsigned char * string,const char * language,raptor_uri * datatype,const unsigned char * datatype_qname)975 rasqal_new_string_literal(rasqal_world* world,
976 const unsigned char *string,
977 const char *language,
978 raptor_uri *datatype,
979 const unsigned char *datatype_qname)
980 {
981 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
982 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, char*, NULL);
983
984 return rasqal_new_string_literal_common(world, string, language, datatype,
985 datatype_qname, 1);
986 }
987
988
989 /*
990 * rasqal_new_string_literal_node:
991 * @world: rasqal world object
992 * @string: UTF-8 string lexical form
993 * @language: RDF language (xml:lang) (or NULL)
994 * @datatype: datatype URI (or NULL for plain literal)
995 *
996 * INTERNAL Constructor - Create a new Rasqal literal with promotion and canonicalization
997 *
998 * All parameters are input parameters and if present are stored in
999 * the literal, not copied. They are freed also on failure.
1000 *
1001 * Return value: New #rasqal_literal or NULL on failure
1002 **/
1003 rasqal_literal*
rasqal_new_string_literal_node(rasqal_world * world,const unsigned char * string,const char * language,raptor_uri * datatype)1004 rasqal_new_string_literal_node(rasqal_world* world, const unsigned char *string,
1005 const char *language, raptor_uri *datatype)
1006 {
1007 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1008 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, char*, NULL);
1009
1010 return rasqal_new_string_literal_common(world, string, language, datatype,
1011 NULL, 1 | 2);
1012 }
1013
1014
1015 /**
1016 * rasqal_new_simple_literal:
1017 * @world: rasqal world object
1018 * @type: RASQAL_LITERAL_BLANK or RASQAL_LITERAL_BLANK_QNAME
1019 * @string: the UTF-8 string value to store
1020 *
1021 * Constructor - Create a new Rasqal simple literal.
1022 *
1023 * The string is an input parameter and is stored in the
1024 * literal, not copied. It is freed also on failure.
1025 *
1026 * Return value: New #rasqal_literal or NULL on failure
1027 **/
1028 rasqal_literal*
rasqal_new_simple_literal(rasqal_world * world,rasqal_literal_type type,const unsigned char * string)1029 rasqal_new_simple_literal(rasqal_world* world,
1030 rasqal_literal_type type,
1031 const unsigned char *string)
1032 {
1033 rasqal_literal* l;
1034
1035 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1036 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, char*, NULL);
1037
1038 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
1039 if(l) {
1040 l->valid = 1;
1041 l->usage = 1;
1042 l->world = world;
1043 l->type = type;
1044 l->string = string;
1045 l->string_len = RASQAL_BAD_CAST(unsigned int, strlen(RASQAL_GOOD_CAST(const char*, string)));
1046 } else {
1047 RASQAL_FREE(char*, string);
1048 }
1049 return l;
1050 }
1051
1052
1053 /**
1054 * rasqal_new_boolean_literal:
1055 * @world: rasqal world object
1056 * @value: non-0 for true, 0 for false
1057 *
1058 * Constructor - Create a new Rasqal boolean literal.
1059 *
1060 * Return value: New #rasqal_literal or NULL on failure
1061 **/
1062 rasqal_literal*
rasqal_new_boolean_literal(rasqal_world * world,int value)1063 rasqal_new_boolean_literal(rasqal_world* world, int value)
1064 {
1065 raptor_uri* dt_uri;
1066 rasqal_literal* l;
1067
1068 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1069
1070 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
1071 if(l) {
1072 l->valid = 1;
1073 l->usage = 1;
1074 l->world = world;
1075 l->type = RASQAL_LITERAL_BOOLEAN;
1076 l->value.integer = value;
1077 l->string = value ? rasqal_xsd_boolean_true : rasqal_xsd_boolean_false;
1078 l->string_len = value ? RASQAL_XSD_BOOLEAN_TRUE_LEN : RASQAL_XSD_BOOLEAN_FALSE_LEN;
1079 dt_uri = rasqal_xsd_datatype_type_to_uri(world, l->type);
1080 if(!dt_uri) {
1081 rasqal_free_literal(l);
1082 return NULL;
1083 }
1084 l->datatype = raptor_uri_copy(dt_uri);
1085 }
1086 return l;
1087 }
1088
1089
1090 /**
1091 * rasqal_new_variable_literal:
1092 * @world: rasqal_world object
1093 * @variable: #rasqal_variable to use
1094 *
1095 * Constructor - Create a new Rasqal variable literal.
1096 *
1097 * variable is an input parameter and stored in the literal, not copied.
1098 *
1099 * Return value: New #rasqal_literal or NULL on failure
1100 **/
1101 rasqal_literal*
rasqal_new_variable_literal(rasqal_world * world,rasqal_variable * variable)1102 rasqal_new_variable_literal(rasqal_world* world, rasqal_variable *variable)
1103 {
1104 rasqal_literal* l;
1105
1106 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1107 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(variable, rasqal_variable, NULL);
1108
1109 l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*l));
1110 if(l) {
1111 l->valid = 1;
1112 l->usage = 1;
1113 l->world = world;
1114 l->type = RASQAL_LITERAL_VARIABLE;
1115 l->value.variable = variable;
1116 } else
1117 rasqal_free_variable(variable);
1118
1119 return l;
1120 }
1121
1122
1123 /**
1124 * rasqal_new_literal_from_literal:
1125 * @l: #rasqal_literal object to copy or NULL
1126 *
1127 * Copy Constructor - create a new rasqal_literal object from an existing rasqal_literal object.
1128 *
1129 * Return value: a new #rasqal_literal object or NULL if @l was NULL.
1130 **/
1131 rasqal_literal*
rasqal_new_literal_from_literal(rasqal_literal * l)1132 rasqal_new_literal_from_literal(rasqal_literal* l)
1133 {
1134 if(!l)
1135 return NULL;
1136
1137 l->usage++;
1138 return l;
1139 }
1140
1141
1142 /**
1143 * rasqal_free_literal:
1144 * @l: #rasqal_literal object
1145 *
1146 * Destructor - destroy an rasqal_literal object.
1147 *
1148 **/
1149 void
rasqal_free_literal(rasqal_literal * l)1150 rasqal_free_literal(rasqal_literal* l)
1151 {
1152 if(!l)
1153 return;
1154
1155 if(--l->usage)
1156 return;
1157
1158 switch(l->type) {
1159 case RASQAL_LITERAL_URI:
1160 if(l->value.uri)
1161 raptor_free_uri(l->value.uri);
1162 break;
1163 case RASQAL_LITERAL_STRING:
1164 case RASQAL_LITERAL_BLANK:
1165 case RASQAL_LITERAL_PATTERN:
1166 case RASQAL_LITERAL_QNAME:
1167 case RASQAL_LITERAL_XSD_STRING:
1168 case RASQAL_LITERAL_DOUBLE:
1169 case RASQAL_LITERAL_INTEGER:
1170 case RASQAL_LITERAL_FLOAT:
1171 case RASQAL_LITERAL_UDT:
1172 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1173 if(l->string)
1174 RASQAL_FREE(char*, l->string);
1175 if(l->language)
1176 RASQAL_FREE(char*, l->language);
1177 if(l->datatype)
1178 raptor_free_uri(l->datatype);
1179 if(l->type == RASQAL_LITERAL_STRING ||
1180 l->type == RASQAL_LITERAL_PATTERN) {
1181 if(l->flags)
1182 RASQAL_FREE(char*, l->flags);
1183 }
1184 break;
1185
1186 case RASQAL_LITERAL_DATE:
1187 if(l->string)
1188 RASQAL_FREE(char*, l->string);
1189 if(l->datatype)
1190 raptor_free_uri(l->datatype);
1191 if(l->value.date)
1192 rasqal_free_xsd_date(l->value.date);
1193 break;
1194
1195 case RASQAL_LITERAL_DATETIME:
1196 if(l->string)
1197 RASQAL_FREE(char*, l->string);
1198 if(l->datatype)
1199 raptor_free_uri(l->datatype);
1200 if(l->value.datetime)
1201 rasqal_free_xsd_datetime(l->value.datetime);
1202 break;
1203
1204 case RASQAL_LITERAL_DECIMAL:
1205 /* l->string is owned by l->value.decimal - do not free it */
1206 if(l->datatype)
1207 raptor_free_uri(l->datatype);
1208 if(l->value.decimal)
1209 rasqal_free_xsd_decimal(l->value.decimal);
1210 break;
1211
1212 case RASQAL_LITERAL_BOOLEAN:
1213 /* static l->string for boolean, does not need freeing */
1214 if(l->datatype)
1215 raptor_free_uri(l->datatype);
1216 break;
1217
1218 case RASQAL_LITERAL_VARIABLE:
1219 if(l->value.variable)
1220 rasqal_free_variable(l->value.variable);
1221 break;
1222
1223 case RASQAL_LITERAL_UNKNOWN:
1224 default:
1225 RASQAL_FATAL2("Unknown literal type %u", l->type);
1226 }
1227 RASQAL_FREE(rasqal_literal, l);
1228 }
1229
1230
1231 /*
1232 * The order here must match that of rasqal_literal_type
1233 * in rasqal.h and is significant as rasqal_literal_compare
1234 * uses it for type comparisons with the RASQAL_COMPARE_XQUERY
1235 * flag.
1236 */
1237 static const char* const rasqal_literal_type_labels[RASQAL_LITERAL_LAST + 1]={
1238 "UNKNOWN",
1239 "blank",
1240 "uri",
1241 "string",
1242 "xsdstring",
1243 "boolean",
1244 "integer",
1245 "float",
1246 "double",
1247 "decimal",
1248 "datetime",
1249 "udt",
1250 "pattern",
1251 "qname",
1252 "variable",
1253 "<integer subtype>",
1254 "date"
1255 };
1256
1257
1258 /**
1259 * rasqal_literal_type_label:
1260 * @type: the #rasqal_literal_type object
1261 *
1262 * Get a label for the rasqal literal type
1263 *
1264 * Return value: the label (shared string) or NULL if type is out of
1265 * range or unknown
1266 **/
1267 const char*
rasqal_literal_type_label(rasqal_literal_type type)1268 rasqal_literal_type_label(rasqal_literal_type type)
1269 {
1270 if(type > RASQAL_LITERAL_LAST)
1271 type = RASQAL_LITERAL_UNKNOWN;
1272
1273 return rasqal_literal_type_labels[RASQAL_GOOD_CAST(int, type)];
1274 }
1275
1276
1277 /**
1278 * rasqal_literal_write_type:
1279 * @l: the #rasqal_literal object
1280 * @iostr: the #raptor_iostream handle to print to
1281 *
1282 * Write a string form for a rasqal literal type to an iostream
1283 *
1284 **/
1285 void
rasqal_literal_write_type(rasqal_literal * l,raptor_iostream * iostr)1286 rasqal_literal_write_type(rasqal_literal* l, raptor_iostream* iostr)
1287 {
1288 if(!l) {
1289 raptor_iostream_counted_string_write("null", 4, iostr);
1290 return;
1291 }
1292
1293 raptor_iostream_string_write(rasqal_literal_type_label(l->type), iostr);
1294 }
1295
1296
1297 /**
1298 * rasqal_literal_print_type:
1299 * @l: the #rasqal_literal object
1300 * @fh: the FILE* handle to print to
1301 *
1302 * Print a string form for a rasqal literal type.
1303 *
1304 **/
1305 void
rasqal_literal_print_type(rasqal_literal * l,FILE * fh)1306 rasqal_literal_print_type(rasqal_literal* l, FILE* fh)
1307 {
1308 raptor_iostream *iostr;
1309
1310 if(!l) {
1311 fputs("null", fh);
1312 return;
1313 }
1314
1315 iostr = raptor_new_iostream_to_file_handle(l->world->raptor_world_ptr, fh);
1316 if(!iostr)
1317 return;
1318
1319 rasqal_literal_write_type(l, iostr);
1320
1321 raptor_free_iostream(iostr);
1322 }
1323
1324
1325 /**
1326 * rasqal_literal_write:
1327 * @l: the #rasqal_literal object
1328 * @iostr: the #raptor_iostream handle to write to
1329 *
1330 * Write a Rasqal literal to an iostream in a debug format.
1331 *
1332 * The print debug format may change in any release.
1333 **/
1334 void
rasqal_literal_write(rasqal_literal * l,raptor_iostream * iostr)1335 rasqal_literal_write(rasqal_literal* l, raptor_iostream* iostr)
1336 {
1337 const unsigned char*str;
1338 size_t len;
1339
1340 if(!l) {
1341 raptor_iostream_counted_string_write("null", 4, iostr);
1342 return;
1343 }
1344
1345 if(!l->valid)
1346 raptor_iostream_counted_string_write("INV:", 4, iostr);
1347
1348 if(l->type != RASQAL_LITERAL_VARIABLE)
1349 rasqal_literal_write_type(l, iostr);
1350
1351 switch(l->type) {
1352 case RASQAL_LITERAL_URI:
1353 raptor_iostream_write_byte('<', iostr);
1354 str = raptor_uri_as_counted_string(l->value.uri, &len);
1355 raptor_string_ntriples_write(str, len, '>', iostr);
1356 raptor_iostream_write_byte('>', iostr);
1357 break;
1358 case RASQAL_LITERAL_BLANK:
1359 raptor_iostream_write_byte(' ', iostr);
1360 raptor_iostream_counted_string_write(l->string, l->string_len, iostr);
1361 break;
1362 case RASQAL_LITERAL_PATTERN:
1363 raptor_iostream_write_byte('/', iostr);
1364 raptor_iostream_counted_string_write(l->string, l->string_len, iostr);
1365 raptor_iostream_write_byte('/', iostr);
1366 if(l->flags)
1367 raptor_iostream_string_write(l->flags, iostr);
1368 break;
1369 case RASQAL_LITERAL_STRING:
1370 case RASQAL_LITERAL_UDT:
1371 raptor_iostream_counted_string_write("(\"", 2, iostr);
1372 raptor_string_ntriples_write(l->string, l->string_len, '"', iostr);
1373 raptor_iostream_write_byte('"', iostr);
1374 if(l->language) {
1375 raptor_iostream_write_byte('@', iostr);
1376 raptor_iostream_string_write(l->language, iostr);
1377 }
1378 if(l->datatype) {
1379 raptor_iostream_counted_string_write("^^<", 3, iostr);
1380 str = raptor_uri_as_counted_string(l->datatype, &len);
1381 raptor_string_ntriples_write(str, len, '>', iostr);
1382 raptor_iostream_write_byte('>', iostr);
1383 }
1384 raptor_iostream_write_byte(')', iostr);
1385 break;
1386 case RASQAL_LITERAL_VARIABLE:
1387 rasqal_variable_write(l->value.variable, iostr);
1388 break;
1389
1390 case RASQAL_LITERAL_QNAME:
1391 case RASQAL_LITERAL_INTEGER:
1392 case RASQAL_LITERAL_XSD_STRING:
1393 case RASQAL_LITERAL_BOOLEAN:
1394 case RASQAL_LITERAL_DOUBLE:
1395 case RASQAL_LITERAL_FLOAT:
1396 case RASQAL_LITERAL_DECIMAL:
1397 case RASQAL_LITERAL_DATE:
1398 case RASQAL_LITERAL_DATETIME:
1399 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1400 raptor_iostream_write_byte('(', iostr);
1401 raptor_iostream_counted_string_write(l->string, l->string_len, iostr);
1402 raptor_iostream_write_byte(')', iostr);
1403 break;
1404
1405 case RASQAL_LITERAL_UNKNOWN:
1406 default:
1407 RASQAL_FATAL2("Unknown literal type %u", l->type);
1408 }
1409 }
1410
1411
1412
1413 /**
1414 * rasqal_literal_print:
1415 * @l: the #rasqal_literal object
1416 * @fh: the FILE handle to print to
1417 *
1418 * Print a Rasqal literal in a debug format.
1419 *
1420 * The print debug format may change in any release.
1421 *
1422 * Return value: non-0 on failure
1423 **/
1424 int
rasqal_literal_print(rasqal_literal * l,FILE * fh)1425 rasqal_literal_print(rasqal_literal* l, FILE* fh)
1426 {
1427 raptor_iostream *iostr;
1428
1429 if(!l) {
1430 fputs("NULL", fh);
1431 return 0;
1432 }
1433
1434 iostr = raptor_new_iostream_to_file_handle(l->world->raptor_world_ptr, fh);
1435 rasqal_literal_write(l, iostr);
1436 raptor_free_iostream(iostr);
1437
1438 return 0;
1439 }
1440
1441
1442
1443 /*
1444 * rasqal_literal_as_boolean:
1445 * @l: #rasqal_literal object
1446 * @error_p: pointer to error flag
1447 *
1448 * INTERNAL - Return a literal as a boolean value
1449 *
1450 * SPARQL Effective Boolean Value (EBV) rules:
1451 * - If the argument is a typed literal with a datatype of xsd:boolean, the
1452 * EBV is the value of that argument.
1453 * - If the argument is a plain literal or a typed literal with a datatype of
1454 * xsd:string, the EBV is false if the operand value has zero length;
1455 * otherwise the EBV is true.
1456 * - If the argument is a numeric type or a typed literal with a datatype
1457 * derived from a numeric type, the EBV is false if the operand value is NaN
1458 * or is numerically equal to zero; otherwise the EBV is true.
1459 * - All other arguments, including unbound arguments, produce a type error.
1460 *
1461 * Return value: non-0 if true
1462 **/
1463 int
rasqal_literal_as_boolean(rasqal_literal * l,int * error_p)1464 rasqal_literal_as_boolean(rasqal_literal* l, int *error_p)
1465 {
1466 if(!l) {
1467 /* type error */
1468 if(error_p)
1469 *error_p = 1;
1470 return 0;
1471 }
1472
1473 switch(l->type) {
1474 case RASQAL_LITERAL_STRING:
1475 if(l->datatype) {
1476 if(raptor_uri_equals(l->datatype,
1477 rasqal_xsd_datatype_type_to_uri(l->world, RASQAL_LITERAL_STRING))) {
1478 /* typed literal with xsd:string datatype -> true if non-empty */
1479 return l->string && *l->string;
1480 }
1481 /* typed literal with other datatype -> type error */
1482 if(error_p)
1483 *error_p = 1;
1484 return 0;
1485 }
1486 /* plain literal -> true if non-empty */
1487 return l->string && *l->string;
1488
1489 case RASQAL_LITERAL_XSD_STRING:
1490 /* xsd:string -> true if non-empty */
1491 return l->string && *l->string;
1492
1493 case RASQAL_LITERAL_URI:
1494 case RASQAL_LITERAL_BLANK:
1495 case RASQAL_LITERAL_PATTERN:
1496 case RASQAL_LITERAL_QNAME:
1497 case RASQAL_LITERAL_DECIMAL:
1498 case RASQAL_LITERAL_DATE:
1499 case RASQAL_LITERAL_DATETIME:
1500 case RASQAL_LITERAL_UDT:
1501 if(error_p)
1502 *error_p = 1;
1503 return 0;
1504
1505 case RASQAL_LITERAL_INTEGER:
1506 case RASQAL_LITERAL_BOOLEAN:
1507 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1508 return l->value.integer != 0;
1509
1510 case RASQAL_LITERAL_DOUBLE:
1511 case RASQAL_LITERAL_FLOAT:
1512 if(isnan(l->value.floating))
1513 return 0;
1514
1515 return fabs(l->value.floating) > RASQAL_DOUBLE_EPSILON;
1516
1517 case RASQAL_LITERAL_VARIABLE:
1518 return rasqal_literal_as_boolean(l->value.variable->value, error_p);
1519
1520 case RASQAL_LITERAL_UNKNOWN:
1521 default:
1522 RASQAL_FATAL2("Unknown literal type %u", l->type);
1523 return 0; /* keep some compilers happy */
1524 }
1525 }
1526
1527
1528 /*
1529 * rasqal_literal_as_integer
1530 * @l: #rasqal_literal object
1531 * @error_p: pointer to error flag
1532 *
1533 * INTERNAL - Return a literal as an integer value
1534 *
1535 * Integers, booleans, double and float literals natural are turned into
1536 * integers. If string values are the lexical form of an integer, that is
1537 * returned. Otherwise the error flag is set.
1538 *
1539 * Return value: integer value
1540 **/
1541 int
rasqal_literal_as_integer(rasqal_literal * l,int * error_p)1542 rasqal_literal_as_integer(rasqal_literal* l, int *error_p)
1543 {
1544 if(!l) {
1545 /* type error */
1546 if(error_p)
1547 *error_p = 1;
1548 return 0;
1549 }
1550
1551 switch(l->type) {
1552 case RASQAL_LITERAL_INTEGER:
1553 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1554 return l->value.integer;
1555
1556 case RASQAL_LITERAL_BOOLEAN:
1557 return l->value.integer != 0;
1558
1559 case RASQAL_LITERAL_DOUBLE:
1560 case RASQAL_LITERAL_FLOAT:
1561 return RASQAL_FLOATING_AS_INT(l->value.floating);
1562
1563 case RASQAL_LITERAL_DECIMAL:
1564 {
1565 int error = 0;
1566
1567 long lvalue = rasqal_xsd_decimal_get_long(l->value.decimal, &error);
1568 if(lvalue < INT_MIN || lvalue > INT_MAX)
1569 error = 1;
1570
1571 if(error) {
1572 if(error_p)
1573 *error_p = 1;
1574 return 0;
1575 }
1576
1577 return RASQAL_GOOD_CAST(int, lvalue);
1578 }
1579
1580 case RASQAL_LITERAL_STRING:
1581 case RASQAL_LITERAL_XSD_STRING:
1582 {
1583 char *eptr;
1584 double d;
1585 long long_i;
1586
1587 eptr = NULL;
1588 errno = 0;
1589 long_i = strtol(RASQAL_GOOD_CAST(const char*, l->string), &eptr, 10);
1590 /* If formatted correctly and no under or overflow */
1591 if(RASQAL_GOOD_CAST(unsigned char*, eptr) != l->string && *eptr=='\0' &&
1592 errno != ERANGE)
1593 /* FIXME may lose precision or be out of range from long to int */
1594 return RASQAL_BAD_CAST(int, long_i);
1595
1596 eptr = NULL;
1597 d = strtod(RASQAL_GOOD_CAST(const char*, l->string), &eptr);
1598 if(RASQAL_GOOD_CAST(unsigned char*, eptr) != l->string && *eptr=='\0')
1599 return RASQAL_FLOATING_AS_INT(d);
1600 }
1601 if(error_p)
1602 *error_p = 1;
1603 return 0;
1604
1605 case RASQAL_LITERAL_VARIABLE:
1606 return rasqal_literal_as_integer(l->value.variable->value, error_p);
1607
1608 case RASQAL_LITERAL_BLANK:
1609 case RASQAL_LITERAL_URI:
1610 case RASQAL_LITERAL_QNAME:
1611 case RASQAL_LITERAL_PATTERN:
1612 case RASQAL_LITERAL_DATE:
1613 case RASQAL_LITERAL_DATETIME:
1614 case RASQAL_LITERAL_UDT:
1615 if(error_p)
1616 *error_p = 1;
1617 return 0;
1618
1619 case RASQAL_LITERAL_UNKNOWN:
1620 default:
1621 RASQAL_FATAL2("Unknown literal type %u", l->type);
1622 return 0; /* keep some compilers happy */
1623 }
1624 }
1625
1626
1627 /*
1628 * rasqal_literal_as_double:
1629 * @l: #rasqal_literal object
1630 * @error_p: pointer to error flag
1631 *
1632 * INTERNAL - Return a literal as a double precision floating value
1633 *
1634 * Integers, booleans, double and float literals natural are turned into
1635 * integers. If string values are the lexical form of an floating, that is
1636 * returned. Otherwise the error flag is set.
1637 *
1638 * Return value: double precision floating value
1639 **/
1640 double
rasqal_literal_as_double(rasqal_literal * l,int * error_p)1641 rasqal_literal_as_double(rasqal_literal* l, int *error_p)
1642 {
1643 if(!l) {
1644 /* type error */
1645 *error_p = 1;
1646 return 0.0;
1647 }
1648
1649 switch(l->type) {
1650 case RASQAL_LITERAL_INTEGER:
1651 case RASQAL_LITERAL_BOOLEAN:
1652 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1653 return (double)l->value.integer;
1654
1655 case RASQAL_LITERAL_DOUBLE:
1656 case RASQAL_LITERAL_FLOAT:
1657 return l->value.floating;
1658
1659 case RASQAL_LITERAL_DECIMAL:
1660 return rasqal_xsd_decimal_get_double(l->value.decimal);
1661
1662 case RASQAL_LITERAL_STRING:
1663 case RASQAL_LITERAL_XSD_STRING:
1664 {
1665 char *eptr = NULL;
1666 double d = strtod(RASQAL_GOOD_CAST(const char*, l->string), &eptr);
1667 if(RASQAL_GOOD_CAST(unsigned char*, eptr) != l->string && *eptr == '\0')
1668 return d;
1669 }
1670 if(error_p)
1671 *error_p = 1;
1672 return 0.0;
1673
1674 case RASQAL_LITERAL_VARIABLE:
1675 return rasqal_literal_as_double(l->value.variable->value, error_p);
1676
1677 case RASQAL_LITERAL_BLANK:
1678 case RASQAL_LITERAL_URI:
1679 case RASQAL_LITERAL_QNAME:
1680 case RASQAL_LITERAL_PATTERN:
1681 case RASQAL_LITERAL_DATE:
1682 case RASQAL_LITERAL_DATETIME:
1683 case RASQAL_LITERAL_UDT:
1684 if(error_p)
1685 *error_p = 1;
1686 return 0.0;
1687
1688 case RASQAL_LITERAL_UNKNOWN:
1689 default:
1690 RASQAL_FATAL2("Unknown literal type %u", l->type);
1691 return 0.0; /* keep some compilers happy */
1692 }
1693 }
1694
1695
1696 /*
1697 * rasqal_literal_as_uri:
1698 * @l: #rasqal_literal object
1699 *
1700 * INTERNAL - Return a literal as a raptor_uri*
1701 *
1702 * Return value: shared raptor_uri* value or NULL on failure
1703 **/
1704 raptor_uri*
rasqal_literal_as_uri(rasqal_literal * l)1705 rasqal_literal_as_uri(rasqal_literal* l)
1706 {
1707 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
1708
1709 if(l->type == RASQAL_LITERAL_URI)
1710 return l->value.uri;
1711
1712 if(l->type == RASQAL_LITERAL_VARIABLE && l->value.variable->value)
1713 return rasqal_literal_as_uri(l->value.variable->value);
1714
1715 return NULL;
1716 }
1717
1718
1719 /**
1720 * rasqal_literal_as_counted_string:
1721 * @l: #rasqal_literal object
1722 * @len_p: pointer to store length of string (or NULL)
1723 * @flags: comparison flags
1724 * @error_p: pointer to error
1725 *
1726 * Return a counted string format of a literal according to flags.
1727 *
1728 * flag bits affects conversion:
1729 * RASQAL_COMPARE_XQUERY: use XQuery conversion rules
1730 *
1731 * If @error is not NULL, *error is set to non-0 on error
1732 *
1733 * Return value: pointer to a shared string format of the literal.
1734 **/
1735 const unsigned char*
rasqal_literal_as_counted_string(rasqal_literal * l,size_t * len_p,int flags,int * error_p)1736 rasqal_literal_as_counted_string(rasqal_literal* l, size_t *len_p,
1737 int flags, int *error_p)
1738 {
1739 if(!l) {
1740 /* type error */
1741 if(error_p)
1742 *error_p = 1;
1743 return NULL;
1744 }
1745
1746 switch(l->type) {
1747 case RASQAL_LITERAL_XSD_STRING:
1748 case RASQAL_LITERAL_BOOLEAN:
1749 case RASQAL_LITERAL_INTEGER:
1750 case RASQAL_LITERAL_DOUBLE:
1751 case RASQAL_LITERAL_STRING:
1752 case RASQAL_LITERAL_BLANK:
1753 case RASQAL_LITERAL_PATTERN:
1754 case RASQAL_LITERAL_QNAME:
1755 case RASQAL_LITERAL_FLOAT:
1756 case RASQAL_LITERAL_DECIMAL:
1757 case RASQAL_LITERAL_DATE:
1758 case RASQAL_LITERAL_DATETIME:
1759 case RASQAL_LITERAL_UDT:
1760 case RASQAL_LITERAL_INTEGER_SUBTYPE:
1761 if(len_p)
1762 *len_p = l->string_len;
1763
1764 return l->string;
1765
1766 case RASQAL_LITERAL_URI:
1767 if(flags & RASQAL_COMPARE_XQUERY) {
1768 if(error_p)
1769 *error_p = 1;
1770 return NULL;
1771 }
1772 return raptor_uri_as_counted_string(l->value.uri, len_p);
1773
1774 case RASQAL_LITERAL_VARIABLE:
1775 return rasqal_literal_as_counted_string(l->value.variable->value, len_p,
1776 flags, error_p);
1777
1778 case RASQAL_LITERAL_UNKNOWN:
1779 default:
1780 RASQAL_FATAL2("Unknown literal type %u", l->type);
1781 }
1782
1783 return NULL;
1784 }
1785
1786
1787 /**
1788 * rasqal_literal_as_string_flags:
1789 * @l: #rasqal_literal object
1790 * @flags: comparison flags
1791 * @error_p: pointer to error
1792 *
1793 * Return the string format of a literal according to flags.
1794 *
1795 * flag bits affects conversion:
1796 * RASQAL_COMPARE_XQUERY: use XQuery conversion rules
1797 *
1798 * If @error is not NULL, *error is set to non-0 on error
1799 *
1800 * Return value: pointer to a shared string format of the literal.
1801 **/
1802 const unsigned char*
rasqal_literal_as_string_flags(rasqal_literal * l,int flags,int * error_p)1803 rasqal_literal_as_string_flags(rasqal_literal* l, int flags, int *error_p)
1804 {
1805 if(!l) {
1806 /* type error */
1807 *error_p = 1;
1808 return NULL;
1809 }
1810
1811 return rasqal_literal_as_counted_string(l, NULL, flags, error_p);
1812 }
1813
1814
1815 /**
1816 * rasqal_literal_as_string:
1817 * @l: #rasqal_literal object
1818 *
1819 * Return the string format of a literal.
1820 *
1821 * Return value: pointer to a shared string format of the literal.
1822 **/
1823 const unsigned char*
rasqal_literal_as_string(rasqal_literal * l)1824 rasqal_literal_as_string(rasqal_literal* l)
1825 {
1826 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
1827
1828 return rasqal_literal_as_string_flags(l, 0, NULL);
1829 }
1830
1831 /**
1832 * rasqal_literal_as_variable:
1833 * @l: #rasqal_literal object
1834 *
1835 * Get the variable inside a literal.
1836 *
1837 * Return value: the #rasqal_variable or NULL if the literal is not a variable
1838 **/
1839 rasqal_variable*
rasqal_literal_as_variable(rasqal_literal * l)1840 rasqal_literal_as_variable(rasqal_literal* l)
1841 {
1842 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
1843
1844 return (l->type == RASQAL_LITERAL_VARIABLE) ? l->value.variable : NULL;
1845 }
1846
1847
1848 /*
1849 * rasqal_literal_promote_numerics:
1850 * @l1: first literal
1851 * @l2: second literal
1852 * @flags: promotion flags
1853 *
1854 * INTERNAL - Calculate the type to promote a pair of literals to
1855 *
1856 * Numeric type promotion
1857 * http://www.w3.org/TR/xpath20/#dt-type-promotion
1858 *
1859 * [[xs:decimal (or any type derived by restriction from xs:decimal,
1860 * including xs:integer) can be promoted to either of the types
1861 * xs:float or xs:double.]]
1862 *
1863 * For here that means xs:integer to xs:double and xs:decimal to xs:double
1864 *
1865 * Return value: promote type or RASQAL_LITERAL_UNKNOWN
1866 */
1867 static rasqal_literal_type
rasqal_literal_promote_numerics(rasqal_literal * l1,rasqal_literal * l2,int flags)1868 rasqal_literal_promote_numerics(rasqal_literal* l1, rasqal_literal* l2,
1869 int flags)
1870 {
1871 rasqal_literal_type type1 = l1->type;
1872 rasqal_literal_type type2 = l2->type;
1873 rasqal_literal_type promotion_type;
1874 rasqal_literal_type result_type = RASQAL_LITERAL_UNKNOWN;
1875
1876 /* B1 1.b http://www.w3.org/TR/xpath20/#dt-type-promotion */
1877 if(type1 == RASQAL_LITERAL_DECIMAL &&
1878 (type2 == RASQAL_LITERAL_FLOAT || type2 == RASQAL_LITERAL_DOUBLE)) {
1879 result_type = type2;
1880 goto done;
1881 } else if(type2 == RASQAL_LITERAL_DECIMAL &&
1882 (type1 == RASQAL_LITERAL_FLOAT || type1 == RASQAL_LITERAL_DOUBLE)) {
1883 result_type = type1;
1884 goto done;
1885 }
1886
1887 for(promotion_type = RASQAL_LITERAL_FIRST_XSD;
1888 promotion_type <= RASQAL_LITERAL_LAST_XSD;
1889 promotion_type = (rasqal_literal_type)(RASQAL_GOOD_CAST(unsigned int, promotion_type) + 1)) {
1890 rasqal_literal_type parent_type1 = rasqal_xsd_datatype_parent_type(type1);
1891 rasqal_literal_type parent_type2 = rasqal_xsd_datatype_parent_type(type2);
1892
1893 /* Finished */
1894 if(type1 == type2) {
1895 result_type = type1;
1896 break;
1897 }
1898
1899 if(parent_type1 == type2) {
1900 result_type = type2;
1901 break;
1902 }
1903
1904 if(parent_type2 == type1) {
1905 result_type = type1;
1906 break;
1907 }
1908
1909 if(parent_type1 == promotion_type)
1910 type1 = promotion_type;
1911 if(parent_type2 == promotion_type)
1912 type2 = promotion_type;
1913 }
1914
1915 done:
1916 RASQAL_DEBUG4("literal 1: type %s literal 2: type %s promoting to %s\n",
1917 rasqal_literal_type_label(type1),
1918 rasqal_literal_type_label(type2),
1919 rasqal_literal_type_label(result_type));
1920
1921 return result_type;
1922 }
1923
1924
1925 /**
1926 * rasqal_literal_get_rdf_term_type:
1927 * @l: literal
1928 *
1929 * Get the RDF term type of a literal
1930 *
1931 * An RDF term can be one of three choices:
1932 * 1. URI: RASQAL_LITERAL_URI
1933 * 2. literal: RASQAL_LITERAL_STRING
1934 * 3. blank node: RASQAL_LITERAL_BLANK
1935 *
1936 * Other non RDF-term cases include: NULL pointer, invalid literal,
1937 * unknown type, a variable or other special cases (such as XML QName
1938 * or Regex pattern) which all turn into RASQAL_LITERAL_UNKNOWN
1939 *
1940 * Return value: type or RASQAL_LITERAL_UNKNOWN if cannot be an RDF term
1941 */
1942 rasqal_literal_type
rasqal_literal_get_rdf_term_type(rasqal_literal * l)1943 rasqal_literal_get_rdf_term_type(rasqal_literal* l)
1944 {
1945 rasqal_literal_type type;
1946
1947 if(!l)
1948 return RASQAL_LITERAL_UNKNOWN;
1949
1950 type = l->type;
1951
1952 /* squash literal datatypes into one type: RDF Literal */
1953 if((type >= RASQAL_LITERAL_FIRST_XSD && type <= RASQAL_LITERAL_LAST_XSD) ||
1954 type == RASQAL_LITERAL_DATE || type == RASQAL_LITERAL_INTEGER_SUBTYPE)
1955 type = RASQAL_LITERAL_STRING;
1956
1957 if(type == RASQAL_LITERAL_UDT)
1958 type = RASQAL_LITERAL_STRING;
1959
1960 if(type != RASQAL_LITERAL_URI &&
1961 type != RASQAL_LITERAL_STRING &&
1962 type != RASQAL_LITERAL_BLANK)
1963 type = RASQAL_LITERAL_UNKNOWN;
1964
1965 return type;
1966 }
1967
1968 /**
1969 * rasqal_literal_get_type:
1970 * @l: literal
1971 *
1972 * Get the type of a literal
1973 *
1974 * Return value: the rasqal literal type or RASQAL_LITERAL_UNKNOWN if l is NULL
1975 */
1976 rasqal_literal_type
rasqal_literal_get_type(rasqal_literal * l)1977 rasqal_literal_get_type(rasqal_literal* l)
1978 {
1979 rasqal_literal_type type;
1980
1981 if(!l)
1982 return RASQAL_LITERAL_UNKNOWN;
1983
1984 type = l->type;
1985
1986 return type;
1987 }
1988
1989 /**
1990 * rasqal_literal_get_language:
1991 * @l: literal
1992 *
1993 * Get the language of a literal (if set)
1994 *
1995 * Return value: the literal language or NULL
1996 */
1997 char*
rasqal_literal_get_language(rasqal_literal * l)1998 rasqal_literal_get_language(rasqal_literal* l)
1999 {
2000 if(!l)
2001 return NULL;
2002
2003 return l->language;
2004 }
2005
2006
2007
2008
2009 /*
2010 * rasqal_new_literal_from_promotion:
2011 * @lit: existing literal
2012 * @type: type to promote to
2013 * @flags: 0 (flag #RASQAL_COMPARE_URI is unused: was RDQL)
2014 *
2015 * INTERNAL - Make a new literal from a type promotion
2016 *
2017 * New literal or NULL on failure
2018 */
2019 static rasqal_literal*
rasqal_new_literal_from_promotion(rasqal_literal * lit,rasqal_literal_type type,int flags)2020 rasqal_new_literal_from_promotion(rasqal_literal* lit,
2021 rasqal_literal_type type,
2022 int flags)
2023 {
2024 rasqal_literal* new_lit = NULL;
2025 int errori = 0;
2026 double d;
2027 int i;
2028 unsigned char *new_s = NULL;
2029 unsigned char* s;
2030 size_t len = 0;
2031 rasqal_xsd_decimal* dec = NULL;
2032
2033 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(lit, rasqal_literal, NULL);
2034
2035 if(lit->type == type)
2036 return rasqal_new_literal_from_literal(lit);
2037
2038 RASQAL_DEBUG3("promoting literal type %s to type %s\n",
2039 rasqal_literal_type_label(lit->type),
2040 rasqal_literal_type_label(type));
2041
2042 if(lit->type == RASQAL_LITERAL_DATE && type == RASQAL_LITERAL_DATETIME) {
2043 rasqal_xsd_datetime* dt;
2044
2045 dt = rasqal_new_xsd_datetime_from_xsd_date(lit->world, lit->value.date);
2046
2047 /* Promotion for comparison ensures a timezone is present.
2048 *
2049 * " If either operand to a comparison function on date or time
2050 * values does not have an (explicit) timezone then, for the
2051 * purpose of the operation, an implicit timezone, provided by the
2052 * dynamic context Section C.2 Dynamic Context ComponentsXP, is
2053 * assumed to be present as part of the value."
2054 * -- XQuery & XPath F&O
2055 * Section 10.4 Comparison Operators on Duration, Date and Time Values
2056 * http://www.w3.org/TR/xpath-functions/#comp.duration.datetime
2057 */
2058 if(dt->have_tz == 'N') {
2059 dt->have_tz = 'Z';
2060 dt->timezone_minutes = 0;
2061 }
2062 return rasqal_new_datetime_literal_from_datetime(lit->world, dt);
2063 }
2064
2065 /* May not promote to non-numerics */
2066 if(!rasqal_xsd_datatype_is_numeric(type)) {
2067 RASQAL_DEBUG2("NOT promoting to non-numeric type %s\n",
2068 rasqal_literal_type_label(lit->type));
2069
2070 if(type == RASQAL_LITERAL_STRING || type == RASQAL_LITERAL_UDT) {
2071 s = RASQAL_GOOD_CAST(unsigned char*, rasqal_literal_as_counted_string(lit, &len, 0, NULL));
2072 new_s = RASQAL_MALLOC(unsigned char*, len + 1);
2073 if(new_s) {
2074 raptor_uri* dt_uri = NULL;
2075 memcpy(new_s, s, len + 1);
2076 if(lit->datatype) {
2077 dt_uri = raptor_uri_copy(lit->datatype);
2078 }
2079 return rasqal_new_string_literal_node(lit->world, new_s, NULL, dt_uri);
2080 } else
2081 return NULL;
2082 }
2083 return NULL;
2084 }
2085
2086 switch(type) {
2087 case RASQAL_LITERAL_DECIMAL:
2088 dec = rasqal_new_xsd_decimal(lit->world);
2089 if(dec) {
2090 d = rasqal_literal_as_double(lit, &errori);
2091 if(errori) {
2092 rasqal_free_xsd_decimal(dec);
2093 new_lit = NULL;
2094 } else {
2095 rasqal_xsd_decimal_set_double(dec, d);
2096 new_lit = rasqal_new_decimal_literal_from_decimal(lit->world,
2097 NULL, dec);
2098 }
2099 }
2100 break;
2101
2102
2103 case RASQAL_LITERAL_DOUBLE:
2104 d = rasqal_literal_as_double(lit, &errori);
2105 if(errori)
2106 new_lit = NULL;
2107 else
2108 new_lit = rasqal_new_double_literal(lit->world, d);
2109 break;
2110
2111
2112 case RASQAL_LITERAL_FLOAT:
2113 d = rasqal_literal_as_double(lit, &errori);
2114 if(errori)
2115 new_lit = NULL;
2116 else if(d < FLT_MIN || d > FLT_MAX)
2117 /* Cannot be stored in a float - fail */
2118 new_lit = NULL;
2119 else
2120 new_lit = rasqal_new_floating_literal(lit->world, RASQAL_LITERAL_FLOAT,
2121 d);
2122 break;
2123
2124
2125 case RASQAL_LITERAL_INTEGER:
2126 case RASQAL_LITERAL_INTEGER_SUBTYPE:
2127 i = rasqal_literal_as_integer(lit, &errori);
2128 /* failure always means no match */
2129 if(errori)
2130 new_lit = NULL;
2131 else
2132 new_lit = rasqal_new_integer_literal(lit->world, type, i);
2133 break;
2134
2135 case RASQAL_LITERAL_BOOLEAN:
2136 if(flags & RASQAL_COMPARE_URI)
2137 i = rasqal_xsd_boolean_value_from_string(lit->string);
2138 else
2139 i = rasqal_literal_as_boolean(lit, &errori);
2140 /* failure always means no match */
2141 if(errori)
2142 new_lit = NULL;
2143 else
2144 new_lit = rasqal_new_integer_literal(lit->world, type, i);
2145 break;
2146
2147 case RASQAL_LITERAL_STRING:
2148 s = RASQAL_GOOD_CAST(unsigned char*, rasqal_literal_as_counted_string(lit, &len, 0, NULL));
2149 new_s = RASQAL_MALLOC(unsigned char*, len + 1);
2150 if(new_s) {
2151 memcpy(new_s, s, len + 1);
2152 new_lit = rasqal_new_string_literal(lit->world, new_s, NULL, NULL, NULL);
2153 }
2154 break;
2155
2156 case RASQAL_LITERAL_XSD_STRING:
2157 s = RASQAL_GOOD_CAST(unsigned char*, rasqal_literal_as_counted_string(lit, &len, 0, NULL));
2158 new_s = RASQAL_MALLOC(unsigned char*, len + 1);
2159 if(new_s) {
2160 raptor_uri* dt_uri;
2161 memcpy(new_s, s, len + 1);
2162 dt_uri = rasqal_xsd_datatype_type_to_uri(lit->world, lit->type);
2163 dt_uri = raptor_uri_copy(dt_uri);
2164 new_lit = rasqal_new_string_literal(lit->world, new_s, NULL, dt_uri,
2165 NULL);
2166 }
2167 break;
2168
2169 case RASQAL_LITERAL_UNKNOWN:
2170 case RASQAL_LITERAL_BLANK:
2171 case RASQAL_LITERAL_URI:
2172 case RASQAL_LITERAL_DATE:
2173 case RASQAL_LITERAL_DATETIME:
2174 case RASQAL_LITERAL_PATTERN:
2175 case RASQAL_LITERAL_QNAME:
2176 case RASQAL_LITERAL_VARIABLE:
2177 case RASQAL_LITERAL_UDT:
2178 default:
2179 errori = 1;
2180 new_lit = NULL;
2181 }
2182
2183 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2184 if(new_lit)
2185 RASQAL_DEBUG4("promoted literal type %s to type %s, with value '%s'\n",
2186 rasqal_literal_type_label(lit->type),
2187 rasqal_literal_type_label(new_lit->type),
2188 rasqal_literal_as_string(new_lit));
2189 else
2190 RASQAL_DEBUG3("failed to promote literal type %s to type %s\n",
2191 rasqal_literal_type_label(lit->type),
2192 rasqal_literal_type_label(type));
2193 #endif
2194
2195 return new_lit;
2196 }
2197
2198
2199 /*
2200 * rasqal_literal_string_languages_compare
2201 * @l1: #rasqal_literal first literal
2202 * @l2: #rasqal_literal second literal
2203 *
2204 * INTERNAL - Compare two string literals languages
2205 *
2206 * Return value: non-0 if equal
2207 */
2208 int
rasqal_literal_string_languages_compare(rasqal_literal * l1,rasqal_literal * l2)2209 rasqal_literal_string_languages_compare(rasqal_literal* l1, rasqal_literal* l2)
2210 {
2211 int rc = 0;
2212
2213 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, 0);
2214 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, 0);
2215
2216 if(l1->language && l2->language)
2217 /* both have a language */
2218 rc = rasqal_strcasecmp(RASQAL_GOOD_CAST(const char*, l1->language),
2219 RASQAL_GOOD_CAST(const char*, l2->language));
2220 else if(l1->language || l2->language)
2221 /* only one has a language; the language-less one is earlier */
2222 rc = (!l1->language ? -1 : 1);
2223
2224 return rc;
2225 }
2226
2227
2228 /*
2229 * rasqal_literal_string_datatypes_compare:
2230 * @l1: first string literal
2231 * @l2: first string literal
2232 *
2233 * INTERNAL - Compare the datatypes of two string RDF literals
2234 *
2235 * Return value: <1, 0, >0
2236 */
2237 int
rasqal_literal_string_datatypes_compare(rasqal_literal * l1,rasqal_literal * l2)2238 rasqal_literal_string_datatypes_compare(rasqal_literal* l1, rasqal_literal* l2)
2239 {
2240 int rc = 0;
2241
2242 if(l1->datatype && l2->datatype) {
2243 /* both have a datatype */
2244 rc = raptor_uri_compare(l1->datatype, l2->datatype);
2245 } else if(l1->datatype || l2->datatype)
2246 /* only one has a datatype; the datatype-less one is earlier */
2247 rc = (!l1->datatype ? -1 : 1);
2248
2249 return rc;
2250 }
2251
2252
2253 /*
2254 * rasqal_literal_string_compare:
2255 * @l1: first string literal
2256 * @l2: first string literal
2257 * @flags: string compare flags (flag #RASQAL_COMPARE_NOCASE is unused; was RDQL)
2258 *
2259 * INTERNAL - Compare two string RDF literals. Bother are the same
2260 * type and either #RASQAL_LITERAL_STRING or #RASQAL_LITERAL_UDT
2261 * however their datatype URIs are the non-promoted types and may differ.
2262 *
2263 * Uses raptor_term_compare() logic for the #RAPTOR_TERM_TYPE_LITERAL
2264 * case, except adding case independent compare for RDQL.
2265 *
2266 * Return value: <1, 0, >0
2267 */
2268 static int
rasqal_literal_string_compare(rasqal_literal * l1,rasqal_literal * l2,int flags)2269 rasqal_literal_string_compare(rasqal_literal* l1, rasqal_literal* l2,
2270 int flags)
2271 {
2272 int rc;
2273
2274 if(flags & RASQAL_COMPARE_NOCASE)
2275 rc = rasqal_strcasecmp(RASQAL_GOOD_CAST(const char*, l1->string),
2276 RASQAL_GOOD_CAST(const char*, l2->string));
2277 else
2278 rc = strcmp(RASQAL_GOOD_CAST(const char*, l1->string),
2279 RASQAL_GOOD_CAST(const char*, l2->string));
2280 if(rc)
2281 return rc;
2282
2283 rc = rasqal_literal_string_languages_compare(l1, l2);
2284 if(rc)
2285 return rc;
2286
2287 return rasqal_literal_string_datatypes_compare(l1, l2);
2288 }
2289
2290
2291 /*
2292 * rasqal_literal_rdql_promote_calculate:
2293 * @l1: first literal
2294 * @l2: second literal
2295 *
2296 * INTERNAL - Handle RDQL type promotion rules
2297 *
2298 * Return value: type to promote to or RASQAL_LITERAL_UNKNOWN if not possible.
2299 */
2300 static rasqal_literal_type
rasqal_literal_rdql_promote_calculate(rasqal_literal * l1,rasqal_literal * l2)2301 rasqal_literal_rdql_promote_calculate(rasqal_literal* l1, rasqal_literal* l2)
2302 {
2303 int seen_string = 0;
2304 int seen_int = 0;
2305 int seen_double = 0;
2306 int seen_boolean = 0;
2307 int i;
2308 rasqal_literal *lits[2];
2309 rasqal_literal_type type = RASQAL_LITERAL_UNKNOWN;
2310
2311 lits[0] = l1;
2312 lits[1] = l2;
2313
2314 for(i = 0; i < 2; i++) {
2315 switch(lits[i]->type) {
2316 case RASQAL_LITERAL_URI:
2317 case RASQAL_LITERAL_DECIMAL:
2318 break;
2319
2320 case RASQAL_LITERAL_STRING:
2321 case RASQAL_LITERAL_XSD_STRING:
2322 case RASQAL_LITERAL_BLANK:
2323 case RASQAL_LITERAL_PATTERN:
2324 case RASQAL_LITERAL_QNAME:
2325 case RASQAL_LITERAL_DATE:
2326 case RASQAL_LITERAL_DATETIME:
2327 case RASQAL_LITERAL_UDT:
2328 seen_string++;
2329 break;
2330
2331 case RASQAL_LITERAL_BOOLEAN:
2332 seen_boolean = 1;
2333 break;
2334
2335 case RASQAL_LITERAL_INTEGER:
2336 case RASQAL_LITERAL_INTEGER_SUBTYPE:
2337 seen_int++;
2338 break;
2339
2340 case RASQAL_LITERAL_DOUBLE:
2341 case RASQAL_LITERAL_FLOAT:
2342 seen_double++;
2343 break;
2344
2345 case RASQAL_LITERAL_VARIABLE:
2346 /* this case was dealt with elsewhere */
2347
2348 case RASQAL_LITERAL_UNKNOWN:
2349 default:
2350 RASQAL_FATAL2("Unknown literal type %u", lits[i]->type);
2351 }
2352 }
2353
2354
2355 if(lits[0]->type != lits[1]->type) {
2356 type = seen_string ? RASQAL_LITERAL_STRING : RASQAL_LITERAL_INTEGER;
2357 if((seen_int & seen_double) || (seen_int & seen_string))
2358 type = RASQAL_LITERAL_DOUBLE;
2359 if(seen_boolean & seen_string)
2360 type = RASQAL_LITERAL_BOOLEAN;
2361 } else
2362 type = lits[0]->type;
2363
2364 return type;
2365 }
2366
2367
2368
2369 /**
2370 * rasqal_literal_compare:
2371 * @l1: #rasqal_literal first literal
2372 * @l2: #rasqal_literal second literal
2373 * @flags: comparison flags
2374 * @error_p: pointer to error
2375 *
2376 * Compare two literals with type promotion.
2377 *
2378 * The two literals are compared across their range. If the types
2379 * are not the same, they are promoted. If one is a double or float, the
2380 * other is promoted to double, otherwise for integers, otherwise
2381 * to strings (all literals have a string value).
2382 *
2383 * The comparison returned is as for strcmp, first before second
2384 * returns <0. equal returns 0, and first after second returns >0.
2385 * For URIs, the string value is used for the comparsion.
2386 *
2387 * flag bits affects comparisons:
2388 * RASQAL_COMPARE_NOCASE: use case independent string comparisons
2389 * RASQAL_COMPARE_XQUERY: use XQuery comparison and type promotion rules
2390 * RASQAL_COMPARE_RDF: use RDF term comparison
2391 * RASQAL_COMPARE_URI: allow comparison of URIs (typically for SPARQL ORDER)
2392 *
2393 * If @error is not NULL, *error is set to non-0 on error
2394 *
2395 * Return value: <0, 0, or >0 as described above.
2396 **/
2397 int
rasqal_literal_compare(rasqal_literal * l1,rasqal_literal * l2,int flags,int * error_p)2398 rasqal_literal_compare(rasqal_literal* l1, rasqal_literal* l2, int flags,
2399 int *error_p)
2400 {
2401 rasqal_literal *lits[2];
2402 rasqal_literal* new_lits[2]; /* after promotions */
2403 rasqal_literal_type type; /* target promotion type */
2404 int i;
2405 int result = 0;
2406 double d = 0;
2407 int promotion = 0;
2408
2409 if(error_p)
2410 *error_p = 0;
2411
2412 if(!l1 || !l2) {
2413 if(error_p)
2414 *error_p = 1;
2415 return 0;
2416 }
2417
2418 lits[0] = rasqal_literal_value(l1);
2419 lits[1] = rasqal_literal_value(l2);
2420
2421 /* null literals */
2422 if(!lits[0] || !lits[1]) {
2423 /* if either is not NULL, the comparison fails */
2424 if(lits[0] || lits[1]) {
2425 if(error_p)
2426 *error_p = 1;
2427 }
2428 return 0;
2429 }
2430
2431 new_lits[0] = NULL;
2432 new_lits[1] = NULL;
2433
2434 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2435 RASQAL_DEBUG3("literal 0 type %s. literal 1 type %s\n",
2436 rasqal_literal_type_label(lits[0]->type),
2437 rasqal_literal_type_label(lits[1]->type));
2438 #endif
2439
2440 if(flags & RASQAL_COMPARE_RDF) {
2441 /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
2442 rasqal_literal_type type0 = rasqal_literal_get_rdf_term_type(lits[0]);
2443 rasqal_literal_type type1 = rasqal_literal_get_rdf_term_type(lits[1]);
2444 int type_diff;
2445
2446 if(type0 == RASQAL_LITERAL_UNKNOWN || type1 == RASQAL_LITERAL_UNKNOWN)
2447 return 1;
2448
2449 type_diff = RASQAL_GOOD_CAST(int, type0) - RASQAL_GOOD_CAST(int, type1);
2450 if(type_diff != 0) {
2451 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2452 RASQAL_DEBUG2("RDF term literal returning type difference %d\n",
2453 type_diff);
2454 #endif
2455 return type_diff;
2456 }
2457 type = type1;
2458 } else if(flags & RASQAL_COMPARE_XQUERY) {
2459 /* SPARQL / XQuery promotion rules */
2460 rasqal_literal_type type0 = lits[0]->type;
2461 rasqal_literal_type type1 = lits[1]->type;
2462
2463 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2464 RASQAL_DEBUG3("xquery literal compare types %s vs %s\n",
2465 rasqal_literal_type_label(type0),
2466 rasqal_literal_type_label(type1));
2467 #endif
2468
2469 /* cannot compare UDTs */
2470 if(type0 == RASQAL_LITERAL_UDT || type1 == RASQAL_LITERAL_UDT) {
2471 if(error_p)
2472 *error_p = 1;
2473 return 0;
2474 }
2475
2476 type = rasqal_literal_promote_numerics(lits[0], lits[1], flags);
2477 if(type == RASQAL_LITERAL_UNKNOWN) {
2478 int type_diff;
2479
2480 /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
2481 type0 = rasqal_literal_get_rdf_term_type(lits[0]);
2482 type1 = rasqal_literal_get_rdf_term_type(lits[1]);
2483
2484 if(type0 == RASQAL_LITERAL_UNKNOWN || type1 == RASQAL_LITERAL_UNKNOWN)
2485 return 1;
2486
2487 type_diff = RASQAL_GOOD_CAST(int, type0) - RASQAL_GOOD_CAST(int, type1);
2488 if(type_diff != 0) {
2489 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2490 RASQAL_DEBUG2("RDF term literal returning type difference %d\n",
2491 type_diff);
2492 #endif
2493 return type_diff;
2494 }
2495 if(error_p)
2496 *error_p = 1;
2497 return 0;
2498 }
2499 promotion = 1;
2500 } else {
2501 /* RDQL promotion rules */
2502 type = rasqal_literal_rdql_promote_calculate(lits[0], lits[1]);
2503 promotion = 1;
2504 }
2505
2506 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2507 if(promotion)
2508 RASQAL_DEBUG2("promoting to type %s\n", rasqal_literal_type_label(type));
2509 #endif
2510
2511 /* do promotions */
2512 for(i = 0; i < 2; i++) {
2513 if(promotion) {
2514 new_lits[i] = rasqal_new_literal_from_promotion(lits[i], type, flags);
2515 if(!new_lits[i]) {
2516 if(error_p)
2517 *error_p = 1;
2518 goto done;
2519 }
2520 } else {
2521 new_lits[i] = lits[i];
2522 }
2523 }
2524
2525
2526 switch(type) {
2527 case RASQAL_LITERAL_URI:
2528 if(flags & RASQAL_COMPARE_URI)
2529 result = raptor_uri_compare(new_lits[0]->value.uri,
2530 new_lits[1]->value.uri);
2531 else {
2532 if(error_p)
2533 *error_p = 1;
2534 result = 0;
2535 goto done;
2536 }
2537 break;
2538
2539 case RASQAL_LITERAL_STRING:
2540 case RASQAL_LITERAL_UDT:
2541 result = rasqal_literal_string_compare(new_lits[0], new_lits[1],
2542 flags);
2543 break;
2544
2545 case RASQAL_LITERAL_BLANK:
2546 case RASQAL_LITERAL_PATTERN:
2547 case RASQAL_LITERAL_QNAME:
2548 case RASQAL_LITERAL_XSD_STRING:
2549 if(flags & RASQAL_COMPARE_NOCASE)
2550 result = rasqal_strcasecmp(RASQAL_GOOD_CAST(const char*, new_lits[0]->string),
2551 RASQAL_GOOD_CAST(const char*, new_lits[1]->string));
2552 else
2553 result = strcmp(RASQAL_GOOD_CAST(const char*, new_lits[0]->string),
2554 RASQAL_GOOD_CAST(const char*, new_lits[1]->string));
2555 break;
2556
2557 case RASQAL_LITERAL_DATE:
2558 result = rasqal_xsd_date_compare(new_lits[0]->value.date,
2559 new_lits[1]->value.date,
2560 error_p);
2561 break;
2562
2563 case RASQAL_LITERAL_DATETIME:
2564 result = rasqal_xsd_datetime_compare2(new_lits[0]->value.datetime,
2565 new_lits[1]->value.datetime,
2566 error_p);
2567 break;
2568
2569 case RASQAL_LITERAL_INTEGER:
2570 case RASQAL_LITERAL_BOOLEAN:
2571 case RASQAL_LITERAL_INTEGER_SUBTYPE:
2572 result = new_lits[0]->value.integer - new_lits[1]->value.integer;
2573 break;
2574
2575 case RASQAL_LITERAL_DOUBLE:
2576 case RASQAL_LITERAL_FLOAT:
2577 d = new_lits[0]->value.floating - new_lits[1]->value.floating;
2578 result = (d > 0.0) ? 1: (d < 0.0) ? -1 : 0;
2579 break;
2580
2581 case RASQAL_LITERAL_DECIMAL:
2582 result = rasqal_xsd_decimal_compare(new_lits[0]->value.decimal,
2583 new_lits[1]->value.decimal);
2584 break;
2585
2586 case RASQAL_LITERAL_UNKNOWN:
2587 case RASQAL_LITERAL_VARIABLE:
2588 default:
2589 RASQAL_FATAL2("Literal type %u cannot be compared", type);
2590 result = 0; /* keep some compilers happy */
2591 }
2592
2593 done:
2594 if(promotion) {
2595 for(i = 0; i < 2; i++) {
2596 if(new_lits[i])
2597 rasqal_free_literal(new_lits[i]);
2598 }
2599 }
2600
2601 return result;
2602 }
2603
2604
2605 /*
2606 * rasqal_literal_is_string:
2607 * @l1: #rasqal_literal first literal
2608 *
2609 * INTERNAL - check literal is a string literal
2610 *
2611 * Return value: non-0 if literal is a string
2612 */
2613 int
rasqal_literal_is_string(rasqal_literal * l1)2614 rasqal_literal_is_string(rasqal_literal* l1)
2615 {
2616 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, 1);
2617
2618 return (l1->type == RASQAL_LITERAL_STRING || l1->type == RASQAL_LITERAL_XSD_STRING);
2619 }
2620
2621
2622 /*
2623 * rasqal_literal_string_equals_flags:
2624 * @l1: #rasqal_literal first literal
2625 * @l2: #rasqal_literal second literal
2626 * @flags: comparison flags
2627 * @error_p: pointer to error
2628 *
2629 * INTERNAL - Compare two typed literals
2630 *
2631 * flag bits affects equality:
2632 * RASQAL_COMPARE_XQUERY: use value equality
2633 * RASQAL_COMPARE_RDF: use RDF term equality
2634 *
2635 * Return value: non-0 if equal
2636 */
2637 static int
rasqal_literal_string_equals_flags(rasqal_literal * l1,rasqal_literal * l2,int flags,int * error_p)2638 rasqal_literal_string_equals_flags(rasqal_literal* l1, rasqal_literal* l2,
2639 int flags, int* error_p)
2640 {
2641 int result = 1;
2642 raptor_uri* dt1;
2643 int free_dt1 = 0;
2644 raptor_uri* dt2;
2645 int free_dt2 = 0;
2646 raptor_uri* xsd_string_uri;
2647
2648 if(error_p)
2649 *error_p = 0;
2650
2651 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, 0);
2652 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, 0);
2653
2654 dt1 = l1->datatype;
2655 dt2 = l2->datatype;
2656
2657 xsd_string_uri = rasqal_xsd_datatype_type_to_uri(l1->world,
2658 RASQAL_LITERAL_XSD_STRING);
2659
2660 if(rasqal_literal_string_languages_compare(l1, l2))
2661 return 0;
2662
2663 /* For a value comparison (or RDQL), promote plain literal to typed
2664 * literal "xx"^^xsd:string if the other literal is typed
2665 */
2666 if(flags & RASQAL_COMPARE_XQUERY || flags & RASQAL_COMPARE_URI) {
2667 if(l1->type == RASQAL_LITERAL_STRING &&
2668 l2->type == RASQAL_LITERAL_XSD_STRING) {
2669 dt1 = raptor_uri_copy(xsd_string_uri);
2670 free_dt1 = 1;
2671 } else if(l1->type == RASQAL_LITERAL_XSD_STRING &&
2672 l2->type == RASQAL_LITERAL_STRING) {
2673 dt2 = raptor_uri_copy(xsd_string_uri);
2674 free_dt2 = 1;
2675 }
2676 }
2677
2678 if(dt1 || dt2) {
2679 /* if either is NULL - type error */
2680 if(!dt1 || !dt2) {
2681 if(error_p)
2682 *error_p = 1;
2683 result = 0;
2684 goto done;
2685 }
2686 /* if different - type error */
2687 if(!raptor_uri_equals(dt1, dt2)) {
2688 if(error_p)
2689 *error_p = 1;
2690 result = 0;
2691 goto done;
2692 }
2693 /* at this point the datatypes (URIs) are the same */
2694 }
2695
2696 /* Finally check the lexical forms */
2697
2698 /* not-equal if lengths are different - cheaper to try this first */
2699 if(l1->string_len != l2->string_len) {
2700 result = 0;
2701 goto done;
2702 }
2703
2704 result = !strcmp(RASQAL_GOOD_CAST(const char*, l1->string),
2705 RASQAL_GOOD_CAST(const char*, l2->string));
2706
2707 /* If result is equality but literals were both typed literals with
2708 * user-defined types then cause a type error; equality is unknown.
2709 */
2710 if(!result &&
2711 (l1->type == RASQAL_LITERAL_UDT && l2->type == RASQAL_LITERAL_UDT)) {
2712 if(error_p)
2713 *error_p = 1;
2714 }
2715
2716 done:
2717 if(dt1 && free_dt1)
2718 raptor_free_uri(dt1);
2719 if(dt2 && free_dt2)
2720 raptor_free_uri(dt2);
2721
2722 return result;
2723 }
2724
2725
2726 static int
rasqal_literal_uri_equals(rasqal_literal * l1,rasqal_literal * l2)2727 rasqal_literal_uri_equals(rasqal_literal* l1, rasqal_literal* l2)
2728 {
2729 return raptor_uri_equals(l1->value.uri, l2->value.uri);
2730 }
2731
2732
2733 static int
rasqal_literal_blank_equals(rasqal_literal * l1,rasqal_literal * l2)2734 rasqal_literal_blank_equals(rasqal_literal* l1, rasqal_literal* l2)
2735 {
2736 /* not-equal if lengths are different - cheap to compare this first */
2737 if(l1->string_len != l2->string_len)
2738 return 0;
2739
2740 return !strcmp(RASQAL_GOOD_CAST(const char*, l1->string),
2741 RASQAL_GOOD_CAST(const char*, l2->string));
2742 }
2743
2744
2745 /**
2746 * rasqal_literal_not_equals_flags:
2747 * @l1: #rasqal_literal literal
2748 * @l2: #rasqal_literal data literal
2749 *
2750 * Check if two literals are not equal with optional type promotion.
2751 *
2752 * Return value: non-0 if not-equal
2753 **/
2754 int
rasqal_literal_not_equals_flags(rasqal_literal * l1,rasqal_literal * l2,int flags,int * error_p)2755 rasqal_literal_not_equals_flags(rasqal_literal* l1, rasqal_literal* l2,
2756 int flags, int* error_p)
2757 {
2758 /* rasqal_literal_equals_flags() checks for NULLs */
2759
2760 return !rasqal_literal_equals_flags(l1, l2, flags, error_p);
2761 }
2762
2763
2764 /**
2765 * rasqal_literal_equals:
2766 * @l1: #rasqal_literal literal
2767 * @l2: #rasqal_literal data literal
2768 *
2769 * Compare two literals with no type promotion.
2770 *
2771 * If the l2 data literal value is a boolean, it will match
2772 * the string "true" or "false" in the first literal l1.
2773 *
2774 * Return value: non-0 if equal
2775 **/
2776 int
rasqal_literal_equals(rasqal_literal * l1,rasqal_literal * l2)2777 rasqal_literal_equals(rasqal_literal* l1, rasqal_literal* l2)
2778 {
2779 /* rasqal_literal_equals_flags() checks for NULLs */
2780
2781 return rasqal_literal_equals_flags(l1, l2, 0, NULL);
2782 }
2783
2784
2785 /*
2786 * rasqal_literal_equals_flags:
2787 * @l1: #rasqal_literal literal
2788 * @l2: #rasqal_literal data literal
2789 * @flags: comparison flags
2790 * @error_p: type error
2791 *
2792 * INTERNAL - Compare two literals with optional type promotion.
2793 *
2794 * flag bits affects equality:
2795 * RASQAL_COMPARE_XQUERY: use XQuery comparison and type promotion rules
2796 * RASQAL_COMPARE_RDF: use RDF term equality
2797 *
2798 * Return value: non-0 if equal
2799 **/
2800 int
rasqal_literal_equals_flags(rasqal_literal * l1,rasqal_literal * l2,int flags,int * error_p)2801 rasqal_literal_equals_flags(rasqal_literal* l1, rasqal_literal* l2,
2802 int flags, int* error_p)
2803 {
2804 rasqal_literal_type type;
2805 rasqal_literal* l1_p = NULL;
2806 rasqal_literal* l2_p = NULL;
2807 int result = 0;
2808 int promotion = 0;
2809
2810 /* NULL literals */
2811 if(!l1 || !l2) {
2812 /* if either is not null, the comparison fails */
2813 return !(l1 || l2);
2814 }
2815
2816 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2817 RASQAL_DEBUG1(" ");
2818 rasqal_literal_print(l1, stderr);
2819 fputs( " to ", stderr);
2820 rasqal_literal_print(l2, stderr);
2821 fprintf(stderr, " with flags %d\n", flags);
2822 #endif
2823
2824 if(flags & RASQAL_COMPARE_RDF) {
2825 /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
2826 rasqal_literal_type type1 = rasqal_literal_get_rdf_term_type(l1);
2827 rasqal_literal_type type2 = rasqal_literal_get_rdf_term_type(l2);
2828
2829 if(type1 == RASQAL_LITERAL_UNKNOWN || type2 == RASQAL_LITERAL_UNKNOWN ||
2830 type1 != type2)
2831 goto tidy;
2832
2833 type = type1;
2834 } else if(flags & RASQAL_COMPARE_XQUERY) {
2835 /* SPARQL / XSD promotion rules */
2836
2837 /* Ensure the values are native */
2838 rasqal_literal_string_to_native(l1, 0);
2839 rasqal_literal_string_to_native(l2, 0);
2840
2841 if((l1->type == RASQAL_LITERAL_DATE &&
2842 l2->type == RASQAL_LITERAL_DATETIME) ||
2843 (l1->type == RASQAL_LITERAL_DATETIME &&
2844 l2->type == RASQAL_LITERAL_DATE)) {
2845 type = RASQAL_LITERAL_DATETIME;
2846 promotion = 1;
2847 } else if(l1->type != l2->type) {
2848 type = rasqal_literal_promote_numerics(l1, l2, flags);
2849 if(type == RASQAL_LITERAL_UNKNOWN) {
2850 /* Cannot numeric promote - try RDF equality */
2851 rasqal_literal_type type1 = rasqal_literal_get_rdf_term_type(l1);
2852 rasqal_literal_type type2 = rasqal_literal_get_rdf_term_type(l2);
2853
2854 if(type1 == RASQAL_LITERAL_UNKNOWN || type2 == RASQAL_LITERAL_UNKNOWN ||
2855 type1 != type2)
2856 goto tidy;
2857
2858 type = type1;
2859 } else
2860 promotion = 1;
2861 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2862 RASQAL_DEBUG4("xquery promoted literals types (%s, %s) to type %s\n",
2863 rasqal_literal_type_label(l1->type),
2864 rasqal_literal_type_label(l2->type),
2865 rasqal_literal_type_label(type));
2866 #endif
2867 } else
2868 type = l1->type;
2869 } else {
2870 /* RDQL rules: compare as values with no promotion */
2871 if(l1->type != l2->type) {
2872 /* booleans can be compared to strings */
2873 if(l2->type == RASQAL_LITERAL_BOOLEAN &&
2874 l1->type == RASQAL_LITERAL_STRING)
2875 result = !strcmp(RASQAL_GOOD_CAST(const char*, l1->string),
2876 RASQAL_GOOD_CAST(const char*, l2->string));
2877 goto tidy;
2878 }
2879 type = l1->type;
2880 }
2881
2882 if(promotion) {
2883 l1_p = rasqal_new_literal_from_promotion(l1, type, flags);
2884 if(l1_p)
2885 l2_p = rasqal_new_literal_from_promotion(l2, type, flags);
2886 if(!l1_p || !l2_p) {
2887 result = 1;
2888 goto tidy;
2889 }
2890 } else {
2891 l1_p = l1;
2892 l2_p = l2;
2893 }
2894
2895 switch(type) {
2896 case RASQAL_LITERAL_URI:
2897 result = rasqal_literal_uri_equals(l1_p, l2_p);
2898 break;
2899
2900 case RASQAL_LITERAL_STRING:
2901 case RASQAL_LITERAL_XSD_STRING:
2902 case RASQAL_LITERAL_UDT:
2903 result = rasqal_literal_string_equals_flags(l1_p, l2_p, flags, error_p);
2904 break;
2905
2906 case RASQAL_LITERAL_BLANK:
2907 result = rasqal_literal_blank_equals(l1_p, l2_p);
2908 break;
2909
2910 case RASQAL_LITERAL_DATE:
2911 result = rasqal_xsd_date_equals(l1_p->value.date, l2_p->value.date,
2912 error_p);
2913 break;
2914
2915 case RASQAL_LITERAL_DATETIME:
2916 result = rasqal_xsd_datetime_equals2(l1_p->value.datetime,
2917 l2_p->value.datetime,
2918 error_p);
2919 break;
2920
2921 case RASQAL_LITERAL_INTEGER:
2922 case RASQAL_LITERAL_BOOLEAN:
2923 case RASQAL_LITERAL_INTEGER_SUBTYPE:
2924 result = l1_p->value.integer == l2_p->value.integer;
2925 break;
2926
2927
2928 case RASQAL_LITERAL_DOUBLE:
2929 case RASQAL_LITERAL_FLOAT:
2930 result = rasqal_double_approximately_equal(l1_p->value.floating,
2931 l2_p->value.floating);
2932 break;
2933
2934
2935 case RASQAL_LITERAL_DECIMAL:
2936 result = rasqal_xsd_decimal_equals(l1_p->value.decimal,
2937 l2_p->value.decimal);
2938 break;
2939
2940 case RASQAL_LITERAL_VARIABLE:
2941 /* both are variables */
2942 result = rasqal_literal_equals(l1_p->value.variable->value,
2943 l2_p->value.variable->value);
2944 break;
2945
2946 case RASQAL_LITERAL_UNKNOWN:
2947 case RASQAL_LITERAL_PATTERN:
2948 case RASQAL_LITERAL_QNAME:
2949 default:
2950 if(error_p)
2951 *error_p = 1;
2952 result = 0; /* keep some compilers happy */
2953 }
2954
2955 tidy:
2956 if(promotion) {
2957 if(l1_p)
2958 rasqal_free_literal(l1_p);
2959 if(l2_p)
2960 rasqal_free_literal(l2_p);
2961 }
2962
2963 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2964 RASQAL_DEBUG2("equals result %d\n", result);
2965 #endif
2966
2967 return result;
2968 }
2969
2970
2971 /*
2972 * rasqal_literal_expand_qname:
2973 * @user_data: #rasqal_query cast as void for use with raptor_sequence_foreach
2974 * @l: #rasqal_literal literal
2975 *
2976 * INTERNAL - Expand any qname in a literal into a URI
2977 *
2978 * Expands any QName inside the literal using prefixes that are
2979 * declared in the query that may not have been present when the
2980 * literal was first declared. Intended to be used standalone
2981 * as well as with raptor_sequence_foreach which takes a function
2982 * signature that this function matches.
2983 *
2984 * Return value: non-0 on failure
2985 **/
2986 int
rasqal_literal_expand_qname(void * user_data,rasqal_literal * l)2987 rasqal_literal_expand_qname(void *user_data, rasqal_literal *l)
2988 {
2989 rasqal_query *rq = (rasqal_query *)user_data;
2990
2991 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 1);
2992
2993 if(l->type == RASQAL_LITERAL_QNAME) {
2994 raptor_uri *uri;
2995
2996 /* expand a literal qname */
2997 uri = raptor_qname_string_to_uri(rq->namespaces,
2998 l->string, l->string_len);
2999 if(!uri)
3000 return 1;
3001 RASQAL_FREE(char*, l->string);
3002 l->string = NULL;
3003 l->type = RASQAL_LITERAL_URI;
3004 l->value.uri = uri;
3005 } else if (l->type == RASQAL_LITERAL_STRING) {
3006 raptor_uri *uri;
3007
3008 if(l->flags) {
3009 /* expand a literal string datatype qname */
3010 uri = raptor_qname_string_to_uri(rq->namespaces,
3011 l->flags,
3012 strlen(RASQAL_GOOD_CAST(const char*, l->flags)));
3013 if(!uri)
3014 return 1;
3015 l->datatype = uri;
3016 RASQAL_FREE(char*, l->flags);
3017 l->flags = NULL;
3018
3019 if(l->language && uri) {
3020 RASQAL_FREE(char*, l->language);
3021 l->language = NULL;
3022 }
3023
3024 if(rasqal_literal_string_to_native(l, 0)) {
3025 rasqal_free_literal(l);
3026 return 1;
3027 }
3028 }
3029 }
3030 return 0;
3031 }
3032
3033
3034 /*
3035 * rasqal_literal_has_qname
3036 * @l: #rasqal_literal literal
3037 *
3038 * INTERNAL - Check if literal has a qname part
3039 *
3040 * Checks if any part ofthe literal has an unexpanded QName.
3041 *
3042 * Return value: non-0 if a QName is present
3043 **/
3044 int
rasqal_literal_has_qname(rasqal_literal * l)3045 rasqal_literal_has_qname(rasqal_literal *l)
3046 {
3047 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 0);
3048
3049 return (l->type == RASQAL_LITERAL_QNAME) ||
3050 (l->type == RASQAL_LITERAL_STRING && (l->flags));
3051 }
3052
3053
3054 /**
3055 * rasqal_literal_as_node:
3056 * @l: #rasqal_literal object
3057 *
3058 * Turn a literal into a new RDF string, URI or blank literal.
3059 *
3060 * Return value: the new #rasqal_literal or NULL on failure or if the literal was an unbound variable.
3061 **/
3062 rasqal_literal*
rasqal_literal_as_node(rasqal_literal * l)3063 rasqal_literal_as_node(rasqal_literal* l)
3064 {
3065 raptor_uri* dt_uri;
3066 rasqal_literal* new_l = NULL;
3067
3068 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3069
3070 reswitch:
3071 switch(l->type) {
3072 case RASQAL_LITERAL_URI:
3073 case RASQAL_LITERAL_STRING:
3074 case RASQAL_LITERAL_BLANK:
3075 new_l = rasqal_new_literal_from_literal(l);
3076 break;
3077
3078 case RASQAL_LITERAL_VARIABLE:
3079 l = l->value.variable->value;
3080 if(!l)
3081 return NULL;
3082 goto reswitch;
3083
3084 case RASQAL_LITERAL_DOUBLE:
3085 case RASQAL_LITERAL_FLOAT:
3086 case RASQAL_LITERAL_INTEGER:
3087 case RASQAL_LITERAL_XSD_STRING:
3088 case RASQAL_LITERAL_BOOLEAN:
3089 case RASQAL_LITERAL_DECIMAL:
3090 case RASQAL_LITERAL_DATE:
3091 case RASQAL_LITERAL_DATETIME:
3092 case RASQAL_LITERAL_UDT:
3093 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3094 new_l = RASQAL_CALLOC(rasqal_literal*, 1, sizeof(*new_l));
3095 if(new_l) {
3096 new_l->valid = 1;
3097 new_l->usage = 1;
3098 new_l->world = l->world;
3099 new_l->type = RASQAL_LITERAL_STRING;
3100 new_l->string_len = l->string_len;
3101 new_l->string = RASQAL_MALLOC(unsigned char*, l->string_len + 1);
3102 if(!new_l->string) {
3103 rasqal_free_literal(new_l);
3104 return NULL;
3105 }
3106 memcpy((void*)new_l->string, l->string, l->string_len + 1);
3107
3108 if(l->type <= RASQAL_LITERAL_LAST_XSD) {
3109 dt_uri = rasqal_xsd_datatype_type_to_uri(l->world, l->type);
3110 if(!dt_uri) {
3111 rasqal_free_literal(new_l);
3112 return NULL;
3113 }
3114 } else {
3115 /* from the case: above this is UDT and INTEGER_SUBTYPE */
3116 dt_uri = l->datatype;
3117 }
3118 new_l->datatype = raptor_uri_copy(dt_uri);
3119 new_l->flags = NULL;
3120 }
3121 break;
3122
3123 case RASQAL_LITERAL_QNAME:
3124 /* QNames should be gone by the time expression eval happens */
3125
3126 case RASQAL_LITERAL_PATTERN:
3127 /* FALLTHROUGH */
3128
3129 case RASQAL_LITERAL_UNKNOWN:
3130 default:
3131 RASQAL_FATAL2("Literal type %u has no node value", l->type);
3132 }
3133
3134 return new_l;
3135 }
3136
3137
3138 /*
3139 * rasqal_literal_ebv:
3140 * @l: #rasqal_literal literal
3141 *
3142 * INTERNAL - Get the rasqal_literal effective boolean value
3143 *
3144 * Return value: non-0 if EBV is true, else false
3145 **/
3146 int
rasqal_literal_ebv(rasqal_literal * l)3147 rasqal_literal_ebv(rasqal_literal* l)
3148 {
3149 rasqal_variable* v;
3150 /* Result is true unless... */
3151 int b = 1;
3152
3153 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 0);
3154
3155 v = rasqal_literal_as_variable(l);
3156 if(v) {
3157 if(v->value == NULL) {
3158 /* ... The operand is unbound */
3159 b = 0;
3160 goto done;
3161 }
3162 l = v->value;
3163 }
3164
3165 if(l->type == RASQAL_LITERAL_BOOLEAN && !l->value.integer) {
3166 /* ... The operand is an xs:boolean with a FALSE value. */
3167 b = 0;
3168 } else if(l->type == RASQAL_LITERAL_STRING &&
3169 !l->datatype && !l->string_len) {
3170 /* ... The operand is a 0-length untyped RDF literal or xs:string. */
3171 b = 0;
3172 } else if(((l->type == RASQAL_LITERAL_INTEGER || l->type == RASQAL_LITERAL_INTEGER_SUBTYPE) && !l->value.integer) ||
3173 ((l->type == RASQAL_LITERAL_DOUBLE ||
3174 l->type == RASQAL_LITERAL_FLOAT) &&
3175 !RASQAL_FLOATING_AS_INT(l->value.floating))
3176 ) {
3177 /* ... The operand is any numeric type with a value of 0. */
3178 b = 0;
3179 } else if(l->type == RASQAL_LITERAL_DECIMAL &&
3180 rasqal_xsd_decimal_is_zero(l->value.decimal)) {
3181 /* ... The operand is any numeric type with a value of 0 (decimal) */
3182 b = 0;
3183 } else if((l->type == RASQAL_LITERAL_DOUBLE ||
3184 l->type == RASQAL_LITERAL_FLOAT) &&
3185 isnan(l->value.floating)
3186 ) {
3187 /* ... The operand is an xs:double or xs:float with a value of NaN */
3188 b = 0;
3189 }
3190
3191 done:
3192 return b;
3193 }
3194
3195
3196 /*
3197 * rasqal_literal_is_constant:
3198 * @l: #rasqal_literal literal
3199 *
3200 * INTERNAL - Check if a literal is a constant
3201 *
3202 * Return value: non-0 if literal is a constant
3203 **/
3204 int
rasqal_literal_is_constant(rasqal_literal * l)3205 rasqal_literal_is_constant(rasqal_literal* l)
3206 {
3207 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 0);
3208
3209 switch(l->type) {
3210 case RASQAL_LITERAL_URI:
3211 case RASQAL_LITERAL_BLANK:
3212 case RASQAL_LITERAL_STRING:
3213 case RASQAL_LITERAL_PATTERN:
3214 case RASQAL_LITERAL_QNAME:
3215 case RASQAL_LITERAL_INTEGER:
3216 case RASQAL_LITERAL_XSD_STRING:
3217 case RASQAL_LITERAL_BOOLEAN:
3218 case RASQAL_LITERAL_DOUBLE:
3219 case RASQAL_LITERAL_FLOAT:
3220 case RASQAL_LITERAL_DECIMAL:
3221 case RASQAL_LITERAL_DATE:
3222 case RASQAL_LITERAL_DATETIME:
3223 case RASQAL_LITERAL_UDT:
3224 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3225 return 1;
3226
3227 case RASQAL_LITERAL_VARIABLE:
3228 return 0;
3229
3230 case RASQAL_LITERAL_UNKNOWN:
3231 default:
3232 RASQAL_FATAL2("Literal type %u cannot be checked for constant", l->type);
3233 return 0; /* keep some compilers happy */
3234 }
3235 }
3236
3237
3238 /**
3239 * rasqal_literal_datatype:
3240 * @l: #rasqal_literal object
3241 *
3242 * Get the datatype URI of a literal
3243 *
3244 * Return value: shared pointer to #raptor_uri of datatype or NULL on failure or no value
3245 */
3246 raptor_uri*
rasqal_literal_datatype(rasqal_literal * l)3247 rasqal_literal_datatype(rasqal_literal* l)
3248 {
3249 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3250
3251 if(l->type != RASQAL_LITERAL_VARIABLE)
3252 return l->datatype;
3253 return rasqal_literal_datatype(l->value.variable->value);
3254 }
3255
3256
3257 rasqal_literal*
rasqal_literal_cast(rasqal_literal * l,raptor_uri * to_datatype,int flags,int * error_p)3258 rasqal_literal_cast(rasqal_literal* l, raptor_uri* to_datatype, int flags,
3259 int* error_p)
3260 {
3261 #ifdef RASQAL_DEBUG
3262 raptor_uri* from_datatype = NULL;
3263 #endif
3264 const unsigned char *string = NULL;
3265 unsigned char *new_string;
3266 rasqal_literal* result = NULL;
3267 rasqal_literal_type from_native_type;
3268 rasqal_literal_type to_native_type;
3269 size_t len;
3270
3271 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3272
3273 l = rasqal_literal_value(l);
3274 if(!l)
3275 return NULL;
3276
3277 #ifdef RASQAL_DEBUG
3278 from_datatype = l->datatype;
3279 #endif
3280 from_native_type = l->type;
3281
3282 to_native_type = rasqal_xsd_datatype_uri_to_type(l->world, to_datatype);
3283
3284 if(from_native_type == to_native_type) {
3285 /* cast to same type is always allowed */
3286 return rasqal_new_literal_from_literal(l);
3287
3288 } else {
3289 int failed = 0;
3290
3291 /* switch on FROM type to check YES/NO conversions and get the string */
3292 switch(from_native_type) {
3293 /* string */
3294 case RASQAL_LITERAL_STRING:
3295 case RASQAL_LITERAL_XSD_STRING:
3296 case RASQAL_LITERAL_UDT:
3297 string = l->string;
3298 len = l->string_len;
3299 break;
3300
3301 /* XSD datatypes: RASQAL_LITERAL_FIRST_XSD to RASQAL_LITERAL_LAST_XSD */
3302 case RASQAL_LITERAL_BOOLEAN:
3303 case RASQAL_LITERAL_INTEGER:
3304 case RASQAL_LITERAL_DOUBLE:
3305 case RASQAL_LITERAL_FLOAT:
3306 case RASQAL_LITERAL_DECIMAL:
3307 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3308 /* XSD (boolean, integer, decimal, double, float) may NOT be
3309 * cast to dateTime or date */
3310 if(to_native_type == RASQAL_LITERAL_DATE ||
3311 to_native_type == RASQAL_LITERAL_DATETIME) {
3312 failed = 1;
3313 if(error_p)
3314 *error_p = 1;
3315 break;
3316 }
3317 string = l->string;
3318 len = l->string_len;
3319 break;
3320
3321 case RASQAL_LITERAL_DATE:
3322 case RASQAL_LITERAL_DATETIME:
3323 string = l->string;
3324 len = l->string_len;
3325 break;
3326
3327 /* SPARQL casts - FIXME */
3328 case RASQAL_LITERAL_BLANK:
3329 case RASQAL_LITERAL_PATTERN:
3330 case RASQAL_LITERAL_QNAME:
3331 string = l->string;
3332 len = l->string_len;
3333 break;
3334
3335 case RASQAL_LITERAL_URI:
3336 /* URI (IRI) May ONLY be cast to an xsd:string */
3337 if(to_native_type != RASQAL_LITERAL_XSD_STRING) {
3338 failed = 1;
3339 if(error_p)
3340 *error_p = 1;
3341 break;
3342 }
3343
3344 string = raptor_uri_as_counted_string(l->value.uri, &len);
3345 if(!string) {
3346 failed = 1;
3347 if(error_p)
3348 *error_p = 1;
3349 }
3350 break;
3351
3352 case RASQAL_LITERAL_VARIABLE:
3353 /* fallthrough since rasqal_literal_value() handled this above */
3354 case RASQAL_LITERAL_UNKNOWN:
3355 default:
3356 RASQAL_FATAL2("Literal type %u cannot be cast", l->type);
3357 failed = 1;
3358 return NULL; /* keep some compilers happy */
3359 }
3360
3361 if(to_native_type == RASQAL_LITERAL_DATE ||
3362 to_native_type == RASQAL_LITERAL_DATETIME) {
3363 /* XSD date and dateTime may ONLY be cast from string (cast
3364 * from dateTime is checked above)
3365 */
3366 if(from_native_type != RASQAL_LITERAL_STRING) {
3367 failed = 1;
3368 if(error_p)
3369 *error_p = 1;
3370 }
3371 }
3372
3373 if(failed)
3374 return NULL;
3375 }
3376
3377
3378 /* switch on the TO type to check MAYBE conversions */
3379
3380 RASQAL_DEBUG4("CAST from \"%s\" type %s to type %s\n",
3381 string,
3382 from_datatype ? RASQAL_GOOD_CAST(const char*, raptor_uri_as_string(from_datatype)) : "(NONE)",
3383 raptor_uri_as_string(to_datatype));
3384
3385 if(!rasqal_xsd_datatype_check(to_native_type, string, flags)) {
3386 if(error_p)
3387 *error_p = 1;
3388 RASQAL_DEBUG3("Illegal cast to type %s string '%s'",
3389 rasqal_xsd_datatype_label(to_native_type), string);
3390 return NULL;
3391 }
3392
3393 new_string = RASQAL_MALLOC(unsigned char*, len + 1);
3394 if(!new_string) {
3395 if(error_p)
3396 *error_p = 1;
3397 return NULL;
3398 }
3399 memcpy(new_string, string, len + 1);
3400 to_datatype = raptor_uri_copy(to_datatype);
3401
3402 result = rasqal_new_string_literal(l->world, new_string, NULL,
3403 to_datatype, NULL);
3404 if(!result) {
3405 if(error_p)
3406 *error_p = 1;
3407 }
3408 return result;
3409 }
3410
3411
3412 /**
3413 * rasqal_literal_value:
3414 * @l: #rasqal_literal object
3415 *
3416 * Get the literal value looking up any variables needed
3417 *
3418 * Return value: literal value or NULL if has no value
3419 */
3420 rasqal_literal*
rasqal_literal_value(rasqal_literal * l)3421 rasqal_literal_value(rasqal_literal* l)
3422 {
3423 if(!l)
3424 return NULL;
3425
3426 while(l && l->type == RASQAL_LITERAL_VARIABLE) {
3427 l = l->value.variable->value;
3428 }
3429
3430 return l;
3431 }
3432
3433
3434 int
rasqal_literal_is_numeric(rasqal_literal * literal)3435 rasqal_literal_is_numeric(rasqal_literal* literal)
3436 {
3437 rasqal_literal_type parent_type;
3438
3439 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(literal, rasqal_literal, 0);
3440
3441 parent_type = rasqal_xsd_datatype_parent_type(literal->type);
3442
3443 return (rasqal_xsd_datatype_is_numeric(literal->type) ||
3444 rasqal_xsd_datatype_is_numeric(parent_type));
3445 }
3446
3447
3448 rasqal_literal*
rasqal_literal_add(rasqal_literal * l1,rasqal_literal * l2,int * error_p)3449 rasqal_literal_add(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
3450 {
3451 int i;
3452 double d;
3453 rasqal_xsd_decimal* dec;
3454 int error = 0;
3455 rasqal_literal_type type;
3456 rasqal_literal* l1_p = NULL;
3457 rasqal_literal* l2_p = NULL;
3458 int flags = 0;
3459 rasqal_literal* result = NULL;
3460
3461 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, NULL);
3462 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, NULL);
3463
3464 type = rasqal_literal_promote_numerics(l1, l2, flags);
3465 switch(type) {
3466 case RASQAL_LITERAL_INTEGER:
3467 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3468 i = rasqal_literal_as_integer(l1, &error);
3469 if(error)
3470 break;
3471 i = i + rasqal_literal_as_integer(l2, &error);
3472 if(error)
3473 break;
3474
3475 result = rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
3476 break;
3477
3478 case RASQAL_LITERAL_FLOAT:
3479 case RASQAL_LITERAL_DOUBLE:
3480 d = rasqal_literal_as_double(l1, &error);
3481 if(error)
3482 break;
3483 d = d + rasqal_literal_as_double(l2, &error);
3484 if(error)
3485 break;
3486
3487 result = rasqal_new_numeric_literal(l1->world, type, d);
3488 break;
3489
3490 case RASQAL_LITERAL_DECIMAL:
3491 l1_p = rasqal_new_literal_from_promotion(l1, type, flags);
3492 if(l1_p)
3493 l2_p = rasqal_new_literal_from_promotion(l2, type, flags);
3494 if(l1_p && l2_p) {
3495 dec = rasqal_new_xsd_decimal(l1->world);
3496 if(rasqal_xsd_decimal_add(dec, l1_p->value.decimal,
3497 l2_p->value.decimal)) {
3498 error = 1;
3499 rasqal_free_xsd_decimal(dec);
3500 } else
3501 result = rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
3502 }
3503 break;
3504
3505 case RASQAL_LITERAL_UNKNOWN:
3506 case RASQAL_LITERAL_BLANK:
3507 case RASQAL_LITERAL_URI:
3508 case RASQAL_LITERAL_STRING:
3509 case RASQAL_LITERAL_XSD_STRING:
3510 case RASQAL_LITERAL_BOOLEAN:
3511 case RASQAL_LITERAL_DATE:
3512 case RASQAL_LITERAL_DATETIME:
3513 case RASQAL_LITERAL_PATTERN:
3514 case RASQAL_LITERAL_QNAME:
3515 case RASQAL_LITERAL_VARIABLE:
3516 case RASQAL_LITERAL_UDT:
3517 default:
3518 error = 1;
3519 break;
3520 }
3521
3522 if(error) {
3523 if(error_p)
3524 *error_p = 1;
3525 }
3526
3527 if(l1_p)
3528 rasqal_free_literal(l1_p);
3529 if(l2_p)
3530 rasqal_free_literal(l2_p);
3531
3532 return result;
3533 }
3534
3535
3536 rasqal_literal*
rasqal_literal_subtract(rasqal_literal * l1,rasqal_literal * l2,int * error_p)3537 rasqal_literal_subtract(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
3538 {
3539 int i;
3540 double d;
3541 rasqal_xsd_decimal* dec;
3542 int error = 0;
3543 rasqal_literal_type type;
3544 rasqal_literal* l1_p = NULL;
3545 rasqal_literal* l2_p = NULL;
3546 int flags = 0;
3547 rasqal_literal* result = NULL;
3548
3549 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, NULL);
3550 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, NULL);
3551
3552 type = rasqal_literal_promote_numerics(l1, l2, flags);
3553 switch(type) {
3554 case RASQAL_LITERAL_INTEGER:
3555 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3556 i = rasqal_literal_as_integer(l1, &error);
3557 if(error)
3558 break;
3559 i = i - rasqal_literal_as_integer(l2, &error);
3560 if(error)
3561 break;
3562
3563 result = rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
3564 break;
3565
3566 case RASQAL_LITERAL_FLOAT:
3567 case RASQAL_LITERAL_DOUBLE:
3568 d = rasqal_literal_as_double(l1, &error);
3569 if(error)
3570 break;
3571 d = d - rasqal_literal_as_double(l2, &error);
3572 if(error)
3573 break;
3574
3575 result = rasqal_new_numeric_literal(l1->world, type, d);
3576 break;
3577
3578 case RASQAL_LITERAL_DECIMAL:
3579 l1_p = rasqal_new_literal_from_promotion(l1, type, flags);
3580 if(l1_p)
3581 l2_p = rasqal_new_literal_from_promotion(l2, type, flags);
3582 if(l1_p && l2_p) {
3583 dec = rasqal_new_xsd_decimal(l1->world);
3584 if(rasqal_xsd_decimal_subtract(dec, l1_p->value.decimal,
3585 l2_p->value.decimal)) {
3586 error = 1;
3587 rasqal_free_xsd_decimal(dec);
3588 } else
3589 result = rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
3590 }
3591 break;
3592
3593 case RASQAL_LITERAL_UNKNOWN:
3594 case RASQAL_LITERAL_BLANK:
3595 case RASQAL_LITERAL_URI:
3596 case RASQAL_LITERAL_STRING:
3597 case RASQAL_LITERAL_XSD_STRING:
3598 case RASQAL_LITERAL_BOOLEAN:
3599 case RASQAL_LITERAL_DATE:
3600 case RASQAL_LITERAL_DATETIME:
3601 case RASQAL_LITERAL_PATTERN:
3602 case RASQAL_LITERAL_QNAME:
3603 case RASQAL_LITERAL_VARIABLE:
3604 case RASQAL_LITERAL_UDT:
3605 default:
3606 error = 1;
3607 break;
3608 }
3609
3610 if(error) {
3611 if(error_p)
3612 *error_p = 1;
3613 }
3614
3615 if(l1_p)
3616 rasqal_free_literal(l1_p);
3617 if(l2_p)
3618 rasqal_free_literal(l2_p);
3619
3620 return result;
3621 }
3622
3623
3624 rasqal_literal*
rasqal_literal_multiply(rasqal_literal * l1,rasqal_literal * l2,int * error_p)3625 rasqal_literal_multiply(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
3626 {
3627 int i;
3628 double d;
3629 rasqal_xsd_decimal* dec;
3630 int error = 0;
3631 rasqal_literal_type type;
3632 rasqal_literal* l1_p = NULL;
3633 rasqal_literal* l2_p = NULL;
3634 int flags = 0;
3635 rasqal_literal* result = NULL;
3636
3637 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, NULL);
3638 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, NULL);
3639
3640 type = rasqal_literal_promote_numerics(l1, l2, flags);
3641 switch(type) {
3642 case RASQAL_LITERAL_INTEGER:
3643 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3644 i = rasqal_literal_as_integer(l1, &error);
3645 if(error)
3646 break;
3647 i = i * rasqal_literal_as_integer(l2, &error);
3648 if(error)
3649 break;
3650
3651 result = rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
3652 break;
3653
3654 case RASQAL_LITERAL_FLOAT:
3655 case RASQAL_LITERAL_DOUBLE:
3656 d = rasqal_literal_as_double(l1, &error);
3657 if(error)
3658 break;
3659 d = d * rasqal_literal_as_double(l2, &error);
3660 if(error)
3661 break;
3662
3663 result = rasqal_new_numeric_literal(l1->world, type, d);
3664 break;
3665
3666 case RASQAL_LITERAL_DECIMAL:
3667 l1_p = rasqal_new_literal_from_promotion(l1, type, flags);
3668 if(l1_p)
3669 l2_p = rasqal_new_literal_from_promotion(l2, type, flags);
3670 if(l1_p && l2_p) {
3671 dec = rasqal_new_xsd_decimal(l1->world);
3672 if(rasqal_xsd_decimal_multiply(dec, l1_p->value.decimal,
3673 l2_p->value.decimal)) {
3674 error = 1;
3675 rasqal_free_xsd_decimal(dec);
3676 } else
3677 result = rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
3678 }
3679 break;
3680
3681 case RASQAL_LITERAL_UNKNOWN:
3682 case RASQAL_LITERAL_BLANK:
3683 case RASQAL_LITERAL_URI:
3684 case RASQAL_LITERAL_STRING:
3685 case RASQAL_LITERAL_XSD_STRING:
3686 case RASQAL_LITERAL_BOOLEAN:
3687 case RASQAL_LITERAL_DATE:
3688 case RASQAL_LITERAL_DATETIME:
3689 case RASQAL_LITERAL_PATTERN:
3690 case RASQAL_LITERAL_QNAME:
3691 case RASQAL_LITERAL_VARIABLE:
3692 case RASQAL_LITERAL_UDT:
3693 default:
3694 error = 1;
3695 break;
3696 }
3697
3698 if(error) {
3699 if(error_p)
3700 *error_p = 1;
3701 }
3702
3703 if(l1_p)
3704 rasqal_free_literal(l1_p);
3705 if(l2_p)
3706 rasqal_free_literal(l2_p);
3707
3708 return result;
3709 }
3710
3711
3712 rasqal_literal*
rasqal_literal_divide(rasqal_literal * l1,rasqal_literal * l2,int * error_p)3713 rasqal_literal_divide(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
3714 {
3715 double d1, d2;
3716 rasqal_xsd_decimal* dec;
3717 int error = 0;
3718 rasqal_literal_type type;
3719 rasqal_literal* l1_p = NULL;
3720 rasqal_literal* l2_p = NULL;
3721 int flags = 0;
3722 rasqal_literal* result = NULL;
3723
3724 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, NULL);
3725 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, NULL);
3726
3727 type = rasqal_literal_promote_numerics(l1, l2, flags);
3728 switch(type) {
3729 case RASQAL_LITERAL_FLOAT:
3730 case RASQAL_LITERAL_DOUBLE:
3731 d2 = rasqal_literal_as_double(l2, &error);
3732 if(!RASQAL_FLOATING_AS_INT(d2))
3733 /* division by zero error */
3734 error = 1;
3735 if(error)
3736 break;
3737 d1 = rasqal_literal_as_double(l1, &error);
3738 if(error)
3739 break;
3740 d1 = d1 / d2;
3741
3742 result = rasqal_new_numeric_literal(l1->world, type, d1);
3743 break;
3744
3745 case RASQAL_LITERAL_INTEGER:
3746 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3747 /* "As a special case, if the types of both $arg1 and $arg2 are
3748 * xs:integer, then the return type is xs:decimal." - F&O
3749 */
3750 type = RASQAL_LITERAL_DECIMAL;
3751 /* fallthrough */
3752
3753 case RASQAL_LITERAL_DECIMAL:
3754 l1_p = rasqal_new_literal_from_promotion(l1, type, flags);
3755 if(l1_p)
3756 l2_p = rasqal_new_literal_from_promotion(l2, type, flags);
3757 if(l1_p && l2_p) {
3758 dec = rasqal_new_xsd_decimal(l1->world);
3759 if(rasqal_xsd_decimal_divide(dec, l1_p->value.decimal,
3760 l2_p->value.decimal)) {
3761 error = 1;
3762 rasqal_free_xsd_decimal(dec);
3763 } else
3764 result = rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
3765 }
3766 break;
3767
3768 case RASQAL_LITERAL_UNKNOWN:
3769 case RASQAL_LITERAL_BLANK:
3770 case RASQAL_LITERAL_URI:
3771 case RASQAL_LITERAL_STRING:
3772 case RASQAL_LITERAL_XSD_STRING:
3773 case RASQAL_LITERAL_BOOLEAN:
3774 case RASQAL_LITERAL_DATE:
3775 case RASQAL_LITERAL_DATETIME:
3776 case RASQAL_LITERAL_PATTERN:
3777 case RASQAL_LITERAL_QNAME:
3778 case RASQAL_LITERAL_VARIABLE:
3779 case RASQAL_LITERAL_UDT:
3780 default:
3781 error = 1;
3782 break;
3783 }
3784
3785 if(error) {
3786 if(error_p)
3787 *error_p = 1;
3788 }
3789
3790 if(l1_p)
3791 rasqal_free_literal(l1_p);
3792 if(l2_p)
3793 rasqal_free_literal(l2_p);
3794
3795 return result;
3796 }
3797
3798
3799 rasqal_literal*
rasqal_literal_negate(rasqal_literal * l,int * error_p)3800 rasqal_literal_negate(rasqal_literal* l, int *error_p)
3801 {
3802 int i;
3803 double d;
3804 rasqal_xsd_decimal* dec;
3805 int error = 0;
3806 rasqal_literal* result = NULL;
3807
3808 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3809
3810 switch(l->type) {
3811 case RASQAL_LITERAL_INTEGER:
3812 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3813 i = rasqal_literal_as_integer(l, &error);
3814 if(error)
3815 break;
3816 i = -i;
3817 result = rasqal_new_integer_literal(l->world, RASQAL_LITERAL_INTEGER, i);
3818 break;
3819
3820 case RASQAL_LITERAL_FLOAT:
3821 case RASQAL_LITERAL_DOUBLE:
3822 d = rasqal_literal_as_double(l, &error);
3823 if(!RASQAL_FLOATING_AS_INT(d))
3824 error = 1;
3825 d = -d;
3826 result = rasqal_new_numeric_literal(l->world, l->type, d);
3827 break;
3828
3829 case RASQAL_LITERAL_DECIMAL:
3830 dec = rasqal_new_xsd_decimal(l->world);
3831 if(rasqal_xsd_decimal_negate(dec, l->value.decimal)) {
3832 error = 1;
3833 rasqal_free_xsd_decimal(dec);
3834 } else
3835 result = rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
3836 break;
3837
3838 case RASQAL_LITERAL_UNKNOWN:
3839 case RASQAL_LITERAL_BLANK:
3840 case RASQAL_LITERAL_URI:
3841 case RASQAL_LITERAL_STRING:
3842 case RASQAL_LITERAL_XSD_STRING:
3843 case RASQAL_LITERAL_BOOLEAN:
3844 case RASQAL_LITERAL_DATE:
3845 case RASQAL_LITERAL_DATETIME:
3846 case RASQAL_LITERAL_PATTERN:
3847 case RASQAL_LITERAL_QNAME:
3848 case RASQAL_LITERAL_VARIABLE:
3849 case RASQAL_LITERAL_UDT:
3850 default:
3851 error = 1;
3852 break;
3853 }
3854
3855 if(error) {
3856 if(error_p)
3857 *error_p = 1;
3858 }
3859
3860 return result;
3861 }
3862
3863
3864 rasqal_literal*
rasqal_literal_abs(rasqal_literal * l,int * error_p)3865 rasqal_literal_abs(rasqal_literal* l, int *error_p)
3866 {
3867 int i;
3868 double d;
3869 rasqal_xsd_decimal* dec;
3870 int error = 0;
3871 rasqal_literal* result = NULL;
3872
3873 if(!rasqal_literal_is_numeric(l))
3874 return NULL;
3875
3876 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3877
3878 switch(l->type) {
3879 case RASQAL_LITERAL_INTEGER:
3880 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3881 i = rasqal_literal_as_integer(l, &error);
3882 if(error)
3883 break;
3884
3885 i = abs(i);
3886 result = rasqal_new_integer_literal(l->world, RASQAL_LITERAL_INTEGER, i);
3887 break;
3888
3889 case RASQAL_LITERAL_FLOAT:
3890 case RASQAL_LITERAL_DOUBLE:
3891 d = rasqal_literal_as_double(l, &error);
3892 if(!RASQAL_FLOATING_AS_INT(d))
3893 error = 1;
3894
3895 d = fabs(d);
3896 result = rasqal_new_numeric_literal(l->world, l->type, d);
3897 break;
3898
3899 case RASQAL_LITERAL_DECIMAL:
3900 dec = rasqal_new_xsd_decimal(l->world);
3901 if(rasqal_xsd_decimal_abs(dec, l->value.decimal)) {
3902 error = 1;
3903 rasqal_free_xsd_decimal(dec);
3904 } else
3905 result = rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
3906 break;
3907
3908 case RASQAL_LITERAL_UNKNOWN:
3909 case RASQAL_LITERAL_BLANK:
3910 case RASQAL_LITERAL_URI:
3911 case RASQAL_LITERAL_STRING:
3912 case RASQAL_LITERAL_XSD_STRING:
3913 case RASQAL_LITERAL_BOOLEAN:
3914 case RASQAL_LITERAL_DATE:
3915 case RASQAL_LITERAL_DATETIME:
3916 case RASQAL_LITERAL_PATTERN:
3917 case RASQAL_LITERAL_QNAME:
3918 case RASQAL_LITERAL_VARIABLE:
3919 case RASQAL_LITERAL_UDT:
3920 default:
3921 error = 1;
3922 break;
3923 }
3924
3925 if(error) {
3926 if(error_p)
3927 *error_p = 1;
3928 }
3929
3930 return result;
3931 }
3932
3933
3934 rasqal_literal*
rasqal_literal_round(rasqal_literal * l,int * error_p)3935 rasqal_literal_round(rasqal_literal* l, int *error_p)
3936 {
3937 double d;
3938 rasqal_xsd_decimal* dec;
3939 int error = 0;
3940 rasqal_literal* result = NULL;
3941
3942 if(!rasqal_literal_is_numeric(l))
3943 return NULL;
3944
3945 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
3946
3947 switch(l->type) {
3948 case RASQAL_LITERAL_INTEGER:
3949 case RASQAL_LITERAL_INTEGER_SUBTYPE:
3950 /* Result is same as input for integral types */
3951 result = rasqal_new_literal_from_literal(l);
3952 break;
3953
3954 case RASQAL_LITERAL_FLOAT:
3955 case RASQAL_LITERAL_DOUBLE:
3956 d = rasqal_literal_as_double(l, &error);
3957 if(!RASQAL_FLOATING_AS_INT(d))
3958 error = 1;
3959
3960 d = round(d);
3961 result = rasqal_new_numeric_literal(l->world, l->type, d);
3962 break;
3963
3964 case RASQAL_LITERAL_DECIMAL:
3965 dec = rasqal_new_xsd_decimal(l->world);
3966 if(rasqal_xsd_decimal_round(dec, l->value.decimal)) {
3967 error = 1;
3968 rasqal_free_xsd_decimal(dec);
3969 } else
3970 result = rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
3971 break;
3972
3973 case RASQAL_LITERAL_UNKNOWN:
3974 case RASQAL_LITERAL_BLANK:
3975 case RASQAL_LITERAL_URI:
3976 case RASQAL_LITERAL_STRING:
3977 case RASQAL_LITERAL_XSD_STRING:
3978 case RASQAL_LITERAL_BOOLEAN:
3979 case RASQAL_LITERAL_DATE:
3980 case RASQAL_LITERAL_DATETIME:
3981 case RASQAL_LITERAL_PATTERN:
3982 case RASQAL_LITERAL_QNAME:
3983 case RASQAL_LITERAL_VARIABLE:
3984 case RASQAL_LITERAL_UDT:
3985 default:
3986 error = 1;
3987 break;
3988 }
3989
3990 if(error) {
3991 if(error_p)
3992 *error_p = 1;
3993 }
3994
3995 return result;
3996 }
3997
3998
3999 rasqal_literal*
rasqal_literal_ceil(rasqal_literal * l,int * error_p)4000 rasqal_literal_ceil(rasqal_literal* l, int *error_p)
4001 {
4002 double d;
4003 rasqal_xsd_decimal* dec;
4004 int error = 0;
4005 rasqal_literal* result = NULL;
4006
4007 if(!rasqal_literal_is_numeric(l))
4008 return NULL;
4009
4010 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
4011
4012 switch(l->type) {
4013 case RASQAL_LITERAL_INTEGER:
4014 case RASQAL_LITERAL_INTEGER_SUBTYPE:
4015 /* Result is same as input for integral types */
4016 result = rasqal_new_literal_from_literal(l);
4017 break;
4018
4019 case RASQAL_LITERAL_FLOAT:
4020 case RASQAL_LITERAL_DOUBLE:
4021 d = rasqal_literal_as_double(l, &error);
4022 if(!RASQAL_FLOATING_AS_INT(d))
4023 error = 1;
4024
4025 d = ceil(d);
4026 result = rasqal_new_numeric_literal(l->world, l->type, d);
4027 break;
4028
4029 case RASQAL_LITERAL_DECIMAL:
4030 dec = rasqal_new_xsd_decimal(l->world);
4031 if(rasqal_xsd_decimal_ceil(dec, l->value.decimal)) {
4032 error = 1;
4033 rasqal_free_xsd_decimal(dec);
4034 } else
4035 result = rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
4036 break;
4037
4038 case RASQAL_LITERAL_UNKNOWN:
4039 case RASQAL_LITERAL_BLANK:
4040 case RASQAL_LITERAL_URI:
4041 case RASQAL_LITERAL_STRING:
4042 case RASQAL_LITERAL_XSD_STRING:
4043 case RASQAL_LITERAL_BOOLEAN:
4044 case RASQAL_LITERAL_DATE:
4045 case RASQAL_LITERAL_DATETIME:
4046 case RASQAL_LITERAL_PATTERN:
4047 case RASQAL_LITERAL_QNAME:
4048 case RASQAL_LITERAL_VARIABLE:
4049 case RASQAL_LITERAL_UDT:
4050 default:
4051 error = 1;
4052 break;
4053 }
4054
4055 if(error) {
4056 if(error_p)
4057 *error_p = 1;
4058 }
4059
4060 return result;
4061 }
4062
4063
4064 rasqal_literal*
rasqal_literal_floor(rasqal_literal * l,int * error_p)4065 rasqal_literal_floor(rasqal_literal* l, int *error_p)
4066 {
4067 double d;
4068 rasqal_xsd_decimal* dec;
4069 int error = 0;
4070 rasqal_literal* result = NULL;
4071
4072 if(!rasqal_literal_is_numeric(l))
4073 return NULL;
4074
4075 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, NULL);
4076
4077 switch(l->type) {
4078 case RASQAL_LITERAL_INTEGER:
4079 case RASQAL_LITERAL_INTEGER_SUBTYPE:
4080 /* Result is same as input for integral types */
4081 result = rasqal_new_literal_from_literal(l);
4082 break;
4083
4084 case RASQAL_LITERAL_FLOAT:
4085 case RASQAL_LITERAL_DOUBLE:
4086 d = rasqal_literal_as_double(l, &error);
4087 if(!RASQAL_FLOATING_AS_INT(d))
4088 error = 1;
4089
4090 d = floor(d);
4091 result = rasqal_new_numeric_literal(l->world, l->type, d);
4092 break;
4093
4094 case RASQAL_LITERAL_DECIMAL:
4095 dec = rasqal_new_xsd_decimal(l->world);
4096 if(rasqal_xsd_decimal_floor(dec, l->value.decimal)) {
4097 error = 1;
4098 rasqal_free_xsd_decimal(dec);
4099 } else
4100 result = rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
4101 break;
4102
4103 case RASQAL_LITERAL_UNKNOWN:
4104 case RASQAL_LITERAL_BLANK:
4105 case RASQAL_LITERAL_URI:
4106 case RASQAL_LITERAL_STRING:
4107 case RASQAL_LITERAL_XSD_STRING:
4108 case RASQAL_LITERAL_BOOLEAN:
4109 case RASQAL_LITERAL_DATE:
4110 case RASQAL_LITERAL_DATETIME:
4111 case RASQAL_LITERAL_PATTERN:
4112 case RASQAL_LITERAL_QNAME:
4113 case RASQAL_LITERAL_VARIABLE:
4114 case RASQAL_LITERAL_UDT:
4115 default:
4116 error = 1;
4117 break;
4118 }
4119
4120 if(error) {
4121 if(error_p)
4122 *error_p = 1;
4123 }
4124
4125 return result;
4126 }
4127
4128
4129 /**
4130 * rasqal_literal_same_term:
4131 * @l1: #rasqal_literal literal
4132 * @l2: #rasqal_literal data literal
4133 *
4134 * Check if literals are same term (URI, literal, blank)
4135 *
4136 * Return value: non-0 if same
4137 **/
4138 int
rasqal_literal_same_term(rasqal_literal * l1,rasqal_literal * l2)4139 rasqal_literal_same_term(rasqal_literal* l1, rasqal_literal* l2)
4140 {
4141 rasqal_literal_type type1;
4142 rasqal_literal_type type2;
4143
4144 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l1, rasqal_literal, 0);
4145 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l2, rasqal_literal, 0);
4146
4147 type1 = rasqal_literal_get_rdf_term_type(l1);
4148 type2 = rasqal_literal_get_rdf_term_type(l2);
4149
4150 if(type1 != type2)
4151 return 0;
4152
4153 if(type1 == RASQAL_LITERAL_UNKNOWN)
4154 return 0;
4155
4156 if(type1 == RASQAL_LITERAL_URI)
4157 return rasqal_literal_uri_equals(l1, l2);
4158
4159 if(type1 == RASQAL_LITERAL_STRING)
4160 /* value compare */
4161 return rasqal_literal_string_equals_flags(l1, l2, RASQAL_COMPARE_XQUERY,
4162 NULL);
4163
4164 if(type1 == RASQAL_LITERAL_BLANK)
4165 return rasqal_literal_blank_equals(l1, l2);
4166
4167 return 0;
4168 }
4169
4170
4171 /**
4172 * rasqal_literal_is_rdf_literal:
4173 * @l: #rasqal_literal literal
4174 *
4175 * Check if a literal is any RDF term literal - plain or typed literal
4176 *
4177 * Return value: non-0 if the value is an RDF term literal
4178 **/
4179 int
rasqal_literal_is_rdf_literal(rasqal_literal * l)4180 rasqal_literal_is_rdf_literal(rasqal_literal* l)
4181 {
4182 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(l, rasqal_literal, 0);
4183
4184 return (rasqal_literal_get_rdf_term_type(l) == RASQAL_LITERAL_STRING);
4185 }
4186
4187
4188 /**
4189 * rasqal_literal_sequence_compare:
4190 * @compare_flags: comparison flags for rasqal_literal_compare()
4191 * @values_a: first sequence of literals
4192 * @values_b: second sequence of literals
4193 *
4194 * INTERNAL - compare two sequences of literals
4195 *
4196 * Return value: <0, 0 or >1 comparison
4197 */
4198 int
rasqal_literal_sequence_compare(int compare_flags,raptor_sequence * values_a,raptor_sequence * values_b)4199 rasqal_literal_sequence_compare(int compare_flags,
4200 raptor_sequence* values_a,
4201 raptor_sequence* values_b)
4202 {
4203 int result = 0;
4204 int i;
4205 int size_a = 0;
4206 int size_b = 0;
4207
4208 /* Turn 0-length sequences into NULL */
4209 if(values_a) {
4210 size_a = raptor_sequence_size(values_a);
4211 if(!size_a)
4212 values_a = NULL;
4213 }
4214
4215 if(values_b) {
4216 size_b = raptor_sequence_size(values_b);
4217 if(!size_b)
4218 values_b = NULL;
4219 }
4220
4221 /* Handle empty sequences: equal if both empty, otherwise empty is earlier */
4222 if(!size_a && !size_b)
4223 return 0;
4224 else if(!size_a)
4225 return -1;
4226 else if(!size_b)
4227 return 1;
4228
4229
4230 /* Now know they are not 0 length */
4231
4232 /* Walk maximum length of the values */
4233 if(size_b > size_a)
4234 size_a = size_b;
4235
4236 for(i = 0; i < size_a; i++) {
4237 rasqal_literal* literal_a = (rasqal_literal*)raptor_sequence_get_at(values_a, i);
4238 rasqal_literal* literal_b = (rasqal_literal*)raptor_sequence_get_at(values_b, i);
4239 int error = 0;
4240
4241 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4242 RASQAL_DEBUG1("Comparing ");
4243 rasqal_literal_print(literal_a, DEBUG_FH);
4244 fputs(" to ", DEBUG_FH);
4245 rasqal_literal_print(literal_b, DEBUG_FH);
4246 fputs("\n", DEBUG_FH);
4247 #endif
4248
4249 if(!literal_a || !literal_b) {
4250 if(!literal_a && !literal_b) {
4251 result = 0;
4252 } else {
4253 result = literal_a ? 1 : -1;
4254 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4255 RASQAL_DEBUG2("Got one NULL literal comparison, returning %d\n",
4256 result);
4257 #endif
4258 }
4259 break;
4260 }
4261
4262 result = rasqal_literal_compare(literal_a, literal_b,
4263 compare_flags, &error);
4264
4265 if(error) {
4266 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4267 RASQAL_DEBUG2("Got literal comparison error at literal %d, returning 0\n",
4268 i);
4269 #endif
4270 result = 0;
4271 break;
4272 }
4273
4274 if(!result)
4275 continue;
4276
4277 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4278 RASQAL_DEBUG3("Returning comparison result %d at literal %d\n", result, i);
4279 #endif
4280 break;
4281 }
4282
4283 return result;
4284 }
4285
4286
4287 int
rasqal_literal_write_turtle(rasqal_literal * l,raptor_iostream * iostr)4288 rasqal_literal_write_turtle(rasqal_literal* l, raptor_iostream* iostr)
4289 {
4290 const unsigned char* str;
4291 size_t len;
4292 int rc = 0;
4293
4294 if(!l)
4295 return rc;
4296
4297 switch(l->type) {
4298 case RASQAL_LITERAL_URI:
4299 str = RASQAL_GOOD_CAST(const unsigned char*, raptor_uri_as_counted_string(l->value.uri, &len));
4300
4301 raptor_iostream_write_byte('<', iostr);
4302 if(str)
4303 raptor_string_ntriples_write(str, len, '>', iostr);
4304 raptor_iostream_write_byte('>', iostr);
4305 break;
4306
4307 case RASQAL_LITERAL_BLANK:
4308 raptor_iostream_counted_string_write("_:", 2, iostr);
4309 raptor_iostream_counted_string_write(l->string, l->string_len,
4310 iostr);
4311 break;
4312
4313 case RASQAL_LITERAL_STRING:
4314 case RASQAL_LITERAL_UDT:
4315 raptor_iostream_write_byte('"', iostr);
4316 raptor_string_ntriples_write(l->string, l->string_len, '"', iostr);
4317 raptor_iostream_write_byte('"', iostr);
4318
4319 if(l->language) {
4320 raptor_iostream_write_byte('@', iostr);
4321 raptor_iostream_string_write(l->language, iostr);
4322 }
4323
4324 if(l->datatype) {
4325 str = RASQAL_GOOD_CAST(const unsigned char*, raptor_uri_as_counted_string(l->datatype, &len));
4326 raptor_iostream_counted_string_write("^^<", 3, iostr);
4327 raptor_string_ntriples_write(str, len, '>', iostr);
4328 raptor_iostream_write_byte('>', iostr);
4329 }
4330
4331 break;
4332
4333 case RASQAL_LITERAL_PATTERN:
4334 case RASQAL_LITERAL_QNAME:
4335 case RASQAL_LITERAL_INTEGER:
4336 case RASQAL_LITERAL_XSD_STRING:
4337 case RASQAL_LITERAL_BOOLEAN:
4338 case RASQAL_LITERAL_DOUBLE:
4339 case RASQAL_LITERAL_FLOAT:
4340 case RASQAL_LITERAL_VARIABLE:
4341 case RASQAL_LITERAL_DECIMAL:
4342 case RASQAL_LITERAL_DATE:
4343 case RASQAL_LITERAL_DATETIME:
4344 case RASQAL_LITERAL_INTEGER_SUBTYPE:
4345
4346 case RASQAL_LITERAL_UNKNOWN:
4347 default:
4348 rasqal_log_error_simple(l->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
4349 "Cannot turn literal type %u into Turtle",
4350 l->type);
4351 rc = 1;
4352 }
4353
4354 return rc;
4355 }
4356
4357
4358 /*
4359 * rasqal_literal_array_compare:
4360 * @values_a: first array of literals
4361 * @values_b: second array of literals
4362 * @exprs_seq: array of expressions (or NULL)
4363 * @size: size of arrays
4364 * @compare_flags: comparison flags for rasqal_literal_compare()
4365 *
4366 * INTERNAL - compare two arrays of literals evaluated in an optional array of expressions
4367 *
4368 * Return value: <0, 0 or >0 comparison
4369 */
4370 int
rasqal_literal_array_compare(rasqal_literal ** values_a,rasqal_literal ** values_b,raptor_sequence * exprs_seq,int size,int compare_flags)4371 rasqal_literal_array_compare(rasqal_literal** values_a,
4372 rasqal_literal** values_b,
4373 raptor_sequence* exprs_seq,
4374 int size,
4375 int compare_flags)
4376 {
4377 int result = 0;
4378 int i;
4379
4380 for(i = 0; i < size; i++) {
4381 rasqal_expression* e = NULL;
4382 int error = 0;
4383 rasqal_literal* literal_a = values_a[i];
4384 rasqal_literal* literal_b = values_b[i];
4385
4386 if(exprs_seq)
4387 e = (rasqal_expression*)raptor_sequence_get_at(exprs_seq, i);
4388
4389 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4390 RASQAL_DEBUG1("Comparing ");
4391 rasqal_literal_print(literal_a, DEBUG_FH);
4392 fputs(" to ", DEBUG_FH);
4393 rasqal_literal_print(literal_b, DEBUG_FH);
4394 fputs("\n", DEBUG_FH);
4395 #endif
4396
4397 /* NULLs order first */
4398 if(!literal_a || !literal_b) {
4399 if(!literal_a && !literal_b) {
4400 result = 0;
4401 } else {
4402 result = (!literal_a) ? -1 : 1;
4403 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4404 RASQAL_DEBUG2("Got one NULL literal comparison, returning %d\n", result);
4405 #endif
4406 }
4407 break;
4408 }
4409
4410 result = rasqal_literal_compare(literal_a, literal_b,
4411 compare_flags | RASQAL_COMPARE_URI,
4412 &error);
4413 if(error) {
4414 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4415 RASQAL_DEBUG2("Got literal comparison error at expression %d, returning 0\n", i);
4416 #endif
4417 result = 0;
4418 break;
4419 }
4420
4421 if(!result)
4422 continue;
4423
4424 if(e && e->op == RASQAL_EXPR_ORDER_COND_DESC)
4425 result = -result;
4426 /* else Order condition is RASQAL_EXPR_ORDER_COND_ASC so nothing to do */
4427
4428 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4429 RASQAL_DEBUG3("Returning comparison result %d at expression %d\n", result, i);
4430 #endif
4431 break;
4432 }
4433
4434 return result;
4435 }
4436
4437
4438 /*
4439 * rasqal_literal_array_compare_by_order:
4440 * @values_a: first array of literals
4441 * @values_b: second array of literals
4442 * @order: array of order offsets
4443 * @size: size of arrays
4444 * @compare_flags: comparison flags for rasqal_literal_compare()
4445 *
4446 * INTERNAL - compare two arrays of literals evaluated in a given order
4447 *
4448 * Return value: <0, 0 or >0 comparison
4449 */
4450 int
rasqal_literal_array_compare_by_order(rasqal_literal ** values_a,rasqal_literal ** values_b,int * order,int size,int compare_flags)4451 rasqal_literal_array_compare_by_order(rasqal_literal** values_a,
4452 rasqal_literal** values_b,
4453 int* order,
4454 int size,
4455 int compare_flags)
4456 {
4457 int result = 0;
4458 int i;
4459
4460 for(i = 0; i < size; i++) {
4461 int error = 0;
4462 int order_i = order[i];
4463 rasqal_literal* literal_a = values_a[order_i];
4464 rasqal_literal* literal_b = values_b[order_i];
4465
4466 /* NULLs order first */
4467 if(!literal_a || !literal_b) {
4468 if(!literal_a && !literal_b) {
4469 result = 0;
4470 } else {
4471 result = (!literal_a) ? -1 : 1;
4472 }
4473 break;
4474 }
4475
4476 result = rasqal_literal_compare(literal_a, literal_b,
4477 compare_flags | RASQAL_COMPARE_URI,
4478 &error);
4479 if(error) {
4480 result = 0;
4481 break;
4482 }
4483
4484 if(!result)
4485 continue;
4486 break;
4487 }
4488
4489 return result;
4490 }
4491
4492
4493 /**
4494 * rasqal_literal_array_equals:
4495 * @values_a: first array of literals
4496 * @values_b: second array of literals
4497 * @size: size of arrays
4498 *
4499 * INTERNAL - compare two arrays of literals for equality
4500 *
4501 * Return value: non-0 if equal
4502 */
4503 int
rasqal_literal_array_equals(rasqal_literal ** values_a,rasqal_literal ** values_b,int size)4504 rasqal_literal_array_equals(rasqal_literal** values_a,
4505 rasqal_literal** values_b,
4506 int size)
4507 {
4508 int result = 1; /* equal */
4509 int i;
4510 int error = 0;
4511
4512 for(i = 0; i < size; i++) {
4513 rasqal_literal* literal_a = values_a[i];
4514 rasqal_literal* literal_b = values_b[i];
4515
4516 result = rasqal_literal_equals_flags(literal_a, literal_b,
4517 RASQAL_COMPARE_RDF, &error);
4518 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4519 RASQAL_DEBUG1("Comparing ");
4520 rasqal_literal_print(literal_a, DEBUG_FH);
4521 fputs(" to ", DEBUG_FH);
4522 rasqal_literal_print(literal_b, DEBUG_FH);
4523 fprintf(DEBUG_FH, " gave %s\n", (result ? "equality" : "not equal"));
4524 #endif
4525
4526 if(error)
4527 result = 0;
4528
4529 /* if different, end */
4530 if(!result)
4531 break;
4532 }
4533
4534 return result;
4535 }
4536
4537
4538 /**
4539 * rasqal_literal_sequence_equals:
4540 * @values_a: first sequence of literals
4541 * @values_b: second sequence of literals
4542 *
4543 * INTERNAL - compare two arrays of literals for equality
4544 *
4545 * Return value: non-0 if equal
4546 */
4547 int
rasqal_literal_sequence_equals(raptor_sequence * values_a,raptor_sequence * values_b)4548 rasqal_literal_sequence_equals(raptor_sequence* values_a,
4549 raptor_sequence* values_b)
4550 {
4551 int result = 1; /* equal */
4552 int i;
4553 int error = 0;
4554 int size = raptor_sequence_size(values_a);
4555
4556 for(i = 0; i < size; i++) {
4557 rasqal_literal* literal_a = (rasqal_literal*)raptor_sequence_get_at(values_a, i);
4558 rasqal_literal* literal_b = (rasqal_literal*)raptor_sequence_get_at(values_b, i);
4559
4560 result = rasqal_literal_equals_flags(literal_a, literal_b,
4561 RASQAL_COMPARE_RDF, &error);
4562 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
4563 RASQAL_DEBUG1("Comparing ");
4564 rasqal_literal_print(literal_a, DEBUG_FH);
4565 fputs(" to ", DEBUG_FH);
4566 rasqal_literal_print(literal_b, DEBUG_FH);
4567 fprintf(DEBUG_FH, " gave %s\n", (result ? "equality" : "not equal"));
4568 #endif
4569
4570 if(error)
4571 result = 0;
4572
4573 /* if different, end */
4574 if(!result)
4575 break;
4576 }
4577
4578 return result;
4579 }
4580
4581
4582 typedef struct
4583 {
4584 int is_distinct;
4585 int compare_flags;
4586 } literal_sequence_sort_compare_data;
4587
4588
4589 /**
4590 * rasqal_literal_sequence_sort_map_compare:
4591 * @user_data: comparison user data pointer
4592 * @a: pointer to address of first array
4593 * @b: pointer to address of second array
4594 *
4595 * INTERNAL - compare two pointers to array of iterals objects
4596 *
4597 * Suitable for use as a compare function in qsort_r() or similar.
4598 *
4599 * Return value: <0, 0 or >1 comparison
4600 */
4601 static int
rasqal_literal_sequence_sort_map_compare(void * user_data,const void * a,const void * b)4602 rasqal_literal_sequence_sort_map_compare(void* user_data,
4603 const void *a,
4604 const void *b)
4605 {
4606 raptor_sequence* literal_seq_a;
4607 raptor_sequence* literal_seq_b;
4608 literal_sequence_sort_compare_data* lsscd;
4609 int result = 0;
4610
4611 lsscd = (literal_sequence_sort_compare_data*)user_data;
4612
4613 literal_seq_a = (raptor_sequence*)a;
4614 literal_seq_b = (raptor_sequence*)b;
4615
4616 if(lsscd->is_distinct) {
4617 result = !rasqal_literal_sequence_equals(literal_seq_a, literal_seq_b);
4618 if(!result)
4619 /* duplicate, so return that */
4620 return 0;
4621 }
4622
4623 /* now order it */
4624 result = rasqal_literal_sequence_compare(lsscd->compare_flags,
4625 literal_seq_a, literal_seq_b);
4626
4627 /* still equal? make sort stable by using the pointers */
4628 if(!result) {
4629 ptrdiff_t d;
4630
4631 /* Have to cast raptor_sequence* to something with a known type
4632 * (not void*, not raptor_sequence* whose size is private to
4633 * raptor) so we can do pointer arithmetic. We only care about
4634 * the relative pointer difference.
4635 */
4636 d = RASQAL_GOOD_CAST(char*, literal_seq_a) - RASQAL_GOOD_CAST(char*, literal_seq_b);
4637
4638 /* copy the sign of the (unknown size) signed integer 'd' into an
4639 * int result
4640 */
4641 result = (d > 0) - (d < 0);
4642 RASQAL_DEBUG2("Got equality result so using pointers, returning %d\n",
4643 result);
4644 }
4645
4646 return result;
4647 }
4648
4649
4650 static int
rasqal_literal_sequence_sort_map_print_literal_sequence(void * object,FILE * fh)4651 rasqal_literal_sequence_sort_map_print_literal_sequence(void *object, FILE *fh)
4652 {
4653 if(object)
4654 raptor_sequence_print((raptor_sequence*)object, fh);
4655 else
4656 fputs("NULL", fh);
4657 return 0;
4658 }
4659
4660
4661 /**
4662 * rasqal_new_literal_sequence_sort_map:
4663 * @compare_flags: flags for rasqal_literal_compare()
4664 *
4665 * INTERNAL - create a new map for sorting arrays of literals
4666 *
4667 */
4668 rasqal_map*
rasqal_new_literal_sequence_sort_map(int is_distinct,int compare_flags)4669 rasqal_new_literal_sequence_sort_map(int is_distinct, int compare_flags)
4670 {
4671 literal_sequence_sort_compare_data* lsscd;
4672
4673 lsscd = RASQAL_MALLOC(literal_sequence_sort_compare_data*, sizeof(*lsscd));
4674 if(!lsscd)
4675 return NULL;
4676
4677 lsscd->is_distinct = is_distinct;
4678 lsscd->compare_flags = compare_flags;
4679
4680 return rasqal_new_map(rasqal_literal_sequence_sort_map_compare,
4681 lsscd,
4682 (raptor_data_free_handler)rasqal_free_memory,
4683 (raptor_data_free_handler)raptor_free_sequence,
4684 NULL, /* free_value_fn */
4685 rasqal_literal_sequence_sort_map_print_literal_sequence,
4686 NULL,
4687 0 /* do not allow duplicates */);
4688 }
4689
4690
4691 /**
4692 * rasqal_literal_sequence_sort_map_add_literal_sequence:
4693 * @map: literal sort map
4694 * @literals_seq: Sequence of #rasqal_literal to add
4695 *
4696 * INTERNAL - Add a row to an literal sequence sort map for sorting
4697 *
4698 * The literals array @literals_sequence becomes owned by the map.
4699 *
4700 * return value: non-0 if the array of literals was a duplicate (and not added)
4701 */
4702 int
rasqal_literal_sequence_sort_map_add_literal_sequence(rasqal_map * map,raptor_sequence * literals_seq)4703 rasqal_literal_sequence_sort_map_add_literal_sequence(rasqal_map* map,
4704 raptor_sequence *literals_seq)
4705 {
4706 if(!rasqal_map_add_kv(map, literals_seq, NULL))
4707 return 0;
4708
4709 /* duplicate, and not added so delete it */
4710 #ifdef RASQAL_DEBUG
4711 RASQAL_DEBUG1("Got duplicate array of literals ");
4712 raptor_sequence_print(literals_seq, DEBUG_FH);
4713 fputc('\n', DEBUG_FH);
4714 #endif
4715 raptor_free_sequence(literals_seq);
4716
4717 return 1;
4718 }
4719
4720
4721 /**
4722 * rasqal_new_literal_sequence_of_sequence_from_data:
4723 * @world: world object ot use
4724 * @row_data: row data
4725 *
4726 * INTERNAL - Make a sequence of sequence of #rasqal_literal* literals
4727 *
4728 * The @row_data parameter is an array of strings forming a table of
4729 * width (literals_count * 2).
4730 * The rows are values where offset 0 is a string literal and
4731 * offset 1 is a URI string literal. If a string literal looks like
4732 * a number (strtol passes), an integer literal is formed.
4733 *
4734 * The end of data is indicated by an entire row of NULLs.
4735 *
4736 * Return value: sequence of rows or NULL on failure
4737 */
4738 raptor_sequence*
rasqal_new_literal_sequence_of_sequence_from_data(rasqal_world * world,const char * const row_data[],int width)4739 rasqal_new_literal_sequence_of_sequence_from_data(rasqal_world* world,
4740 const char* const row_data[],
4741 int width)
4742 {
4743 raptor_sequence *seq = NULL;
4744 int row_i;
4745 int column_i;
4746 int failed = 0;
4747
4748 #define GET_CELL(row, column, offset) \
4749 row_data[((((row) * width) + (column))<<1) + (offset)]
4750
4751 seq = raptor_new_sequence((raptor_data_free_handler)raptor_free_sequence,
4752 (raptor_data_print_handler)raptor_sequence_print);
4753 if(!seq)
4754 return NULL;
4755
4756 for(row_i = 0; 1; row_i++) {
4757 raptor_sequence* row;
4758 int data_values_seen = 0;
4759
4760 /* Terminate on an entire row of NULLs */
4761 for(column_i = 0; column_i < width; column_i++) {
4762 if(GET_CELL(row_i, column_i, 0) || GET_CELL(row_i, column_i, 1)) {
4763 data_values_seen++;
4764 break;
4765 }
4766 }
4767 if(!data_values_seen)
4768 break;
4769
4770 row = raptor_new_sequence((raptor_data_free_handler)rasqal_free_literal,
4771 (raptor_data_print_handler)rasqal_literal_print);
4772 if(!row) {
4773 raptor_free_sequence(seq); seq = NULL;
4774 goto tidy;
4775 }
4776
4777 for(column_i = 0; column_i < width; column_i++) {
4778 rasqal_literal* l = NULL;
4779
4780 if(GET_CELL(row_i, column_i, 0)) {
4781 /* string literal */
4782 const char* str = GET_CELL(row_i, column_i, 0);
4783 size_t str_len = strlen(str);
4784 char *eptr = NULL;
4785 long number;
4786
4787 number = strtol(RASQAL_GOOD_CAST(const char*, str), &eptr, 10);
4788 if(!*eptr) {
4789 /* is numeric */
4790 l = rasqal_new_numeric_literal_from_long(world,
4791 RASQAL_LITERAL_INTEGER,
4792 number);
4793 } else {
4794 unsigned char *val;
4795 val = RASQAL_MALLOC(unsigned char*, str_len + 1);
4796 if(val) {
4797 memcpy(val, str, str_len + 1);
4798
4799 l = rasqal_new_string_literal_node(world, val, NULL, NULL);
4800 } else
4801 failed = 1;
4802 }
4803 } else if(GET_CELL(row_i, column_i, 1)) {
4804 /* URI */
4805 const unsigned char* str;
4806 raptor_uri* u;
4807
4808 str = RASQAL_GOOD_CAST(const unsigned char*, GET_CELL(row_i, column_i, 1));
4809 u = raptor_new_uri(world->raptor_world_ptr, str);
4810
4811 if(u)
4812 l = rasqal_new_uri_literal(world, u);
4813 else
4814 failed = 1;
4815 } else {
4816 /* variable is not defined for this row */
4817 continue;
4818 }
4819
4820 if(!l) {
4821 raptor_free_sequence(row);
4822 failed = 1;
4823 goto tidy;
4824 }
4825 raptor_sequence_set_at(row, column_i, l);
4826 }
4827
4828 raptor_sequence_push(seq, row);
4829 }
4830
4831 tidy:
4832 if(failed) {
4833 if(seq) {
4834 raptor_free_sequence(seq);
4835 seq = NULL;
4836 }
4837 }
4838
4839 return seq;
4840 }
4841
4842
4843
4844 /*
4845 * rasqal_new_literal_from_term:
4846 * @world: rasqal world
4847 * @term: term object
4848 *
4849 * INTERNAL - create a new literal from a #raptor_term
4850 *
4851 * Return value: new literal or NULL on failure
4852 */
4853 rasqal_literal*
rasqal_new_literal_from_term(rasqal_world * world,raptor_term * term)4854 rasqal_new_literal_from_term(rasqal_world* world, raptor_term* term)
4855 {
4856 rasqal_literal* l = NULL;
4857 size_t len;
4858 unsigned char* new_str = NULL;
4859
4860 if(!term)
4861 return NULL;
4862
4863 if(term->type == RAPTOR_TERM_TYPE_LITERAL) {
4864 char *language = NULL;
4865 raptor_uri* uri = NULL;
4866
4867 len = term->value.literal.string_len;
4868 new_str = RASQAL_MALLOC(unsigned char*, len + 1);
4869 if(!new_str)
4870 goto fail;
4871
4872 memcpy(new_str, term->value.literal.string, len + 1);
4873
4874 if(term->value.literal.language) {
4875 len = term->value.literal.language_len;
4876 language = RASQAL_MALLOC(char*, len + 1);
4877 if(!language)
4878 goto fail;
4879
4880 memcpy(language, term->value.literal.language, len + 1);
4881 }
4882
4883 if(term->value.literal.datatype)
4884 uri = raptor_uri_copy(term->value.literal.datatype);
4885
4886 l = rasqal_new_string_literal(world, new_str, language, uri, NULL);
4887 } else if(term->type == RAPTOR_TERM_TYPE_BLANK) {
4888 len = term->value.blank.string_len;
4889 new_str = RASQAL_MALLOC(unsigned char*, len + 1);
4890 if(!new_str)
4891 goto fail;
4892
4893 memcpy(new_str, term->value.blank.string, len + 1);
4894 l = rasqal_new_simple_literal(world, RASQAL_LITERAL_BLANK, new_str);
4895 } else if(term->type == RAPTOR_TERM_TYPE_URI) {
4896 raptor_uri* uri;
4897 uri = raptor_uri_copy((raptor_uri*)term->value.uri);
4898 l = rasqal_new_uri_literal(world, uri);
4899 } else
4900 goto fail;
4901
4902 return l;
4903
4904 fail:
4905 if(new_str)
4906 RASQAL_FREE(unsigned char*, new_str);
4907
4908 return NULL;
4909 }
4910
4911
4912 #endif /* not STANDALONE */
4913
4914
4915
4916
4917 #ifdef STANDALONE
4918 #include <stdio.h>
4919
4920 int main(int argc, char *argv[]);
4921
4922 /* Test 0 */
4923 static const char* const data_3x3_unique_rows[] =
4924 {
4925 /* 3 literals in 3 rows - all distinct */
4926 /* row 1 data */
4927 "0", NULL, "1", NULL, "2", NULL,
4928 /* row 2 data */
4929 "3", NULL, "4", NULL, "5", NULL,
4930 /* row 3 data */
4931 "6", NULL, "7", NULL, "8", NULL,
4932 /* end of data */
4933 NULL, NULL, NULL, NULL, NULL, NULL,
4934 };
4935
4936 static const char* const data_3x4_1_duplicate_rows[] =
4937 {
4938 /* 3 literals in 4 rows - with one duplicate */
4939 /* row 1 data */
4940 "0", NULL, "1", NULL, "2", NULL,
4941 /* row 2 data */
4942 "3", NULL, "4", NULL, "5", NULL,
4943 /* row 3 data */
4944 "0", NULL, "1", NULL, "2", NULL,
4945 /* row 4 data */
4946 "6", NULL, "7", NULL, "8", NULL,
4947 /* end of data */
4948 NULL, NULL, NULL, NULL, NULL, NULL,
4949 };
4950
4951 static const char* const data_3x6_2_duplicate_rows[] =
4952 {
4953 /* 3 literals in 6 rows - with one duplicate */
4954 /* row 1 data */
4955 "0", NULL, "1", NULL, "2", NULL,
4956 /* row 2 data */
4957 "3", NULL, "4", NULL, "5", NULL,
4958 /* row 3 data */
4959 "0", NULL, "1", NULL, "2", NULL,
4960 /* row 4 data */
4961 "3", NULL, "4", NULL, "5", NULL,
4962 /* row 5 data */
4963 "6", NULL, "7", NULL, "8", NULL,
4964 /* row 6 data */
4965 "8", NULL, "9", NULL, "0", NULL,
4966 /* end of data */
4967 NULL, NULL, NULL, NULL, NULL, NULL,
4968 };
4969
4970
4971
4972 #define TESTS_COUNT 3
4973
4974 static const struct {
4975 int width;
4976 int expected_rows;
4977 const char* const *data;
4978 } test_data[TESTS_COUNT] = {
4979 /* Test 0: 3 literals, 3 rows (no duplicates) */
4980 {3, 3, data_3x3_unique_rows },
4981 /* Test 1: 3 literals, 4 rows (1 duplicate) */
4982 {3, 3, data_3x4_1_duplicate_rows },
4983 /* Test 2: 3 literals, 6 rows (2 duplicate2) */
4984 {3, 4, data_3x6_2_duplicate_rows }
4985 };
4986
4987
4988 int
main(int argc,char * argv[])4989 main(int argc, char *argv[])
4990 {
4991 const char *program = rasqal_basename(argv[0]);
4992 int failures = 0;
4993 rasqal_world *world;
4994 int test_id;
4995
4996 world = rasqal_new_world();
4997 if(!world || rasqal_world_open(world)) {
4998 fprintf(stderr, "%s: rasqal_world init failed\n", program);
4999 return(1);
5000 }
5001
5002 /* test */
5003 fprintf(stderr, "%s: Testing literals\n", program);
5004
5005 for(test_id = 0; test_id < TESTS_COUNT; test_id++) {
5006 int expected_rows = test_data[test_id].expected_rows;
5007 int width = test_data[test_id].width;
5008 raptor_sequence* seq;
5009 int duplicates;
5010 int count;
5011 int i;
5012 raptor_sequence* seq2;
5013 rasqal_map* map;
5014
5015 seq = rasqal_new_literal_sequence_of_sequence_from_data(world,
5016 test_data[test_id].data,
5017 width);
5018 if(!seq) {
5019 fprintf(stderr, "%s: failed to create seq of literal seq\n", program);
5020 failures++;
5021 goto tidy;
5022 }
5023
5024 fprintf(DEBUG_FH, "%s: Test %d data (seq of seq of literals) is: ", program,
5025 test_id);
5026 raptor_sequence_print(seq, DEBUG_FH);
5027 fputc('\n', DEBUG_FH);
5028
5029 map = rasqal_new_literal_sequence_sort_map(1 /* is_distinct */,
5030 0 /* compare_flags */);
5031 if(!map) {
5032 fprintf(DEBUG_FH, "%s: Test %d failed to create map\n",
5033 program, test_id);
5034 failures++;
5035 raptor_free_sequence(seq);
5036 continue;
5037 }
5038
5039 duplicates = 0;
5040 count = 0;
5041 for(i = 0;
5042 (seq2 = (raptor_sequence*)raptor_sequence_delete_at(seq, i));
5043 i++) {
5044 int rc;
5045
5046 rc = rasqal_literal_sequence_sort_map_add_literal_sequence(map, seq2);
5047 if(rc) {
5048 fprintf(DEBUG_FH, "%s: Test %d literal seq %d is a duplicate\n",
5049 program, test_id, i);
5050 duplicates++;
5051 } else
5052 count++;
5053 }
5054 rasqal_free_map(map);
5055
5056 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
5057 fprintf(DEBUG_FH, "%s: Test %d had %d duplicates\n", program, test_id,
5058 duplicates);
5059 #endif
5060
5061 raptor_free_sequence(seq);
5062
5063 if(count != expected_rows) {
5064 fprintf(DEBUG_FH, "%s: Test %d returned %d rows expected %d\n", program,
5065 test_id, count, expected_rows);
5066 failures++;
5067 }
5068 }
5069
5070
5071 tidy:
5072 rasqal_free_world(world);
5073
5074 return failures;
5075 }
5076 #endif /* STANDALONE */
5077