- ConjunctionQuery *q = (ConjunctionQuery*) this;
- int i = q->size - 1;
- enum NextState s = subsequent;
- switch ( state ) {
- case initial:
- q->active = 1;
- i = 0;
- s = initial;
- // Fall through?
- case subsequent:
- while ( i < q->size ) {
- if ( q->conjuncts[i]->def->next( q->conjuncts[i], bt, s ) ) {
- continue;
- }
- q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
- if ( i-- == 0 ) {
- // The first conjunct now exhausted
- q->active = 0;
- return 0;
- }
- s = subsequent;
- }
- return 1;
- case restore:
- if ( q->active ) {
- for ( ; i >= 0; i-- ) {
- q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
- }
- }
- q->active = 0;
- return 0;
- }
- return 0;
-}
-
-static struct QueryCallbacks ConjunctionQuery_def = {
- .reclaim = ConjunctionQuery_reclaim,
- .next = ConjunctionQuery_next
-};
-
-Query *Query_and(int n,...) {
- va_list args;
- ConjunctionQuery *q = (ConjunctionQuery *)
- malloc( sizeof( ConjunctionQuery ) );
- (*q) = (ConjunctionQuery) {
- .def = &ConjunctionQuery_def,
- .active = 0,
- .size = n,
- .conjuncts = (Query**) malloc( n * sizeof( Query* ) )
- };
- int i;
- va_start( args, n );
- for ( i = 0; i < n; i++ ) {
- q->conjuncts[i] = va_arg( args, Query* );
- }
- va_end( args );
- return (Query*) q;
-}
-
-/* ==================== disjunction ==================== */
-
-/**
- * DisjunctionQuery represents a disjunction of sub queries.
- * \extends Query
- * \related Query
- */
-typedef struct {
- struct QueryCallbacks *def;
- int index;
- int size;
- Query **disjuncts;
-} DisjunctionQuery;
-
-static void DisjunctionQuery_reclaim(Query *this) {
- DisjunctionQuery *q = (DisjunctionQuery*) this;
- int i;
- for ( i = 0; i < q->size; i++ ) {
- q->disjuncts[i]->def->reclaim( q->disjuncts[i] );
- }
- free( q->disjuncts );
- free( this );
-}
-
-static int DisjunctionQuery_next(
- Query *this,BindingTable *bt,enum NextState state) {
- DisjunctionQuery *q = (DisjunctionQuery*) this;
- int i = q->index;
- enum NextState s = subsequent;
- switch ( state ) {
- case initial:
- i = 0;
- s = initial;
- case subsequent:
- for ( ; i < q->size; i++ ) {
- if ( q->disjuncts[i]->def->next( q->disjuncts[i], bt, s ) ) {
- q->index = i;
- return 1;
- }
- q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
- s = initial;
- }
- q->index = -1;
- return 0;
- case restore:
- if ( i >= 0 ) {
- q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
- q->index = -1;
- }
- return 0;
- }
- return 0;
-}
-
-static struct QueryCallbacks DisjunctionQuery_def = {
- .reclaim = DisjunctionQuery_reclaim,
- .next = DisjunctionQuery_next,
-};
-
-Query *Query_or(int n,...) {
- va_list args;
- DisjunctionQuery *q = (DisjunctionQuery *)
- malloc( sizeof( DisjunctionQuery ) );
- (*q) = (DisjunctionQuery) {
- .def = &DisjunctionQuery_def,
- .index = -1,
- .size = n,
- .disjuncts = (Query**) malloc( n * sizeof( Query* ) ),
- };
- int i;
- va_start( args, n );
- for ( i = 0; i < n; i++ ) {
- q->disjuncts[i] = va_arg( args, Query* );