updates towards supporting relation.
[rrq/rrqmisc.git] / vector / tupleitem.c
1 #include <stdarg.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <tupleitem.h>
5
6 #define COLUMN def->columns
7
8 unsigned long tupleitem_hashcode(itemkeyfun *this,void *key) {
9     tupleschema *def = (tupleschema *) this;
10     tuple *kp = (tuple*) key;
11     int i = 0;
12     unsigned long value = 0;
13     for ( ; i < def->arity; i++ ) {
14         if ( COLUMN[i] ) {
15             value <<= 3;
16             value += COLUMN[i]->hashcode( COLUMN[i], (*kp)[i] );
17         }
18     }
19     return value;
20 }
21
22 /**
23  * This callback function determines whether an item has a
24  * given key or not.
25  */
26 int tupleitem_haskey(itemkeyfun *this,void *item,void *key) {
27     tupleschema *def = (tupleschema *) this;
28     tuple *kp = (tuple*) key;
29     tuple *tp = (tuple*) item;
30     int i = 0;
31     int haskey = 1;
32     for ( ; i < def->arity; i++ ) {
33         if ( COLUMN[i] ) {
34             haskey &= COLUMN[i]->haskey( COLUMN[i], (*tp)[i], (*kp)[i] );
35         }
36     }
37     return haskey;
38 }
39
40
41 /**
42  * This callback function returns the key of an item by considering
43  * the arity and mask.
44  */
45 void *tupleitem_itemkey(itemkeyfun *this,void *item) {
46     tupleschema *def = (tupleschema *) this;
47     tuple *tp = (tuple*) item;
48     int i, j;
49     int keylen = 0;
50     for ( i = 0 ; i < def->arity; i++ ) {
51         if ( COLUMN[i] ) {
52             keylen++;
53         }
54     }
55     void **parts = calloc( keylen, sizeof( void* ) );
56     for ( i = 0, j = 0; i < def->arity; i++ ) {
57         if ( COLUMN[i] ) {
58             parts[j++] = COLUMN[i]->itemkey( COLUMN[i], (*tp)[i] );
59         }
60     }
61     return (void*) parts;
62 }
63
64 /**
65  * This callback function handles a key obtained from the itemkey
66  * callback function to reclaim temporary allocation.
67  */
68 void tupleitem_releasekey(itemkeyfun *this,void *key) {
69     tupleschema *def = (tupleschema *) this;
70     tuple *kp = (tuple*) key;
71     int i,j;
72     for ( i = 0, j = 0; i < def->arity; i++ ) {
73         if ( COLUMN[i] ) {
74             COLUMN[i]->releasekey( COLUMN[i], (*kp)[j++] );
75         }
76     }
77     free( key );
78 }
79
80 // Allocate
81 tuple *tuple_create(int arity,...) {
82     va_list ap;
83     int i;
84     tuple *t = (tuple *)malloc( arity * sizeof( void* ) );
85     for ( i = 0; i < arity; i++ ) {
86         (*t)[i] = va_arg( ap, void* );
87     }
88     return t;
89 }
90
91 tupleschema *tupleschema_create(int arity,tuple *columns) {
92     tupleschema *ts = (tupleschema*) malloc( sizeof( tupleschema ) );
93     (*ts) = (tupleschema) {
94         .functions = {
95             .hashcode = tupleitem_hashcode,
96             .haskey = tupleitem_haskey,
97             .itemkey = tupleitem_itemkey,
98             .releasekey = tupleitem_releasekey
99         },
100         .arity = arity,
101         .columns = (itemkeyfun**) columns
102     };
103     return ts;
104 }
105
106 #define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
107 #define COPY(T,P) COPYA(T,P,1)
108
109 // Duplicate a tupleschema with optionally some columns reset.
110 tupleschema *tupleschema_mask(tupleschema *schema,...) {
111     tupleschema *masked = COPY(tupleschema,schema);
112     masked->columns = COPYA( itemkeyfun*, schema->columns, schema->arity );
113     va_list ap;
114     int i;
115     for ( ;; ) {
116         i = va_arg( ap, int );
117         if ( i < 0 || i >= schema->arity ) {
118             break;
119         }
120         masked->columns[i] = 0;
121     };
122     return masked;
123 }