refactoring
[rrq/rrqmisc.git] / vector / AndQuery.c
1 #include <stdarg.h>
2 #include <stdlib.h>
3 #include <AndQuery.h>
4
5 static void AndQuery_reclaim(Query *this) {
6     AndQuery *q = (AndQuery*) this;
7     int i;
8     for ( i = 0; i < q->size; i++ ) {
9         Query_reclaim( q->conjuncts[i] );
10     }
11     free( q->conjuncts );
12     free( this );
13 }
14
15 static int AndQuery_next(
16     Query *this,BindingTable *bt,enum NextState state)
17 {
18     AndQuery *q = (AndQuery*) this;
19     int i = q->size - 1;
20     enum NextState s = subsequent;
21     switch ( state ) {
22     case initial:
23         q->active = 1;
24         i = 0;
25         s = initial;
26         // Fall through?
27     case subsequent:
28         while ( i < q->size ) {
29             if ( Query_next( q->conjuncts[i], bt, s ) ) {
30                 continue;
31             }
32             Query_next( q->conjuncts[i], bt, restore );
33             if ( i-- == 0 ) {
34                 // The first conjunct now exhausted
35                 q->active = 0;
36                 return 0;
37             }
38             s = subsequent;
39         }
40         return 1;
41     case restore:
42         if ( q->active ) {
43             for ( ; i >= 0; i-- ) {
44                 Query_next( q->conjuncts[i], bt, restore );
45             }
46         }
47         q->active = 0;
48         return 0;
49     }
50     return 0;
51 }
52
53 static void AndQuery_variables(Query *this,HashVector *hv) {
54     AndQuery *q = (AndQuery*) this;
55     int i; 
56     for ( i = 0; i < q->size; i++ ) {
57         Query_variables( q->conjuncts[i], hv );
58     }
59 }
60
61 static struct QueryCallbacks AndQuery_def = {
62     .reclaim = AndQuery_reclaim,
63     .next = AndQuery_next,
64     .variables = AndQuery_variables
65 };
66
67 Query *Query_and(int n,...) {
68     va_list args;
69     AndQuery *q = (AndQuery *)
70         malloc( sizeof( AndQuery ) );
71     (*q) = (AndQuery) {
72         .def = &AndQuery_def,
73         .active = 0,
74         .size = n,
75         .conjuncts = (Query**) malloc( n * sizeof( Query* ) )
76     };
77     int i;
78     va_start( args, n );
79     for ( i = 0; i < n; i++ ) {
80         q->conjuncts[i] = va_arg( args, Query* );
81     }
82     va_end( args );
83     return (Query*) q;
84 }
85