portability fixes
[rrq/rrqmisc.git] / logic / AssignQuery.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <AssignQuery.h>
4
5 // Release any memory.
6 static void AssignQuery_reclaim(Query *this) {
7     AssignQuery *q = (AssignQuery*) this;
8     free( q->saved );
9     free( this );
10 }
11
12 static int AssignQuery_check(Tuple *a,Tuple *b) {
13     int i;
14     for ( i = 0; i < a->size; i++ ) {
15         char *value = a->elements[i];
16         char *current = b->elements[i];
17         if ( value && current && current != value &&
18              strcmp( current, value ) != 0 ) {
19             return 0;
20         }
21     }
22     return 1;
23 }
24
25 // Make names have given values and return 1. If any name has a
26 // different value then return 0. Values are strings.
27 static int AssignQuery_next(
28     Query *this,BindingTable *bt,enum NextState state) {
29     AssignQuery *q = (AssignQuery*) this;
30     switch ( state ) {
31     case initial:
32         if ( q->saved == 0 ) {
33             q->saved = Tuple_clone( q->names );
34         } else {
35             memcpy( q->saved, q->names, q->names->size * sizeof( void* ) );
36         }
37         BindingTable_deref( bt, q->saved );
38         // Check with new values
39         if ( AssignQuery_check( q->values, q->saved ) ) {
40             BindingTable_set_all( bt, q->names, q->values, 0 );
41             return 1;
42         }
43         // Fall through
44     case subsequent:
45     case restore:
46         if ( q->saved ) {
47             BindingTable_set_all( bt, q->names, q->saved, 1 );
48             free( q->saved );
49             q->saved = 0;
50         }
51         return 0;
52     }
53     return 0;
54 }
55
56 static void AssignQuery_variables(Query *this,HashVector *hv) {
57     AssignQuery *q = (AssignQuery*) this;
58     unsigned long i;
59     for ( i = 0; i < q->names->size; i++ ) {
60         HashVector_add( hv, q->names->elements[i] );
61     }
62 }
63
64 static struct QueryCallbacks AssignQuery_def = {
65     .reclaim = AssignQuery_reclaim,
66     .next = AssignQuery_next,
67     .variables = AssignQuery_variables
68 };
69
70 /**
71  * Return a Query object representing an assignment of one or more
72  * variables.
73  */
74 Query *Query_assign(int arity,Tuple *names,Tuple *values) {
75     AssignQuery *q = (AssignQuery*)
76         malloc( sizeof( AssignQuery ) );
77     (*q) = (AssignQuery) {
78         .def = &AssignQuery_def,
79         .names = names,
80         .values = values,
81         .saved = 0
82     };
83     return (Query*) q;
84 }