1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_variable.c - Rasqal variable support
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 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #include <stdarg.h>
40
41 #include "rasqal.h"
42 #include "rasqal_internal.h"
43
44 #if 0
45 #define RASQAL_DEBUG_VARIABLE_USAGE
46 #endif
47
48 #ifndef STANDALONE
49
50
51 /**
52 * rasqal_new_variable_from_variable:
53 * @v: #rasqal_variable to copy
54 *
55 * Copy Constructor - Create a new Rasqal variable from an existing one
56 *
57 * This adds a new reference to the variable, it does not do a deep copy
58 *
59 * Return value: a new #rasqal_variable or NULL on failure.
60 **/
61 rasqal_variable*
rasqal_new_variable_from_variable(rasqal_variable * v)62 rasqal_new_variable_from_variable(rasqal_variable* v)
63 {
64 if(!v)
65 return NULL;
66
67 v->usage++;
68
69 #ifdef RASQAL_DEBUG_VARIABLE_USAGE
70 RASQAL_DEBUG3("Variable %s usage increased to %d\n", v->name, v->usage);
71 #endif
72
73 return v;
74 }
75
76 /**
77 * rasqal_free_variable:
78 * @v: #rasqal_variable object
79 *
80 * Destructor - Destroy a Rasqal variable object.
81 *
82 **/
83 void
rasqal_free_variable(rasqal_variable * v)84 rasqal_free_variable(rasqal_variable* v)
85 {
86 if(!v)
87 return;
88
89 #ifdef RASQAL_DEBUG_VARIABLE_USAGE
90 v->usage--;
91 RASQAL_DEBUG3("Variable %s usage decreased to %d\n", v->name, v->usage);
92 if(v->usage)
93 return;
94 #else
95 if(--v->usage)
96 return;
97 #endif
98
99 if(v->name)
100 RASQAL_FREE(char*, v->name);
101
102 if(v->value)
103 rasqal_free_literal(v->value);
104
105 if(v->expression)
106 rasqal_free_expression(v->expression);
107
108 RASQAL_FREE(rasqal_variable, v);
109 }
110
111
112 /**
113 * rasqal_variable_write:
114 * @v: the #rasqal_variable object
115 * @iostr: the #raptor_iostream handle to write to
116 *
117 * Write a Rasqal variable to an iostream in a debug format.
118 *
119 * The write debug format may change in any release.
120 *
121 **/
122 void
rasqal_variable_write(rasqal_variable * v,raptor_iostream * iostr)123 rasqal_variable_write(rasqal_variable* v, raptor_iostream* iostr)
124 {
125 if(!v || !iostr)
126 return;
127
128 if(v->type == RASQAL_VARIABLE_TYPE_ANONYMOUS)
129 raptor_iostream_counted_string_write("anon-variable(", 14, iostr);
130 else
131 raptor_iostream_counted_string_write("variable(", 9, iostr);
132
133 raptor_iostream_string_write(v->name, iostr);
134
135 if(v->expression) {
136 raptor_iostream_write_byte('=', iostr);
137 rasqal_expression_write(v->expression, iostr);
138 }
139
140 if(v->value) {
141 raptor_iostream_write_byte('=', iostr);
142 rasqal_literal_write(v->value, iostr);
143 }
144
145 #ifdef RASQAL_DEBUG_VARIABLE_USAGE
146 raptor_iostream_write_byte('[', iostr);
147 raptor_iostream_decimal_write(v->usage, iostr);
148 raptor_iostream_write_byte(']', iostr);
149 #endif
150
151 raptor_iostream_write_byte(')', iostr);
152 }
153
154
155 /*
156 * rasqal_variables_write:
157 * @seq: sequence of #rasqal_variable to write
158 * @iostr: the #raptor_iostream handle to write to
159 *
160 * INTERNAL - Write a sequence of Rasqal variable to an iostream in a debug format.
161 *
162 * The write debug format may change in any release.
163 *
164 **/
165 int
rasqal_variables_write(raptor_sequence * seq,raptor_iostream * iostr)166 rasqal_variables_write(raptor_sequence* seq, raptor_iostream* iostr)
167 {
168 int vars_size;
169 int i;
170
171 if(!seq || !iostr)
172 return 1;
173
174 vars_size = raptor_sequence_size(seq);
175 for(i = 0; i < vars_size; i++) {
176 rasqal_variable* v;
177
178 v = (rasqal_variable*)raptor_sequence_get_at(seq, i);
179 if(i > 0)
180 raptor_iostream_counted_string_write(", ", 2, iostr);
181
182 rasqal_variable_write(v, iostr);
183 }
184
185 return 0;
186 }
187
188
189 /**
190 * rasqal_variable_print:
191 * @v: the #rasqal_variable object
192 * @fh: the FILE* handle to print to
193 *
194 * Print a Rasqal variable in a debug format.
195 *
196 * The print debug format may change in any release.
197 *
198 * Return value: non-0 on failure
199 **/
200 int
rasqal_variable_print(rasqal_variable * v,FILE * fh)201 rasqal_variable_print(rasqal_variable* v, FILE* fh)
202 {
203 if(v->type == RASQAL_VARIABLE_TYPE_ANONYMOUS)
204 fprintf(fh, "anon-variable(%s", v->name);
205 else
206 fprintf(fh, "variable(%s", v->name);
207
208 if(v->expression) {
209 fputc('=', fh);
210 rasqal_expression_print(v->expression, fh);
211 }
212
213 if(v->value) {
214 fputc('=', fh);
215 rasqal_literal_print(v->value, fh);
216 }
217
218 #ifdef RASQAL_DEBUG_VARIABLE_USAGE
219 fprintf(fh, "[%d]", v->usage);
220 #endif
221
222 fputc(')', fh);
223
224 return 0;
225 }
226
227
228 /**
229 * rasqal_variable_set_value:
230 * @v: the #rasqal_variable object
231 * @l: the #rasqal_literal value to set (or NULL)
232 *
233 * Set the value of a Rasqal variable.
234 *
235 * The variable value is an input parameter and is copied in, not shared.
236 * If the variable value is NULL, any existing value is deleted.
237 *
238 **/
239 void
rasqal_variable_set_value(rasqal_variable * v,rasqal_literal * l)240 rasqal_variable_set_value(rasqal_variable* v, rasqal_literal* l)
241 {
242 if(v->value)
243 rasqal_free_literal(v->value);
244
245 v->value = l;
246
247 #ifdef RASQAL_DEBUG
248 if(!v->name)
249 RASQAL_FATAL1("variable has no name");
250
251 RASQAL_DEBUG2("setting variable %s to value ", v->name);
252 rasqal_literal_print(v->value, stderr);
253 fputc('\n', stderr);
254 #endif
255 }
256
257
258
259 /*
260 * A table of variables with optional binding values
261 *
262 * variables are named or anonymous (cannot be selected).
263 */
264 struct rasqal_variables_table_s {
265 rasqal_world* world;
266
267 /* usage/reference count */
268 int usage;
269
270 /* The variables of size @variables_count + @anon_variables_count
271 * shared pointers into @variables_sequence and @anon_variables_sequence
272 */
273 rasqal_variable** variables;
274
275 /* Named variables (owner) */
276 raptor_sequence* variables_sequence;
277 int variables_count;
278
279 /* Anonymous variables (owner) */
280 raptor_sequence* anon_variables_sequence;
281 int anon_variables_count;
282
283 /* array of variable names. The array is allocated here but the
284 * pointers are into the #variables_sequence above. It is only
285 * allocated if rasqal_variables_table_get_names() is called
286 * on demand, otherwise is NULL.
287 */
288 const unsigned char** variable_names;
289 };
290
291
292
293 /**
294 * rasqal_new_variables_table:
295 * @world: rasqal world
296 *
297 * Constructor - create a new variables table
298 *
299 * Return value: new variables table or NULL On failure
300 */
301 rasqal_variables_table*
rasqal_new_variables_table(rasqal_world * world)302 rasqal_new_variables_table(rasqal_world* world)
303 {
304 rasqal_variables_table* vt;
305
306 vt = RASQAL_CALLOC(rasqal_variables_table*, 1, sizeof(*vt));
307 if(!vt)
308 return NULL;
309
310 vt->usage = 1;
311 vt->world = world;
312
313 vt->variables_sequence = raptor_new_sequence((raptor_data_free_handler)rasqal_free_variable,
314 (raptor_data_print_handler)rasqal_variable_print);
315 if(!vt->variables_sequence)
316 goto tidy;
317
318 vt->anon_variables_sequence = raptor_new_sequence((raptor_data_free_handler)rasqal_free_variable,
319 (raptor_data_print_handler)rasqal_variable_print);
320 if(!vt->anon_variables_sequence)
321 goto tidy;
322
323 vt->variable_names = NULL;
324
325 return vt;
326
327 tidy:
328 rasqal_free_variables_table(vt);
329 vt = NULL;
330
331 return vt;
332 }
333
334
335 rasqal_variables_table*
rasqal_new_variables_table_from_variables_table(rasqal_variables_table * vt)336 rasqal_new_variables_table_from_variables_table(rasqal_variables_table* vt)
337 {
338 vt->usage++;
339 return vt;
340 }
341
342
343 /**
344 * rasqal_free_variables_table:
345 * @vt: rasqal variables table
346 *
347 * Destructor - destroy a new variables table
348 */
349 void
rasqal_free_variables_table(rasqal_variables_table * vt)350 rasqal_free_variables_table(rasqal_variables_table* vt)
351 {
352 if(!vt)
353 return;
354
355 if(--vt->usage)
356 return;
357
358 if(vt->variables)
359 RASQAL_FREE(vararray, vt->variables);
360
361 if(vt->anon_variables_sequence)
362 raptor_free_sequence(vt->anon_variables_sequence);
363
364 if(vt->variables_sequence)
365 raptor_free_sequence(vt->variables_sequence);
366
367 if(vt->variable_names)
368 RASQAL_FREE(cstrings, vt->variable_names);
369
370 RASQAL_FREE(rasqal_variables_table, vt);
371 }
372
373
374 /**
375 * rasqal_variables_table_add_variable:
376 * @vt: #rasqal_variables_table to associate the variable with
377 * @variable: existing variable to add
378 *
379 * Constructor - Add an existing variable to the variables table
380 *
381 * The variables table @vt takes a reference to @variable. This
382 * function will fail if the variable is already in the table. Use
383 * rasqal_variables_table_contains() to check before calling.
384 *
385 * Return value: non-0 on failure (such as name already exists)
386 **/
387 int
rasqal_variables_table_add_variable(rasqal_variables_table * vt,rasqal_variable * variable)388 rasqal_variables_table_add_variable(rasqal_variables_table* vt,
389 rasqal_variable* variable)
390 {
391 raptor_sequence* seq = NULL;
392 int* count_p = NULL;
393
394 if(!vt)
395 return 1;
396
397 switch(variable->type) {
398 case RASQAL_VARIABLE_TYPE_ANONYMOUS:
399 seq = vt->anon_variables_sequence;
400 count_p = &vt->anon_variables_count;
401 break;
402 case RASQAL_VARIABLE_TYPE_NORMAL:
403 seq = vt->variables_sequence;
404 count_p = &vt->variables_count;
405 break;
406
407 case RASQAL_VARIABLE_TYPE_UNKNOWN:
408 default:
409 RASQAL_DEBUG2("Unknown variable type %u", variable->type);
410 return 1;
411 }
412
413 if(rasqal_variables_table_contains(vt, variable->type, variable->name))
414 /* variable with this name already present - error */
415 return 1;
416
417 /* add a new v reference for the variables table's sequence */
418 variable = rasqal_new_variable_from_variable(variable);
419 if(raptor_sequence_push(seq, variable))
420 return 1;
421
422 variable->offset = (*count_p);
423
424 (*count_p)++;
425
426 if(variable->type == RASQAL_VARIABLE_TYPE_ANONYMOUS) {
427 /* new anon variable: add base offset */
428 variable->offset += vt->variables_count;
429 } else {
430 int i;
431
432 /* new normal variable: move all anon variable offsets up 1 */
433 for(i = 0; i < vt->anon_variables_count; i++) {
434 rasqal_variable* anon_v;
435 anon_v = (rasqal_variable*)raptor_sequence_get_at(vt->anon_variables_sequence, i);
436 anon_v->offset++;
437 }
438 }
439
440 if(vt->variable_names) {
441 RASQAL_FREE(cstrings, vt->variable_names);
442 vt->variable_names = NULL;
443 }
444
445 return 0;
446 }
447
448
449 /**
450 * rasqal_variables_table_add2:
451 * @vt: #rasqal_variables_table to associate the variable with
452 * @type: variable type defined by enumeration rasqal_variable_type
453 * @name: variable name
454 * @name_len: length of @name (or 0)
455 * @value: variable #rasqal_literal value (or NULL)
456 *
457 * Constructor - Create a new variable and add it to the variables table
458 *
459 * The @name and @value fields are copied. If a variable with the
460 * name already exists, that is returned and the new @value is
461 * ignored.
462 *
463 * Return value: a new #rasqal_variable or NULL on failure.
464 **/
465 rasqal_variable*
rasqal_variables_table_add2(rasqal_variables_table * vt,rasqal_variable_type type,const unsigned char * name,size_t name_len,rasqal_literal * value)466 rasqal_variables_table_add2(rasqal_variables_table* vt,
467 rasqal_variable_type type,
468 const unsigned char *name, size_t name_len,
469 rasqal_literal *value)
470 {
471 rasqal_variable* v = NULL;
472
473 if(!vt || !name)
474 goto failed;
475
476 if(!name_len)
477 name_len = strlen(RASQAL_GOOD_CAST(const char*, name));
478
479 if(!name_len)
480 goto failed;
481
482 /* If already present, just return a new reference to it */
483 v = rasqal_variables_table_get_by_name(vt, type, name);
484 if(v)
485 return rasqal_new_variable_from_variable(v);
486
487 v = RASQAL_CALLOC(rasqal_variable*, 1, sizeof(*v));
488 if(!v)
489 goto failed;
490
491 v->offset = -1;
492 v->usage = 1;
493 v->vars_table = vt;
494 v->type = type;
495 v->name = RASQAL_MALLOC(unsigned char*, name_len + 1);
496 memcpy(RASQAL_GOOD_CAST(char*, v->name), name, name_len + 1);
497 v->value = rasqal_new_literal_from_literal(value);
498
499 if(rasqal_variables_table_add_variable(vt, v))
500 goto failed;
501
502 return v;
503
504
505 failed:
506 if(v)
507 RASQAL_FREE(rasqal_variable*, v);
508
509 return NULL;
510 }
511
512
513 /**
514 * rasqal_variables_table_add:
515 * @vt: #rasqal_variables_table to associate the variable with
516 * @type: variable type defined by enumeration rasqal_variable_type
517 * @name: variable name
518 * @value: variable #rasqal_literal value (or NULL)
519 *
520 * Constructor - Create a new variable and add it to the variables table
521 *
522 * @Deprecated: for rasqal_variables_table_add2() which copies the @name
523 * and @value
524 *
525 * The @name and @value become owned by the rasqal_variable
526 * structure. If a variable with the name already exists, that is
527 * returned and the new @value is ignored.
528 *
529 * Return value: a new #rasqal_variable or NULL on failure.
530 **/
531 rasqal_variable*
rasqal_variables_table_add(rasqal_variables_table * vt,rasqal_variable_type type,const unsigned char * name,rasqal_literal * value)532 rasqal_variables_table_add(rasqal_variables_table* vt,
533 rasqal_variable_type type,
534 const unsigned char *name, rasqal_literal *value)
535 {
536 rasqal_variable* v;
537
538 if(!vt || !name)
539 return NULL;
540
541 v = rasqal_variables_table_add2(vt, type, name, 0, value);
542 RASQAL_FREE(char*, name);
543 if(value)
544 rasqal_free_literal(value);
545 return v;
546 }
547
548
549 rasqal_variable*
rasqal_variables_table_get(rasqal_variables_table * vt,int idx)550 rasqal_variables_table_get(rasqal_variables_table* vt, int idx)
551 {
552 raptor_sequence* seq = NULL;
553
554 if(idx < 0)
555 return NULL;
556
557 if(idx < vt->variables_count)
558 seq = vt->variables_sequence;
559 else {
560 idx -= vt->variables_count;
561 seq = vt->anon_variables_sequence;
562 }
563
564 return (rasqal_variable*)raptor_sequence_get_at(seq, idx);
565 }
566
567
568 rasqal_literal*
rasqal_variables_table_get_value(rasqal_variables_table * vt,int idx)569 rasqal_variables_table_get_value(rasqal_variables_table* vt, int idx)
570 {
571 rasqal_variable* v;
572
573 v = rasqal_variables_table_get(vt, idx);
574 if(!v)
575 return NULL;
576
577 return v->value;
578 }
579
580
581 /**
582 * rasqal_variables_table_get_by_name:
583 * @vt: the variables table
584 * @type: the variable type to match or #RASQAL_VARIABLE_TYPE_UNKNOWN for any.
585 * @name: the variable type
586 *
587 * Lookup a variable by type and name in the variables table.
588 *
589 * Note that looking up for any type #RASQAL_VARIABLE_TYPE_UNKNOWN
590 * may a name match but for any type so in cases where the query has
591 * both a named and anonymous (extensional) variable, an arbitrary one
592 * will be returned.
593 *
594 * Return value: a shared pointer to the #rasqal_variable or NULL if not found
595 **/
596 rasqal_variable*
rasqal_variables_table_get_by_name(rasqal_variables_table * vt,rasqal_variable_type type,const unsigned char * name)597 rasqal_variables_table_get_by_name(rasqal_variables_table* vt,
598 rasqal_variable_type type,
599 const unsigned char *name)
600 {
601 int i;
602 rasqal_variable* v;
603
604 for(i = 0; (v = rasqal_variables_table_get(vt, i)); i++) {
605 if(((type != RASQAL_VARIABLE_TYPE_UNKNOWN) && v->type == type) &&
606 !strcmp(RASQAL_GOOD_CAST(const char*, v->name),
607 RASQAL_GOOD_CAST(const char*, name)))
608 return v;
609 }
610 return NULL;
611 }
612
613
614 /**
615 * rasqal_variables_table_contains:
616 * @vt: #rasqal_variables_table to lookup
617 * @type: variable type
618 * @name: variable name
619 *
620 * Check if there is a variable with the given type and name in the variables table
621 *
622 * Return value: non-0 if the variable is present
623 */
624 int
rasqal_variables_table_contains(rasqal_variables_table * vt,rasqal_variable_type type,const unsigned char * name)625 rasqal_variables_table_contains(rasqal_variables_table* vt,
626 rasqal_variable_type type,
627 const unsigned char *name)
628 {
629 return (rasqal_variables_table_get_by_name(vt, type, name) != NULL);
630 }
631
632
633 int
rasqal_variables_table_set(rasqal_variables_table * vt,rasqal_variable_type type,const unsigned char * name,rasqal_literal * value)634 rasqal_variables_table_set(rasqal_variables_table* vt,
635 rasqal_variable_type type,
636 const unsigned char *name, rasqal_literal* value)
637 {
638 rasqal_variable* v;
639
640 v = rasqal_variables_table_get_by_name(vt, type, name);
641 if(!v)
642 return 1;
643
644 rasqal_variable_set_value(v, value);
645 return 0;
646 }
647
648
649 int
rasqal_variables_table_get_named_variables_count(rasqal_variables_table * vt)650 rasqal_variables_table_get_named_variables_count(rasqal_variables_table* vt)
651 {
652 return vt->variables_count;
653 }
654
655
656 int
rasqal_variables_table_get_anonymous_variables_count(rasqal_variables_table * vt)657 rasqal_variables_table_get_anonymous_variables_count(rasqal_variables_table* vt)
658 {
659 return vt->anon_variables_count;
660 }
661
662
663 int
rasqal_variables_table_get_total_variables_count(rasqal_variables_table * vt)664 rasqal_variables_table_get_total_variables_count(rasqal_variables_table* vt)
665 {
666 return vt->variables_count + vt->anon_variables_count;
667 }
668
669
670 raptor_sequence*
rasqal_variables_table_get_named_variables_sequence(rasqal_variables_table * vt)671 rasqal_variables_table_get_named_variables_sequence(rasqal_variables_table* vt)
672 {
673 return vt->variables_sequence;
674 }
675
676
677 raptor_sequence*
rasqal_variables_table_get_anonymous_variables_sequence(rasqal_variables_table * vt)678 rasqal_variables_table_get_anonymous_variables_sequence(rasqal_variables_table* vt)
679 {
680 return vt->anon_variables_sequence;
681 }
682
683
684 const unsigned char**
rasqal_variables_table_get_names(rasqal_variables_table * vt)685 rasqal_variables_table_get_names(rasqal_variables_table* vt)
686 {
687 int size = vt->variables_count;
688
689 if(!vt->variable_names && size) {
690 int i;
691
692 vt->variable_names = RASQAL_CALLOC(const unsigned char**, RASQAL_GOOD_CAST(size_t, (size + 1)),
693 sizeof(unsigned char*));
694 if(!vt->variable_names)
695 return NULL;
696
697 for(i = 0; i < size; i++) {
698 rasqal_variable* v;
699
700 v = (rasqal_variable*)raptor_sequence_get_at(vt->variables_sequence, i);
701 vt->variable_names[i] = v->name;
702 }
703 }
704
705 return vt->variable_names;
706 }
707
708
709 /*
710 * Deep copy a sequence of rasqal_variable to a new one.
711 */
712 raptor_sequence*
rasqal_variable_copy_variable_sequence(raptor_sequence * vars_seq)713 rasqal_variable_copy_variable_sequence(raptor_sequence* vars_seq)
714 {
715 raptor_sequence* nvars_seq = NULL;
716 int size;
717 int i;
718
719 if(!vars_seq)
720 return NULL;
721
722 nvars_seq = raptor_new_sequence((raptor_data_free_handler)rasqal_free_variable,
723 (raptor_data_print_handler)rasqal_variable_print);
724 if(!nvars_seq)
725 return NULL;
726
727 size = raptor_sequence_size(vars_seq);
728 for(i = 0; i < size; i++) {
729 rasqal_variable* v;
730
731 v = (rasqal_variable*)raptor_sequence_get_at(vars_seq, i);
732 v = rasqal_new_variable_from_variable(v);
733 raptor_sequence_set_at(nvars_seq, i, v);
734 }
735
736 return nvars_seq;
737 }
738
739
740
741 #if RAPTOR_VERSION < 20015
742 /* pointers are rasqal_variable** */
743 static int
rasqal_variable_compare_by_name_arg(const void * a,const void * b,void * arg)744 rasqal_variable_compare_by_name_arg(const void *a, const void *b, void *arg)
745 {
746 rasqal_variable *var_a;
747 rasqal_variable *var_b;
748
749 var_a = *(rasqal_variable**)a;
750 var_b = *(rasqal_variable**)b;
751
752 return strcmp(RASQAL_GOOD_CAST(const char*, var_a->name),
753 RASQAL_GOOD_CAST(const char*, var_b->name));
754 }
755
756 #else
757 /* pointers are int* */
758 static int
rasqal_order_compare_by_name_arg(const void * a,const void * b,void * arg)759 rasqal_order_compare_by_name_arg(const void *a, const void *b, void *arg)
760 {
761 int offset_a;
762 int offset_b;
763 rasqal_variables_table* vt;
764 const unsigned char* name_a;
765 const unsigned char* name_b;
766
767 offset_a = *(int*)a;
768 offset_b = *(int*)b;
769 vt = (rasqal_variables_table*)arg;
770
771 name_a = rasqal_variables_table_get(vt, offset_a)->name;
772 name_b = rasqal_variables_table_get(vt, offset_b)->name;
773
774 return strcmp(RASQAL_GOOD_CAST(const char*, name_a),
775 RASQAL_GOOD_CAST(const char*, name_b));
776 }
777 #endif
778
779
780 /*
781 * rasqal_variables_table_get_order:
782 * @vt: variables table
783 *
784 * INTERNAL - Get the order of the variables in sort order
785 *
786 * Return value: array of integers of order variables (terminated by integer < 0) or NULL on failure
787 */
788 int*
rasqal_variables_table_get_order(rasqal_variables_table * vt)789 rasqal_variables_table_get_order(rasqal_variables_table* vt)
790 {
791 raptor_sequence* seq;
792 int size;
793 int* order;
794 int i;
795 #if RAPTOR_VERSION < 20015
796 void** array;
797 #endif
798
799 seq = rasqal_variables_table_get_named_variables_sequence(vt);
800 if(!seq)
801 return NULL;
802
803 size = raptor_sequence_size(seq);
804 if(!size)
805 return NULL;
806
807 order = RASQAL_CALLOC(int*, RASQAL_GOOD_CAST(size_t, size + 1), sizeof(int));
808 if(!order)
809 return NULL;
810
811 #if RAPTOR_VERSION < 20015
812 array = rasqal_sequence_as_sorted(seq, rasqal_variable_compare_by_name_arg,
813 vt);
814 if(!array)
815 return NULL;
816
817 for(i = 0; i < size; i++)
818 order[i] = (RASQAL_GOOD_CAST(rasqal_variable*, array[i]))->offset;
819 RASQAL_FREE(void*, array);
820 #else
821 for(i = 0; i < size; i++)
822 order[i] = i;
823
824 raptor_sort_r(order, size, sizeof(int), rasqal_order_compare_by_name_arg, vt);
825 #endif
826 order[size] = -1;
827
828 return order;
829 }
830
831
832 #endif /* not STANDALONE */
833
834
835
836 #ifdef STANDALONE
837 #include <stdio.h>
838
839 int main(int argc, char *argv[]);
840
841
842 int
main(int argc,char * argv[])843 main(int argc, char *argv[])
844 {
845 const char *program = rasqal_basename(argv[0]);
846 rasqal_world* world = NULL;
847 rasqal_variables_table* vt = NULL;
848 #define NUM_VARS 3
849 const char* var_names[NUM_VARS] = {"normal-null", "normal-value", "anon"};
850 rasqal_variable* vars[NUM_VARS];
851 rasqal_literal *value = NULL;
852 int i;
853 int rc = 0;
854
855 world = rasqal_new_world();
856 if(!world || rasqal_world_open(world)) {
857 fprintf(stderr, "%s: rasqal_world init failed\n", program);
858 rc = 1;
859 goto tidy;
860 }
861
862 vt = rasqal_new_variables_table(world);
863 if(!vt) {
864 fprintf(stderr, "%s: Failed to make variables table\n", program);
865 rc = 1;
866 goto tidy;
867 }
868
869 vars[0] = rasqal_variables_table_add2(vt, RASQAL_VARIABLE_TYPE_NORMAL,
870 RASQAL_GOOD_CAST(const unsigned char*, var_names[0]),
871 0, NULL);
872 if(!vars[0]) {
873 fprintf(stderr, "%s: Failed to make normal variable with NULL value\n",
874 program);
875 rc = 1;
876 goto tidy;
877 }
878 /* vars[0] now owned by vt */
879
880 value = rasqal_new_double_literal(world, 42.0);
881 if(!value) {
882 fprintf(stderr, "%s: Failed to make double literal\n", program);
883 rc = 1;
884 goto tidy;
885 }
886 vars[1] = rasqal_variables_table_add2(vt, RASQAL_VARIABLE_TYPE_NORMAL,
887 RASQAL_GOOD_CAST(const unsigned char*, var_names[1]),
888 0, value);
889 if(!vars[1]) {
890 fprintf(stderr, "%s: Failed to make normal variable with literal value\n",
891 program);
892 rc = 1;
893 goto tidy;
894 }
895 /* vars[1] now owned by vt */
896
897 vars[2] = rasqal_variables_table_add2(vt, RASQAL_VARIABLE_TYPE_ANONYMOUS,
898 RASQAL_GOOD_CAST(const unsigned char*, var_names[2]),
899 0, NULL);
900 if(!vars[2]) {
901 fprintf(stderr, "%s: Failed to make anonymous variable with NULL value\n",
902 program);
903 rc = 1;
904 goto tidy;
905 }
906 /* vars[2] now owned by vt */
907
908 tidy:
909 for(i = 0; i < NUM_VARS; i++) {
910 if(vars[i])
911 rasqal_free_variable(vars[i]);
912 }
913
914 if(value)
915 rasqal_free_literal(value);
916 if(vt)
917 rasqal_free_variables_table(vt);
918
919 if(world)
920 rasqal_free_world(world);
921
922 return rc;
923 }
924 #endif /* STANDALONE */
925