94a39d744a2b288638d107501edbc7ab088c5b1c
[rrq/rrqmisc.git] / vector / Query.c
1 #include <Query.h>
2
3 /**
4  * \brief Trampoline for the callback function to reclaim the Query
5  * memory for a given Query.
6  *
7  * \param this is the specific \ref Query concerned.
8  *
9  * Ground queries recalim their own state memory. Composite
10  * queries first propagate the reclaim call to its components, and
11  * thereafter reclaim their local state memory.
12  */
13 void Query_reclaim(Query *this) {
14     this->def->reclaim( this );
15 }
16
17 /**
18  * \brief Trampoline for the callback function to update the Binding
19  * table with a succession of alternative bindings.
20  *
21  * \param this is the specific \ref Query concerned.
22  *
23  * \param bt is the Binding table to set bindings in.
24  *
25  * \param s is the call "sub-command" for the function.
26  *
27  * \returns 1 if a new Binding is provided and 0 otherwise.
28  *
29  * This function is called repeatedly for successively obtaining
30  * the alternative bindings that satisfy the Query. The "initial"
31  * state sub-command tells the function to capture the incoming
32  * BindingTable state so that the function can later restore it
33  * upon the "restore" sub-command. Upon the "initial" command, the
34  * function also sets up the Binding table with its first Binding
35  * alternative. This is followed by a series of "subsequent"
36  * sub-command calls for the function to change the BindingTable
37  * for its succession of Binding alternatives. The function should
38  * return 1 after any successful Binding setup, and return 0 when
39  * it cannot setup any (more) Binding.
40  */
41 int Query_next(Query *this,BindingTable *bt,enum NextState state) {
42     return this->def->next( this, bt, state );
43 }
44
45 /**
46  * \brief Trampoline for the callback function that adds its binding
47  * names to the hashvector.
48  */
49 void Query_variables(Query *this,HashVector *hv) {
50     this->def->variables( this, hv );
51 }
52
53 void Query_eval(
54     Query *q,BindingTable *bt,
55     int (*consequent)(BindingTable *bt,void *data),
56     void *data )
57 {
58     if ( Query_next( q, bt, initial ) && consequent( bt, data ) ) {
59         while ( Query_next( q, bt, subsequent ) && consequent( bt, data ) );
60     }
61     (void) Query_next( q, bt, restore );
62 }
63
64 /* ==================== Snapshotting a query ==================== */
65
66 /**
67  * The data used for bindings capture in  snapshotting.
68  */
69 struct Query_snapshot_data {
70     Tuple *names;
71     Vector *v;
72 };
73
74 static int Query_snapshot_capture(BindingTable *bt,void *data) {
75     struct Query_snapshot_data *d = (struct Query_snapshot_data*) data;
76     Tuple *values = Tuple_clone( d->names );
77     BindingTable_deref( bt, values );
78     Vector_append( d->v, values );
79     return 1;
80 }
81
82 int Query_snapshot(Query *q,Tuple *names,Vector *v) {
83     BindingTable *bt = BindingTable_create( 0 );
84     struct Query_snapshot_data data = { .names = names, .v = v };
85     Vector_resize( v, 0, Vector_free_any, 0 );
86     Query_eval( q, bt, Query_snapshot_capture, &data );
87     return v->size;
88 }