major reorganisation
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 18 Jul 2022 06:00:26 +0000 (16:00 +1000)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 18 Jul 2022 06:00:26 +0000 (16:00 +1000)
68 files changed:
Doxyfile
htable/Makefile
logic/AndQuery.c [new file with mode: 0644]
logic/AndQuery.h [new file with mode: 0644]
logic/AssignQuery.c [new file with mode: 0644]
logic/AssignQuery.h [new file with mode: 0644]
logic/Binding.c [new file with mode: 0644]
logic/Binding.h [new file with mode: 0644]
logic/BindingTable.c [new file with mode: 0644]
logic/BindingTable.h [new file with mode: 0644]
logic/Makefile [new file with mode: 0644]
logic/NotQuery.c [new file with mode: 0644]
logic/NotQuery.h [new file with mode: 0644]
logic/OrQuery.c [new file with mode: 0644]
logic/OrQuery.h [new file with mode: 0644]
logic/Query.c [new file with mode: 0644]
logic/Query.h [new file with mode: 0644]
logic/QueryCallbacks.h [new file with mode: 0644]
logic/Relation.c [new file with mode: 0644]
logic/Relation.h [new file with mode: 0644]
logic/RelationQuery.c [new file with mode: 0644]
logic/RelationQuery.h [new file with mode: 0644]
logic/Tuple.c [new file with mode: 0644]
logic/Tuple.h [new file with mode: 0644]
logic/TupleSchema.c [new file with mode: 0644]
logic/TupleSchema.h [new file with mode: 0644]
socket-sniff/Makefile
socket-sniff/socket-sniff.c
tests/Makefile
tests/example-relation.c
typing/ItemKeyFun.c [new file with mode: 0644]
typing/ItemKeyFun.h [new file with mode: 0644]
typing/Makefile [new file with mode: 0644]
typing/integeritem.c [new file with mode: 0644]
typing/integeritem.h [new file with mode: 0644]
typing/stringitem.c [new file with mode: 0644]
typing/stringitem.h [new file with mode: 0644]
vector/AndQuery.c [deleted file]
vector/AndQuery.h [deleted file]
vector/AssignQuery.c [deleted file]
vector/AssignQuery.h [deleted file]
vector/Binding.c [deleted file]
vector/Binding.h [deleted file]
vector/BindingTable.c [deleted file]
vector/BindingTable.h [deleted file]
vector/HashVector.c
vector/ItemKeyFun.h [deleted file]
vector/Makefile
vector/NotQuery.c [deleted file]
vector/NotQuery.h [deleted file]
vector/OrQuery.c [deleted file]
vector/OrQuery.h [deleted file]
vector/Query.c [deleted file]
vector/Query.h [deleted file]
vector/QueryCallbacks.h [deleted file]
vector/Relation.c [deleted file]
vector/Relation.h [deleted file]
vector/RelationQuery.c [deleted file]
vector/RelationQuery.h [deleted file]
vector/Tuple.c [deleted file]
vector/Tuple.h [deleted file]
vector/TupleSchema.c [deleted file]
vector/TupleSchema.h [deleted file]
vector/integeritem.c [deleted file]
vector/integeritem.h [deleted file]
vector/mainpage.dox [deleted file]
vector/stringitem.c [deleted file]
vector/stringitem.h [deleted file]

index a32e453f98e174a729e12cd4b26b59963b54f445..d4690db594037877597d969e2a1cd1efe0889261 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -58,7 +58,7 @@ PROJECT_LOGO           =
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = /home/ralph/src/borta/misc/docs
+OUTPUT_DIRECTORY       = /home/ralph/src/borta/rrqmisc/docs
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -864,7 +864,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = /home/ralph/src/borta/misc/vector
+INPUT                  = /home/ralph/src/borta/rrqmisc/vector
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
index 4d0ed950bd473f117753633c258192205a73978f..e8bd7e1ac9103c47cca7372299ae1bdcc51f0936 100644 (file)
@@ -1,18 +1,14 @@
-default: libhtable.a
+LIBRARY = librrqhtable.a
+LIBOBJS = htable.o
 
-.INTERMEDIATE: htable.o
-htable.o: CFLAGS = -Wall -g
-htable.o: htable.c
+default: $(LIBRARY) example-htable
+CLEANRM += $(LIBRARY)
 
-libhtable.a: htable.o
-       $(AR) r $@ $^
-CLEANRM += libhtable.a
+include ../common.mk
 
 .INTERMEDIATE: example-htable.o
 example-htable: CFLAGS = -Wall -g
-example-htable: LDLIBS = libhtable.a
-example-htable: example-htable.o libhtable.a
+example-htable: example-htable.o $(LIBRARY)
+
 CLEANRM += example-htable
 
-clean:
-       rm -f $(CLEANRM)
diff --git a/logic/AndQuery.c b/logic/AndQuery.c
new file mode 100644 (file)
index 0000000..169ff9e
--- /dev/null
@@ -0,0 +1,85 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <AndQuery.h>
+
+static void AndQuery_reclaim(Query *this) {
+    AndQuery *q = (AndQuery*) this;
+    int i;
+    for ( i = 0; i < q->size; i++ ) {
+       Query_reclaim( q->conjuncts[i] );
+    }
+    free( q->conjuncts );
+    free( this );
+}
+
+static int AndQuery_next(
+    Query *this,BindingTable *bt,enum NextState state)
+{
+    AndQuery *q = (AndQuery*) 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 ( Query_next( q->conjuncts[i], bt, s ) ) {
+               continue;
+           }
+           Query_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-- ) {
+               Query_next( q->conjuncts[i], bt, restore );
+           }
+       }
+       q->active = 0;
+       return 0;
+    }
+    return 0;
+}
+
+static void AndQuery_variables(Query *this,HashVector *hv) {
+    AndQuery *q = (AndQuery*) this;
+    int i; 
+    for ( i = 0; i < q->size; i++ ) {
+       Query_variables( q->conjuncts[i], hv );
+    }
+}
+
+static struct QueryCallbacks AndQuery_def = {
+    .reclaim = AndQuery_reclaim,
+    .next = AndQuery_next,
+    .variables = AndQuery_variables
+};
+
+Query *Query_and(int n,...) {
+    va_list args;
+    AndQuery *q = (AndQuery *)
+       malloc( sizeof( AndQuery ) );
+    (*q) = (AndQuery) {
+       .def = &AndQuery_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;
+}
+
diff --git a/logic/AndQuery.h b/logic/AndQuery.h
new file mode 100644 (file)
index 0000000..7871eea
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef AndQuery_H
+#define AndQuery_H
+
+#include <Query.h>
+
+/**
+ * AndQuery represents a conjunction of sub queries.
+ * \extends Query
+ * \related Query
+ */
+typedef struct {
+    struct QueryCallbacks *def;
+    int active;
+    int size;
+    Query **conjuncts;
+} AndQuery;
+
+
+#endif
diff --git a/logic/AssignQuery.c b/logic/AssignQuery.c
new file mode 100644 (file)
index 0000000..bb264aa
--- /dev/null
@@ -0,0 +1,84 @@
+#include <stdlib.h>
+#include <string.h>
+#include <AssignQuery.h>
+
+// Release any memory.
+static void AssignQuery_reclaim(Query *this) {
+    AssignQuery *q = (AssignQuery*) this;
+    free( q->saved );
+    free( this );
+}
+
+static int AssignQuery_check(Tuple *a,Tuple *b) {
+    int i;
+    for ( i = 0; i < a->size; i++ ) {
+       char *value = a->elements[i];
+       char *current = b->elements[i];
+       if ( value && current && current != value &&
+            strcmp( current, value ) != 0 ) {
+           return 0;
+       }
+    }
+    return 1;
+}
+
+// Make names have given values and return 1. If any name has a
+// different value then return 0. Values are strings.
+static int AssignQuery_next(
+    Query *this,BindingTable *bt,enum NextState state) {
+    AssignQuery *q = (AssignQuery*) this;
+    switch ( state ) {
+    case initial:
+       if ( q->saved == 0 ) {
+           q->saved = Tuple_clone( q->names );
+       } else {
+           memcpy( q->saved, q->names, q->names->size * sizeof( void* ) );
+       }
+       BindingTable_deref( bt, q->saved );
+       // Check with new values
+       if ( AssignQuery_check( q->values, q->saved ) ) {
+           BindingTable_set_all( bt, q->names, q->values, 0 );
+           return 1;
+       }
+       // Fall through
+    case subsequent:
+    case restore:
+       if ( q->saved ) {
+           BindingTable_set_all( bt, q->names, q->saved, 1 );
+           free( q->saved );
+           q->saved = 0;
+       }
+       return 0;
+    }
+    return 0;
+}
+
+static void AssignQuery_variables(Query *this,HashVector *hv) {
+    AssignQuery *q = (AssignQuery*) this;
+    unsigned long i;
+    for ( i = 0; i < q->names->size; i++ ) {
+       HashVector_add( hv, q->names->elements[i] );
+    }
+}
+
+static struct QueryCallbacks AssignQuery_def = {
+    .reclaim = AssignQuery_reclaim,
+    .next = AssignQuery_next,
+    .variables = AssignQuery_variables
+};
+
+/**
+ * Return a Query object representing an assignment of one or more
+ * variables.
+ */
+Query *Query_assign(int arity,Tuple *names,Tuple *values) {
+    AssignQuery *q = (AssignQuery*)
+       malloc( sizeof( AssignQuery ) );
+    (*q) = (AssignQuery) {
+       .def = &AssignQuery_def,
+       .names = names,
+       .values = values,
+       .saved = 0
+    };
+    return (Query*) q;
+}
diff --git a/logic/AssignQuery.h b/logic/AssignQuery.h
new file mode 100644 (file)
index 0000000..2e38b87
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef AssignQuery_H
+#define AssignQuery_H
+
+#include <QueryCallbacks.h>
+#include <Tuple.h>
+
+/**
+ * AssignQuery represents an assignment of values to names.
+ *
+ * \extends Query
+ * \related Query
+ */
+typedef struct {
+    struct QueryCallbacks *def;
+    Tuple *names;
+    Tuple *values;
+    Tuple *saved;
+} AssignQuery;
+
+void AssignQuery_assign(
+    BindingTable *bt,Tuple *names,Tuple *values,int all);
+
+#endif
diff --git a/logic/Binding.c b/logic/Binding.c
new file mode 100644 (file)
index 0000000..9bcc0c1
--- /dev/null
@@ -0,0 +1,60 @@
+#include <string.h>
+#include <HashVector.h>
+#include <Binding.h>
+
+/**
+ * This callback function returns the hashcode of a Binding key, which
+ * is its name string.
+ */
+static unsigned long Binding_hashcode(void *this,void *key) {
+    return HashVector_hashcode(
+       (unsigned char *) key, strlen( (char*) key ) );
+}
+
+/**
+ * This callback function determines whether a Binding item has a
+ * given key or not.
+ */
+static int Binding_haskey(void *this,void *item,void *key) {
+    Binding *b = (Binding*) item;
+    char *name = (char *) key;
+    return strcmp( name, (char*) b->name ) == 0;
+}
+
+/**
+ * This callback function returns the key of a Binding itme, which is
+ * its name string.
+ */
+static void *Binding_itemkey(void *this,void *item) {
+    return ((Binding*) item)->name;
+}
+    
+
+/**
+ * This callback function handles the "release" of a Binding key,
+ * which is to do nothing, since the name string memory is not managed
+ * here.
+ */
+static void Binding_releasekey(void *this,void *key) {
+}
+
+/**
+ * This callback function writes a representation of a Binding item
+ * into a character buffer.
+ */
+static int Binding_tostring(void *this,void *item,char *buffer,int limit) {
+    Binding *b = (Binding*) item;
+    return snprintf( buffer, limit, "{%s,%p}", b->name, b->value );
+}
+
+/**
+ * This is the "item type" for Binding items.
+ */
+ItemKeyFun Bindingitem = {
+    .hashcode = Binding_hashcode,
+    .haskey = Binding_haskey,
+    .itemkey = Binding_itemkey,
+    .releasekey = Binding_releasekey,
+    .tostring = Binding_tostring
+};
+
diff --git a/logic/Binding.h b/logic/Binding.h
new file mode 100644 (file)
index 0000000..2d1a0b3
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef Binding_H
+#define Binding_H
+
+#include <ItemKeyFun.h>
+
+/**
+ * \brief A Binding is an association of a (var*) name with a (void*)
+ * value.
+ *
+ * A \b (void*)0 value marks an "unbound" value.
+ */
+typedef struct Binding {
+    char *name;
+    void *value;
+} Binding;
+
+/**
+ * \brief This is the applicable ItemKeyFun callbacks for a Binding
+ * item.
+ */
+extern ItemKeyFun Bindingitem;
+
+#endif
diff --git a/logic/BindingTable.c b/logic/BindingTable.c
new file mode 100644 (file)
index 0000000..2728516
--- /dev/null
@@ -0,0 +1,72 @@
+#include <BindingTable.h>
+#include <string.h>
+#include <stdlib.h>
+
+BindingTable *BindingTable_create() {
+    BindingTable *this = (BindingTable*) malloc( sizeof( BindingTable ) );
+    (*this) = (HashVector) {
+       .table = (Vector) {
+           .variant = Nibble_index_levels, .size = 16, .entries = 0
+       }, .fill = 0, .holes = 0, .type = &Bindingitem
+    };
+    return this;
+}
+
+void BindingTable_release(BindingTable *bt) {
+    if ( bt ) {
+       Vector_resize( &bt->table, 0, Vector_free_any, 0 );
+       free( bt );
+    }
+}
+
+void BindingTable_set(BindingTable *bt,char *name,void *value) {
+    Binding *b = (Binding*) HashVector_find( bt, name );
+    if ( b == 0 ) {
+       b = (Binding*) malloc( sizeof( Binding ) );
+       b->name = name;
+       HashVector_add( bt, b );
+    }
+    b->value = value;
+}
+
+void *BindingTable_get(BindingTable *bt,char *name) {
+    Binding *b = (Binding*) HashVector_find( bt, name );
+    return b? b->value : 0;
+}
+
+void BindingTable_deref(BindingTable *bt,Tuple *t) {
+    unsigned long i;
+    for ( i = 0; i < t->size; i++ ) {
+       if ( t->elements[i] ) {
+           t->elements[i] = BindingTable_get( bt, t->elements[i] );
+       }
+    }
+}
+
+#if 0
+int BindingTable_unify(
+    BindingTable *bt,char *n1,char *n2,int (*eq)(void*,void*)) {
+    void *v1 = BindingTable_get( bt, n1 );
+    void *v2 = BindingTable_get( bt, n2 );
+    if ( v2 && v1 == 0 ) {
+       BindingTable_set( bt, n1, v2 );
+    }
+    if ( v1 && v2 == 0 ) {
+       BindingTable_set( bt, n2, v1 );
+    }
+    return ( v1 && v2 )? ( eq? ( eq( v1, v2 ) == 0 ) : ( v1 == v2 ) ) : 1;
+}
+#endif
+
+Tuple *BindingTable_get_all(BindingTable *bt,Tuple *t) {
+    Tuple *vt = Tuple_clone( t );
+    BindingTable_deref( bt, vt );
+    return vt;
+}
+
+void BindingTable_set_all(BindingTable *bt,Tuple *nm,Tuple *vs,int all) {
+    int i;
+    for ( i = 0; i < nm->size; i++ ) {
+       BindingTable_set( bt, nm->elements[i], vs->elements[i] );
+    }
+}
diff --git a/logic/BindingTable.h b/logic/BindingTable.h
new file mode 100644 (file)
index 0000000..aa4ee6e
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef BindingTable_H
+#define BindingTable_H
+
+#include <HashVector.h>
+#include <TupleSchema.h>
+#include <Binding.h>
+
+/**
+ * A BindingTable is a chain of \ref HashVector "HashVectors" of
+ * Binding items that associate a (char*) name with a (void*) value.
+ */
+typedef HashVector/*<Binding>*/ BindingTable;
+
+/**
+ * \brief Allocate a new \ref BindingTable.
+ *
+ * \returns the allocated \ref bandingtable.
+ *
+ * \related BindingTable
+ */
+extern BindingTable *BindingTable_create();
+
+/**
+ * \brief Reclaim a \ref BindingTable with all its bindings.
+ *
+ * \param bt is the \ref BindingTable to reclaim.
+ *
+ * \related BindingTable
+ */
+extern void BindingTable_release(BindingTable *bt);
+
+/**
+ * \brief Set a Binding in a \ref BindingTable.
+ *
+ * \param bt is the \ref BindingTable concerned.
+ *
+ * \param name is the Binding name.
+ *
+ * \param value is the Binding value.
+ *
+ * \note Binding names are equal or not by means of strcmp, and each
+ * name has a at most single Binding.
+ *
+ * The name and the value are held as given with all memory management
+ * the callers responsibility. This function will however create new
+ * Binding objects and reclaim the old ones as needed.
+ *
+ * A value of \b 0 indicates "unbound".
+ *
+ * \related BindingTable
+ */
+extern void BindingTable_set(BindingTable *bt,char *name,void *value);
+
+/**
+ * \brief Get a Binding from a BindingTable chain.
+ *
+ * \param bt is the first BindingTable concerned.
+ *
+ * \param name is the Binding variable name.
+ *
+ * \returns the value of the found Binding, or \b 0 if none is found.
+ *
+ * \note Binding names are equal or not by means of strcmp, and each
+ * name has a at most single Binding.
+ *
+ * \note Not also that a name can be made unbound on top of being
+ * bound by setting it to \b 0.
+ *
+ * \related BindingTable
+ */
+extern void *BindingTable_get(BindingTable *bt,char *name);
+
+/**
+ * \brief Replace all names with their values.
+ *
+ * \param bt is the BindingTable concerned.
+ *
+ * \param t is the tuple of (char*) names to dereference.
+ */
+extern void BindingTable_deref(BindingTable *bt,Tuple *t);
+
+/**
+ * \brief Set values for names, optionally unbinding names as well.
+ *
+ * \param bt is the bindingtable concerned.
+ *
+ * \param nm is the Tuple of names to bind.
+ *
+ * \param vs is the Tuple of values.
+ *
+ * \param all is a flag to assign all (1) or only non-zero (0) values.
+ *
+ * \note The values tuple must be as wide as the names tuple.
+ */
+extern void BindingTable_set_all(BindingTable *bt,Tuple *nm,Tuple *vs,int all);
+
+#endif
diff --git a/logic/Makefile b/logic/Makefile
new file mode 100644 (file)
index 0000000..e18ef6c
--- /dev/null
@@ -0,0 +1,13 @@
+LIBRARY = librrqlogic.a
+LIBOBJS += Tuple.o TupleSchema.o Relation.o
+LIBOBJS += Binding.o BindingTable.o
+LIBOBJS += Query.o
+LIBOBJS += AssignQuery.o RelationQuery.o
+LIBOBJS += NotQuery.o AndQuery.o OrQuery.o
+#LIBOBJS += View.o
+
+default: $(LIBRARY)
+
+all: default
+
+include ../common.mk
diff --git a/logic/NotQuery.c b/logic/NotQuery.c
new file mode 100644 (file)
index 0000000..8418715
--- /dev/null
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <NotQuery.h>
+
+static void NotQuery_reclaim(Query *this) {
+    NotQuery *q = (NotQuery*) this;
+    Query_reclaim( q->query );
+    free( this );
+}
+
+static int NotQuery_next(
+    Query *this,BindingTable *bt,enum NextState state)
+{
+    NotQuery *q = (NotQuery*) this;
+    if ( state == initial ) {
+       if ( Query_next( q->query, bt, initial ) ) {
+           Query_next( q->query, bt, restore );
+           return 0;
+       }
+       return 1;
+    }
+    return 0;
+}
+
+static void NotQuery_variables(Query *this,HashVector *hv) {
+    Query_variables( ((NotQuery*) this)->query, hv );
+}
+
+static struct QueryCallbacks NotQuery_def = {
+    .reclaim = NotQuery_reclaim,
+    .next = NotQuery_next,
+    .variables = NotQuery_variables
+};
+
+Query *Query_not(Query *q) {
+    NotQuery *nq = (NotQuery*) malloc( sizeof( NotQuery ) );
+    (*nq) = (NotQuery) {
+       .def = &NotQuery_def,
+       .query = q
+    };
+    return (Query*) nq;
+}
diff --git a/logic/NotQuery.h b/logic/NotQuery.h
new file mode 100644 (file)
index 0000000..f2bf7ed
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef NotQuery_H
+#define NotQuery_H
+
+#include <Query.h>
+
+/**
+ * NotQuery represents logical negation.
+ *
+ * \extends Query
+ */
+typedef struct NotQuery {
+    struct QueryCallbacks *def;
+    Query *query;
+} NotQuery;
+
+#endif
diff --git a/logic/OrQuery.c b/logic/OrQuery.c
new file mode 100644 (file)
index 0000000..5a48e5e
--- /dev/null
@@ -0,0 +1,76 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <OrQuery.h>
+
+static void OrQuery_reclaim(Query *this) {
+    OrQuery *q = (OrQuery*) this;
+    int i;
+    for ( i = 0; i < q->size; i++ ) {
+       Query_reclaim( q->disjuncts[i] );
+    }
+    free( q->disjuncts );
+    free( this );
+}
+
+static int OrQuery_next( Query *this,BindingTable *bt,enum NextState state) {
+    OrQuery *q = (OrQuery*) 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 ( Query_next( q->disjuncts[i], bt, s ) ) {
+               q->index = i;
+               return 1;
+           }
+           Query_next( q->disjuncts[i], bt, restore );
+           s = initial;
+       }
+       q->index = -1;
+       return 0;
+    case restore:
+       if ( i >= 0 ) {
+           Query_next( q->disjuncts[i], bt, restore );
+           q->index = -1;
+       }
+       return 0;
+    }
+    return 0;
+}
+
+static void OrQuery_variables(Query *this,HashVector *hv) {
+    OrQuery *q = (OrQuery*) this;
+    int i; 
+    for ( i = 0; i < q->size; i++ ) {
+       Query_variables( q->disjuncts[i], hv );
+    }
+}
+
+static struct QueryCallbacks OrQuery_def = {
+    .reclaim = OrQuery_reclaim,
+    .next = OrQuery_next,
+    .variables = OrQuery_variables
+};
+
+Query *Query_or(int n,...) {
+    va_list args;
+    OrQuery *q = (OrQuery *)
+       malloc( sizeof( OrQuery ) );
+    (*q) = (OrQuery) {
+       .def = &OrQuery_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* );
+    }
+    va_end( args );
+    return (Query*) q;
+}
+
diff --git a/logic/OrQuery.h b/logic/OrQuery.h
new file mode 100644 (file)
index 0000000..9528356
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef OrQuery_H
+#define OrQuery_H
+
+#include <Query.h>
+
+/**
+ * OrQuery represents a disjunction of sub queries.
+ *
+ * \extends Query
+ */
+typedef struct {
+    struct QueryCallbacks *def;
+    int index;
+    int size;
+    Query **disjuncts;
+} OrQuery;
+
+#endif
diff --git a/logic/Query.c b/logic/Query.c
new file mode 100644 (file)
index 0000000..94a39d7
--- /dev/null
@@ -0,0 +1,88 @@
+#include <Query.h>
+
+/**
+ * \brief Trampoline for the callback function to reclaim the Query
+ * memory for a given Query.
+ *
+ * \param this is the specific \ref Query concerned.
+ *
+ * Ground queries recalim their own state memory. Composite
+ * queries first propagate the reclaim call to its components, and
+ * thereafter reclaim their local state memory.
+ */
+void Query_reclaim(Query *this) {
+    this->def->reclaim( this );
+}
+
+/**
+ * \brief Trampoline for the callback function to update the Binding
+ * table with a succession of alternative bindings.
+ *
+ * \param this is the specific \ref Query concerned.
+ *
+ * \param bt is the Binding table to set bindings in.
+ *
+ * \param s is the call "sub-command" for the function.
+ *
+ * \returns 1 if a new Binding is provided and 0 otherwise.
+ *
+ * This function is called repeatedly for successively obtaining
+ * the alternative bindings that satisfy the Query. The "initial"
+ * state sub-command tells the function to capture the incoming
+ * BindingTable state so that the function can later restore it
+ * upon the "restore" sub-command. Upon the "initial" command, the
+ * function also sets up the Binding table with its first Binding
+ * alternative. This is followed by a series of "subsequent"
+ * sub-command calls for the function to change the BindingTable
+ * for its succession of Binding alternatives. The function should
+ * return 1 after any successful Binding setup, and return 0 when
+ * it cannot setup any (more) Binding.
+ */
+int Query_next(Query *this,BindingTable *bt,enum NextState state) {
+    return this->def->next( this, bt, state );
+}
+
+/**
+ * \brief Trampoline for the callback function that adds its binding
+ * names to the hashvector.
+ */
+void Query_variables(Query *this,HashVector *hv) {
+    this->def->variables( this, hv );
+}
+
+void Query_eval(
+    Query *q,BindingTable *bt,
+    int (*consequent)(BindingTable *bt,void *data),
+    void *data )
+{
+    if ( Query_next( q, bt, initial ) && consequent( bt, data ) ) {
+       while ( Query_next( q, bt, subsequent ) && consequent( bt, data ) );
+    }
+    (void) Query_next( q, bt, restore );
+}
+
+/* ==================== Snapshotting a query ==================== */
+
+/**
+ * The data used for bindings capture in  snapshotting.
+ */
+struct Query_snapshot_data {
+    Tuple *names;
+    Vector *v;
+};
+
+static int Query_snapshot_capture(BindingTable *bt,void *data) {
+    struct Query_snapshot_data *d = (struct Query_snapshot_data*) data;
+    Tuple *values = Tuple_clone( d->names );
+    BindingTable_deref( bt, values );
+    Vector_append( d->v, values );
+    return 1;
+}
+
+int Query_snapshot(Query *q,Tuple *names,Vector *v) {
+    BindingTable *bt = BindingTable_create( 0 );
+    struct Query_snapshot_data data = {        .names = names, .v = v };
+    Vector_resize( v, 0, Vector_free_any, 0 );
+    Query_eval( q, bt, Query_snapshot_capture, &data );
+    return v->size;
+}
diff --git a/logic/Query.h b/logic/Query.h
new file mode 100644 (file)
index 0000000..4b2fa6a
--- /dev/null
@@ -0,0 +1,190 @@
+#ifndef Query_H
+#define Query_H
+
+#include <QueryCallbacks.h>
+#include <BindingTable.h>
+#include <Relation.h>
+
+/**
+ * A Query is an implementation of a generic ABI over relations. It's
+ * more or less a "virtual Relation" representing a logical composite
+ * access of actual relations, and as such its active part is held in
+ * a separate \ref Querytype record similar to how \ref ItemKeyFun
+ * records define valye types.
+ */
+typedef struct Query {
+    struct QueryCallbacks *def;
+} Query;
+
+/**
+ * \brief Trampoline for the callback function to reclaim the Query
+ * memory for a given Query.
+ *
+ * \param this is the specific \ref Query concerned.
+ *
+ * Ground queries recalim their own state memory. Composite
+ * queries first propagate the reclaim call to its components, and
+ * thereafter reclaim their local state memory.
+ */
+extern void Query_reclaim(Query *this);
+
+/**
+ * \brief Trampoline for the callback function to update the Binding
+ * table with a succession of alternative bindings.
+ *
+ * \param this is the specific \ref Query concerned.
+ *
+ * \param bt is the Binding table to set bindings in.
+ *
+ * \param s is the call "sub-command" for the function.
+ *
+ * \returns 1 if a new Binding is provided and 0 otherwise.
+ *
+ * This function is called repeatedly for successively obtaining
+ * the alternative bindings that satisfy the Query. The "initial"
+ * state sub-command tells the function to capture the incoming
+ * BindingTable state so that the function can later restore it
+ * upon the "restore" sub-command. Upon the "initial" command, the
+ * function also sets up the Binding table with its first Binding
+ * alternative. This is followed by a series of "subsequent"
+ * sub-command calls for the function to change the BindingTable
+ * for its succession of Binding alternatives. The function should
+ * return 1 after any successful Binding setup, and return 0 when
+ * it cannot setup any (more) Binding.
+ */
+extern int Query_next(Query *this,BindingTable *bt,enum NextState state);
+
+/**
+ * \brief Trampoline for the callback function that adds its binding
+ * names to the hashvector.
+ *
+ * \param this is the query concerned.
+ *
+ * \param hv is the HashVector for collating names.
+ */
+extern void Query_variables(Query *this,HashVector *hv);
+
+
+
+
+/**
+ * \brief Creates an assignment Query.
+ *
+ * \param arity is the assignment tuple arity.
+ *
+ * \param names is the (char*) names to assign.
+ *
+ * \param values is the (void*) values to asign.
+ *
+ * The two tuples must have the same arity for assigning names[i] to
+ * values[i]. This Query makes the given names have the given values,
+ * once for each (*next) call following a (*reset) call.
+ *
+ * \related Query
+ */
+extern Query *Query_assign(int arity,Tuple *names,Tuple *values);
+
+/**
+ * \brief Create a Query record for lookup data in a Relation.
+ *
+ * \param r is the relation being queried.
+ *
+ * \param names is a same-arity tuple of binding names for the
+ * columns, using \b 0 for unnamed columns.
+ *
+ * \param values is a same--arity tuple of query values, using \b 0 for
+ * columns to enumerate.
+ *
+ * The names and values tuples identify bindings and values to use for
+ * the search query, and which bindings to set up from the successive
+ * results. Names that are bound beforhand identify constraining
+ * values, and the names that are unbound gain successive values from
+ * the matching tuples.
+ *
+ * \related Query
+ */
+extern Query *Query_Relation(Relation *r,Tuple *names,Tuple *values);
+
+/**
+ * \brief Create a Query record for a conjunction of queries.
+ *
+ * \param n is the number of sub queries.
+ *
+ * \param ... are the sub queries.
+ *
+ * The conjunction query processes the sub queries in order resulting
+ * in the sequence of their combined bindings.
+ *
+ * \related Query
+ */
+extern Query *Query_and(int n,...);
+
+/**
+ * \brief Create a Query record for a disjunction of queries.
+ *
+ * \param n is the number of sub queries.
+ *
+ * \param ... are the sub queries.
+ *
+ * The disjunction query processed the sub queries in order to find
+ * all their individual "true" binding combinations. It processes one
+ * sub query at a time to exhaustion and provide their individudal
+ * binding sequences separately.
+ *
+ * \related Query
+ */
+extern Query *Query_or(int n,...);
+
+/**
+ * \brief Invoke a consequent callback function for each successful
+ * binding of a query.
+ *
+ * \param q is the antecedent query to process.
+ *
+ * \param bt is the binding table to use.
+ *
+ * \param consequent is the callback function to invoke for each
+ * binding.
+ * \param data is the caller's context data.
+ *
+ * This function prrocesses the Query for establishing its binding
+ * sequence and inokes the consequent callback function for each
+ * binding as it is provided.
+ * 
+ * \related Query
+ */
+extern void Query_eval(
+    Query *q,BindingTable *bt,
+    int (*consequent)(BindingTable *bt,void *data),
+    void *data );
+
+/**
+ * \brief Collect all bindings of query.
+ *
+ * \param q is the query to enumerate.
+ *
+ * \param names is the binding names to track.
+ *
+ * \param results is the result store of bindings for the names.
+ *
+ * \returns the number of results.
+ *
+ * This function evaluates the query for one round of bindings, and
+ * stores their value \ref Tuple Tuples in the given vector. The given
+ * vector is first cleared, and any item is reclaimed with \b free.
+ * Correspondingly the binding \ref Tuple Tuples are allocated with \b
+ * malloc for the caller to reclaim (possibly via a successive call to
+ * this function).
+ */
+//extern int Query_snapshot(Query *q,Tuple *names,Vector *v);
+
+/**
+ * \brief Creates an NotQuery.
+ *
+ * \param query is the query to negate.
+ *
+ * \related Query
+ */
+extern Query *Query_not(Query *values);
+
+#endif
diff --git a/logic/QueryCallbacks.h b/logic/QueryCallbacks.h
new file mode 100644 (file)
index 0000000..5d36e0b
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef QueryCallbacks_H
+#define QueryCallbacks_H
+
+#include <BindingTable.h>
+
+typedef struct Query Query; // forward
+
+enum NextState {
+    /**
+     * This state tells the "next" function that it should capture the
+     * incoming BindingTable state and provide the initial Binding of
+     * a new sucession of bindings.
+     */
+    initial, 
+    /**
+     * This state tells the "next" function that it should update the
+     * bidning table with a subsequent Binding in the current
+     * succession of bindings.
+     */
+    subsequent,
+    /**
+     * This state tells the "next" function that it should just
+     * restore the Binding table to its incoming state.
+     */
+    restore
+};
+
+/**
+ * A struct Query_callbacks record defines the callbacks for a
+ * specific Query type.
+ */
+typedef struct QueryCallbacks {
+    /**
+     * \brief Callback function to reclaim the Query memory for a
+     * given Query.
+     *
+     * \param this is the specific \ref Query concerned.
+     *
+     * Ground queries recalim their own state memory. Composite
+     * queries first propagate the reclaim call to its components, and
+     * thereafter reclaim their local state memory.
+     */
+    void (*reclaim)(Query *this);
+
+    /**
+     * \brief Callback function to update the Binding table with a
+     * succession of alternative bindings.
+     *
+     * \param this is the specific \ref Query concerned.
+     *
+     * \param bt is the Binding table to set bindings in.
+     *
+     * \param s is the call "sub-command" for the function.
+     *
+     * \returns 1 if a new Binding is provided and 0 otherwise.
+     *
+     * This function is called repeatedly for successively obtaining
+     * the alternative bindings that satisfy the Query. The "initial"
+     * state sub-command tells the function to capture the incoming
+     * BindingTable state so that the function can later restore it
+     * upon the "restore" sub-command. Upon the "initial" command, the
+     * function also sets up the Binding table with its first Binding
+     * alternative. This is followed by a series of "subsequent"
+     * sub-command calls for the function to change the BindingTable
+     * for its succession of Binding alternatives. The function should
+     * return 1 after any successful Binding setup, and return 0 when
+     * it cannot setup any (more) Binding.
+     */
+    int (*next)(Query *this,BindingTable *bt,enum NextState state);
+
+    /**
+     * \brief This callback function adds its binding names to the
+     * hashvector.
+     */
+    void (*variables)(Query *this,HashVector *hv);
+} QueryCallbacks;
+
+#endif
diff --git a/logic/Relation.c b/logic/Relation.c
new file mode 100644 (file)
index 0000000..868a477
--- /dev/null
@@ -0,0 +1,162 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <Relation.h>
+
+Relation *Relation_create(TupleSchema *schema) {
+    Relation *r = (Relation *) malloc( sizeof( Relation ) );
+    (*r) = (Relation) {
+       .content = (HashVector) {
+           .table = (Vector) {
+               .variant = Nibble_index_levels,
+               .size = 16,
+               .entries = 0
+           },
+           .fill = 0, .holes = 0, .type = (ItemKeyFun*) schema
+       },
+       .constraints = (Vector) {
+           .variant = single_index_level,
+           .size = 0,
+           .entries = 0
+       },
+    };
+    return r;
+}
+
+#define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
+#define COPY(T,P) COPYA(T,P,1)
+
+// Add an indexing HashVector to the Relation using the given column
+// flags with 1 indicating key column and 0 indicating value column.
+int Relation_add_constraint(Relation *r,...) {
+    va_list ap;
+    TupleSchema *ts = (TupleSchema *) r->content.type;
+    Tuple *columns = Tuple_clone( ts->columns );
+    int i = 0;
+    va_start( ap, r );
+    for ( ; i < columns->size; i++ ) {
+       if ( va_arg( ap, int ) == 0 ) {
+           columns->elements[i] = 0;
+       }
+    }
+    va_end( ap );
+    ts = TupleSchema_create( columns );
+    i = (int) r->constraints.size;
+    Vector_append(
+       &r->constraints,
+       HashVector_create( Nibble_index_levels, (ItemKeyFun*) ts ) );
+    return i;
+}
+
+//============== Adding an item =============
+// Iteration context for adding or Querying a Relation
+typedef struct {
+    Relation *rel;
+    HashVector knockouts;
+    void *item;
+} Knockout;
+
+// Determine matches to ((Knockout*)data)->key in
+// (HashVector*)item, optionally using ((Knockout*)data)->columns
+// for ignoring full matches to the key tuple.
+static int knockout_check(VectorIndex index,void *item,void *data) {
+    Knockout *kod = (Knockout*) data;
+    void *key = kod->item;
+    HashVector *hv = (HashVector*) item;
+    TupleSchema *type = (TupleSchema *)hv->type;
+    VectorIndex i = 0;
+    for ( ; i < hv->table.size; i++ ) {
+       void *old = HashVector_next( hv, &i );
+       if ( old ) {
+           if ( key && type->base.haskey( type, old, key ) == 0 ) {
+               continue;
+           }
+           HashVector_add( &kod->knockouts, old );
+       }
+    }
+    return 0;
+}
+
+// delete the (tuple*)item from the (HashVector*)data
+static int knockout_delete(VectorIndex index,void *item,void *data) {
+    HashVector_delete( (HashVector*) item, data );
+    return 0;
+}
+
+// add the (tuple*)data to the (HashVector*)item
+static int knockout_add(VectorIndex index,void *item,void *data) {
+    HashVector_add( (HashVector*)item, data );
+    return 0;
+}
+
+// Find and remove all collisions for a Query, unless "add" is
+// non-zero in which case the function aborts if there is any match in
+// the main content.
+static int knockout_clear(Knockout *this,Relation *r,Tuple *item,int add) {
+    (*this) = (Knockout) {
+       .rel = r,
+       .knockouts = {
+           .table = {
+               .variant = Nibble_index_levels, .size = 16, .entries = 0
+           },
+           .fill = 0, .holes = 0, .type = r->content.type,
+       },
+       .item = item
+    };
+    knockout_check( 0, &r->content, this );
+    if ( add ) {
+       if ( this->knockouts.fill > 0 ) {
+           return 0;
+       }
+       // Find all constraint knockouts for addition
+       Vector_iterate( &r->constraints, 0, knockout_check, this );
+    }
+    if ( this->knockouts.fill > 0 ) {
+       // Delete them from all tables
+       VectorIndex i;
+       for ( i = 0; i < this->knockouts.table.size; i++ ) {
+           void *t = HashVector_next( &this->knockouts, &i );
+           if ( t ) {
+               HashVector_delete( &r->content, t );
+               Vector_iterate( &r->constraints, 0, knockout_delete, t );
+           }
+       }
+    }
+    return 1;
+}
+
+// add a tuple to a Relation and return a Vector of knocked out
+// tuples, if any, or 0 otherwise.
+Vector *Relation_add(Relation *r,Tuple *item) {
+    Knockout data;
+    if ( knockout_clear( &data, r, item, 1 ) ) {
+       // Add the new tuple
+       HashVector_add( &r->content, item );
+       Vector_iterate( &r->constraints, 0, knockout_add, item );
+       return HashVector_contents( &data.knockouts, single_index_level, 0 );
+    }
+    return 0;
+}
+
+Vector *Relation_delete(Relation *r,Tuple *item) {
+    Knockout data;
+    (void) knockout_clear( &data, r, item, 0 );
+    return HashVector_contents( &data.knockouts, single_index_level, 0 );
+}
+
+void *Relation_next(Relation *r,VectorIndex *index,Tuple *query) {
+    HashVector *hv = &r->content;
+    void *key = query;
+    TupleSchema *type = (TupleSchema *) hv->type;
+    for ( ; (*index) < hv->table.size; (*index)++ ) {
+       void *old = HashVector_next( hv, index );
+       if ( old ) {
+           if ( key && type->base.haskey( type, old, key ) == 0 ) {
+               continue;
+           }
+           return old;
+       }
+    }
+    (*index) = hv->table.size;
+    return 0;
+}
+
diff --git a/logic/Relation.h b/logic/Relation.h
new file mode 100644 (file)
index 0000000..852101a
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef Relation_H
+#define Relation_H
+
+#include <HashVector.h>
+#include <TupleSchema.h>
+
+/**
+ * A Relation is an implementation of a tuple set with (optional) key
+ * constraints. The store is a \ref HashVector whose \b type is a \ref
+ * TupleSchema that defines the columns. The key constraints are
+ * represented as additional \ref HashVector "HashVectors" whose \ref
+ * TupleSchema "TupleSchemas" are clones of the column schema with
+ * some columns excluded.
+ *
+ * \extends HashVector
+ */
+typedef struct {
+    /**
+     * This is the primary content store for the Relation. Its type
+     * should be a TupleSchema declaring the "item types" for the
+     * Relation columns.
+     */
+    HashVector content;
+
+    /**
+     * This is a collection of relational constraints, if any, which
+     * are represented as HashVectors whose TupleSchemas are clones of
+     * the content TupleSchema with some columns excluded.
+     */
+    Vector constraints;
+} Relation;
+
+/**
+ * \brief Create a Relation for the given TupleSchema.
+ *
+ * \param schema is the column schema
+ *
+ * \returns the allocated Relation record.
+ *
+ * The given TupleSchema is set up as the type of the content
+ * HashVector, which also is initialised as a Nibble_index_levels
+ * variant Vector.
+ *
+ * \related Relation
+ */
+extern Relation *Relation_create(TupleSchema *schema);
+
+/**
+ * \brief Add a key constraint to a \ref Relation.
+ *
+ * \param r is the Relation concerned.
+ *
+ * \param ... are the column flags indicating key (1) or value (0)
+ * column for all columns.
+ *
+ * \returns the index into the constraints \ref Vector for the added
+ * constraint.
+ *
+ * This function adds a \ref HashVector with a \ref TupleSchema as its
+ * item type cloned from the content type and then modified to
+ * represent the constraint. Namely that the key columns have their
+ * "column type" set while value columsn are reset.
+ *
+ * The \b constraint \ref HashVectors are used when \ref tuple
+ * "tuples" are added to the \ref Relation so as to identify the
+ * already contained \ref tuple "tuples" that contradict the addition
+ * by means of having the same constraint key. The already contained
+ * \ref tuple "tuples" are then "knocked out" from the Relation by the
+ * new addition.
+ *
+ * \see Relation_add
+ * \related Relation
+ */
+extern int Relation_add_constraint(Relation *r,...);
+
+/**
+ * \brief Add the tuple to the Relation.
+ *
+ * \param r is the \ref Relation concerned.
+ *
+ * \param t is the \ref tuple to add.
+ *
+ * \returns a Vector of all knocked out tuples.
+ *
+ * This function adds the \ref tuple \b t to the \ref Relation \b r,
+ * and it returns a \ref Vector (single_index_level variant) of all
+ * same-key constraint tuples. The returned Vector is malloc-ed and it
+ * must be free-ed by the caller. If the tuple is already contained or
+ * there are no other same-key tuples knocked out, then \b 0 is
+ * returned.
+ *
+ * \related Relation
+ */
+extern Vector *Relation_add(Relation *r,Tuple *t);
+
+/**
+ * \brief Delete all tuples matching to the Query \ref tuple fromt the
+ * \ref Relation.
+ *
+ * \param r is the \ref Relation concerned.
+ *
+ * \param t is the \ref tuple to delete.
+ *
+ * \returns a \Vector Vector of all knocked out tuples, i.e. the
+ * same-key tuples, if any, contained in the Relation
+ *
+ * Note that deletion uses a "Query" tuple, which means that some
+ * columns may be null to mark that them match to any value.
+ *
+ * \related Relation
+ */
+extern Vector *Relation_delete(Relation *r,Tuple *query);
+
+/**
+ * \brief Return the next \ref tuple in the \ref Relation that matches
+ * to the Query \ref tuple, at or after the index.
+ *
+ * \param r is the \ref Relation concerned.
+ *
+ * \param index is a pointer to the \ref Vector index to update.
+ *
+ * \param Query is a Query \tuple tuple for selection of certain
+ * column values.
+ *
+ * \returns any such matching \tuple tuple and an updateed *index.
+ *
+ * \related Relation
+ */
+extern void *Relation_next(Relation *r,VectorIndex *index,Tuple *query);
+
+/**
+ * \brief Lay out a dynamic \ref Relation initializer for a Relation
+ * wth the given column "types".
+ *
+ * This defines a \ref Relation intializer that creates the \ref
+ * TupleSchema for the given columns.
+ *
+ * \note The initializer cannot be used statically.
+ *
+ * The \b content \ref HashVector is a \ref Nibble_index_level variant
+ * with an initial size of 16 slots.
+ *
+ * The constraints \ref Vector is a \ref BitPair_index_level variant
+ * with initial size 0.
+ *
+ * The \b content \ref HashVector \b type is set up with an allocated
+ * \ref TupleSchema that has an allocated \ref tuple that declares the
+ * column "types" view the given \ref ItemKeyFun pointers. Any add
+ * constraints will need to clone that \ref TupleSchema and then clear
+ * the column slots for the constraint value columns, typically by
+ * using \ref TupleSchema_mask for this.
+ *
+ * \related Relation
+ */
+#define RELATION(...) (Relation) { \
+    .content = { \
+        .table = { .variant = Nibble_index_levels, .size=16, .entries=0 }, \
+        .fill = 0, .holes = 0, \
+       .type = (ItemKeyFun*) TUPLESCHEMA( __VA_ARGS__ )        \
+    }, \
+    .constraints = { .variant = BitPair_index_levels, .size=0, .entries=0 } \
+}
+
+#endif
diff --git a/logic/RelationQuery.c b/logic/RelationQuery.c
new file mode 100644 (file)
index 0000000..aa4bdbd
--- /dev/null
@@ -0,0 +1,78 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <RelationQuery.h>
+
+// Release any memory.
+static void RelationQuery_reclaim(Query *this) {
+    RelationQuery *q = (RelationQuery*) this;
+    free( q->saved );
+    free( this );
+}
+
+// Make names have given values and return 1. If any name has a
+// different value then return 0. Values are strings.
+static int RelationQuery_next(
+    Query *this,BindingTable *bt,enum NextState state) {
+    RelationQuery *q = (RelationQuery*) this;
+    VectorIndex index = q->index + 1;
+    switch ( state ) {
+    case initial:
+       if ( q->saved == 0 ) {
+           q->saved = Tuple_clone( q->names );
+       } else {
+           memcpy( q->saved, q->names, q->names->size * sizeof( void* ) );
+       }
+       BindingTable_deref( bt, q->saved );
+       index = 0;
+       // Fall through
+    case subsequent:
+       for ( ; index < q->rel->content.table.size; index++ ) {
+           Tuple *values = Relation_next( q->rel, &index, q->values );
+           if ( values ) {
+               q->index = index;
+               BindingTable_set_all( bt, q->names, values, 1 );
+               return 1;
+           }
+       }
+    case restore:
+       if ( q->saved ) {
+           BindingTable_set_all( bt, q->names, q->saved, 1 );
+           free( q->saved );
+           q->saved = 0;
+       }
+       return 0;
+    }
+    return 0;
+}
+
+static void RelationQuery_variables(Query *this,HashVector *hv) {
+    RelationQuery *q = (RelationQuery*) this;
+    unsigned long i;
+    for ( i = 0; i < q->names->size; i++ ) {
+       HashVector_add( hv, q->names->elements[i] );
+    }
+}
+
+static struct QueryCallbacks RelationQuery_def = {
+    .reclaim = RelationQuery_reclaim,
+    .next = RelationQuery_next,
+    .variables = RelationQuery_variables
+};
+
+/**
+ * Return a Query object representing an Relation of one or more
+ * variables.
+ */
+Query *Query_relation(Relation *r,Tuple *names,Tuple *values) {
+    RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) );
+    (*q) = (RelationQuery) {
+       .def = &RelationQuery_def,
+       .rel = r,
+       .names = names,
+       .values = values,
+       .saved = 0
+    };
+    return (Query*) q;
+}
+
diff --git a/logic/RelationQuery.h b/logic/RelationQuery.h
new file mode 100644 (file)
index 0000000..4c50a53
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef RelationQuery_H
+#define RelationQuery_H
+
+#include <Relation.h>
+#include <Query.h>
+
+/**
+ * RelationQuery represents a ground query on a relation.
+ * \extends Query
+ * \related Query
+ */
+typedef struct {
+    struct QueryCallbacks *def;
+    Relation *rel;
+    VectorIndex index;
+    Tuple *names;
+    Tuple *values;
+    Tuple *saved;
+} RelationQuery;
+
+#endif
diff --git a/logic/Tuple.c b/logic/Tuple.c
new file mode 100644 (file)
index 0000000..2b5b04e
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Tuple.h>
+
+// Allocate zero-ed
+Tuple *Tuple_calloc(unsigned long arity) {
+    Tuple *t = (Tuple *) malloc( sizeof( Tuple ) + arity * sizeof( void* ) );
+    t->size = arity;
+    memset( t->elements, 0, arity * sizeof( void* ) );
+    return t;
+}
+
+// Allocate with values
+Tuple *Tuple_create(int arity,...) {
+    va_list ap;
+    int i;
+    Tuple *t = (Tuple *) malloc( sizeof( Tuple ) + arity * sizeof( void* ) );
+    t->size = arity;
+    va_start( ap, arity );
+    for ( i = 0; i < arity; i++ ) {
+       t->elements[i] = va_arg( ap, void* );
+    }
+    va_end( ap );
+    return t;
+}
+
+// Duplicate
+Tuple *Tuple_clone(Tuple *t) {
+    unsigned long size = t->size * sizeof( void* );
+    Tuple *ct = (Tuple *) malloc( sizeof( Tuple ) + size );
+    memcpy( ct, t, size );
+    return ct;
+}
diff --git a/logic/Tuple.h b/logic/Tuple.h
new file mode 100644 (file)
index 0000000..ea439c5
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef Tuple_H
+#define Tuple_H
+
+#include <ItemKeyFun.h>
+
+typedef struct TupleSchema TupleSchema;
+
+/**
+ * A Tuple is a "self typed" array of elements.
+ */
+typedef struct {
+    /**
+     * The number of elements.
+     */
+    unsigned long size;
+    /**
+     * Base address for element pointers, which thus follow this
+     * struct in memory.
+     */
+    void *elements[];
+} Tuple;
+
+/**
+ * \brief Create an untyped tuple with given values.
+ *
+ * \related Tuple
+ */
+extern Tuple *Tuple_create(int arity,...);
+
+/**
+ * \brief Create an untyped tuple with 0 values.
+ *
+ * \related Tuple
+ */
+extern Tuple *Tuple_calloc(unsigned long arity);
+
+/**
+ * \brief Create a tuple as a clone of a given tuple.
+ *
+ * \related Tuple
+ */
+extern Tuple *Tuple_clone(Tuple *t);
+
+#endif
diff --git a/logic/TupleSchema.c b/logic/TupleSchema.c
new file mode 100644 (file)
index 0000000..5a92b64
--- /dev/null
@@ -0,0 +1,159 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <TupleSchema.h>
+
+/**
+ * This callback function returns the hashcode of a key.
+ *
+ * \param this is a pointer to the ItemKeyFun record from where this
+ * callback got invoked
+ *
+ * \param key is the key to produce a hascode for
+ *
+ * \returns the hashcode which is a VectorIndex (i.e. unsigned long)
+ *
+ * The hashcode is used for indexing into the backing Vector for
+ * finding the an item via its key. The same key must map consistently
+ * to the same hashcode while the hashtable contains an item with that
+ * key. Different keys map map to the same hashcode, in which case the
+ * Vector placement is made at the first empty or hole slot following
+ * the hashcode index.
+ */
+static unsigned long TupleSchema_hashcode(void *this,void *key) {
+    TupleSchema *def = (TupleSchema *) this;
+    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
+    Tuple *kp = (Tuple*) key;
+    int i = 0;
+    unsigned long value = 5381;
+    for ( ; i < def->columns->size; i++ ) {
+       if ( columns[i] ) {
+           value <<= 3;
+           if ( kp->elements[i] ) {
+               value += columns[i]->hashcode( columns[i], kp->elements[i] );
+           }
+       }
+       value += 17;
+    }
+    return value;
+}
+
+/**
+ * This callback function determines whether an item has a
+ * given key or not.
+ */
+static int TupleSchema_haskey(void *this,void *item,void *key) {
+    TupleSchema *def = (TupleSchema *) this;
+    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
+    Tuple *kp = (Tuple*) key;
+    Tuple *tp = (Tuple*) item;
+    int i = 0;
+    for ( ; i < def->columns->size; i++ ) {
+       if ( columns[i] && kp->elements[i] ) {
+           if ( columns[i]->haskey(
+                    columns[i], tp->elements[i], kp->elements[i] ) == 0 ) {
+               return 0;
+           }
+       }
+    }
+    return 1;
+}
+
+
+/**
+ * This callback function returns the key of an item by considering
+ * the arity and mask.
+ */
+static void *TupleSchema_itemkey(void *this,void *item) {
+    TupleSchema *def = (TupleSchema *) this;
+    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
+    Tuple *tp = (Tuple*) item;
+    Tuple *key = Tuple_clone( tp );
+    int i;
+    for ( i = 0; i < def->columns->size; i++ ) {
+       if ( columns[i] ) {
+           key->elements[i] = columns[i]->itemkey(
+               columns[i], tp->elements[i] );
+       } else {
+           key->elements[i] = 0;
+       }
+    }
+    return (void*) key;
+}
+
+/**
+ * This callback function handles a key obtained from the itemkey
+ * callback function to reclaim temporary allocation.
+ */
+static void TupleSchema_releasekey(void *this,void *key) {
+    TupleSchema *def = (TupleSchema *) this;
+    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
+    Tuple *kp = (Tuple*) key;
+    int i;
+    for ( i = 0; i < def->columns->size; i++ ) {
+       if ( columns[i] ) {
+           columns[i]->releasekey( columns[i], kp->elements[i] );
+       }
+    }
+    free( key );
+}
+
+#define OUT(X) a = X; if ( a > limit ) return 0; buffer += a; limit -= a
+
+/**
+ * This callback function writes a representation of an item into
+ * a character buffer.
+ */
+static int TupleSchema_tostring(void *this,void *item,char *buffer,int limit) {
+    TupleSchema *def = (TupleSchema *) this;
+    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
+    Tuple *t = (Tuple*) item;
+    char *x = "<";
+    int a, i;
+    for ( i = 0; i < def->columns->size; i++ ) {
+       OUT( snprintf( buffer, limit, x ) );
+       x = ",";
+       OUT( columns[i]->tostring(
+                columns[i], t->elements[i], buffer, limit ) );
+    }
+    OUT( snprintf( buffer, limit, ">" ) );
+    return a;
+}
+
+ItemKeyFun TupleSchema_callbacks = {
+    .hashcode = TupleSchema_hashcode,
+    .haskey = TupleSchema_haskey,
+    .itemkey = TupleSchema_itemkey,
+    .releasekey = TupleSchema_releasekey,
+    .tostring = TupleSchema_tostring
+};
+
+TupleSchema *TupleSchema_create(Tuple *columns) {
+    TupleSchema *ts = (TupleSchema*) malloc( sizeof( TupleSchema ) );
+    (*ts) = (TupleSchema) {
+       .base = TupleSchema_callbacks,
+       .columns = columns
+    };
+    return ts;
+}
+
+#define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
+#define COPY(T,P) COPYA(T,P,1)
+
+// Duplicate a TupleSchema with optionally some columns reset.
+TupleSchema *TupleSchema_mask(TupleSchema *schema,...) {
+    TupleSchema *masked = COPY(TupleSchema,schema);
+    masked->columns = Tuple_clone( schema->columns );
+    va_list ap;
+    int i;
+    va_start( ap, schema );
+    for ( ;; ) {
+       i = va_arg( ap, int );
+       if ( i < 0 || i >= schema->columns->size ) {
+           break;
+       }
+       masked->columns->elements[i] = 0;
+    };
+    va_end( ap );
+    return masked;
+}
diff --git a/logic/TupleSchema.h b/logic/TupleSchema.h
new file mode 100644 (file)
index 0000000..664ddad
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef tupleitem_H
+#define tupleitem_H
+
+#include <Tuple.h>
+
+/**
+ * A TupleSchema record declares the ItemKeyFun functions for tuple
+ * items together with applicable arity and domain combinations.
+ * Records are created dynamically via the \ref TupleSchema_create
+ * function or the \ref TUPLESCHEMA convenience macro.
+ *
+ * \extends ItemKeyFun
+ */
+typedef struct TupleSchema {
+    /**
+     * These are the ItemKeyFun callback functions to support
+     * HashVector use for tuple items. The functions expects their
+     * ItemKeyFun pointer to be within a TupleSchema record so as to
+     * provide the handling of the tuple columns.
+     */
+    ItemKeyFun base;
+
+    /**
+     * This points to tuple whose elements is array of pointers to the
+     * tuple item domains as represented by their associated
+     * ItemKeyFun records.
+     */
+    Tuple *columns;
+} TupleSchema;
+
+/**
+ * Create a tuples with given values.
+ *
+ * \related TupleSchema
+ */
+extern TupleSchema *TupleSchema_create(Tuple *columns);
+
+/**
+ * Copy the given TupleSchema into a new TupleSchema with some columns
+ * masked. This represents a sub-index type using the unmasked columns
+ * for indexing.
+ *
+ * \related TupleSchema
+ */
+extern TupleSchema *TupleSchema_mask(TupleSchema *schema,...);
+
+/**
+ * \brief Return 1/0 to indicate whether the Query matches the item.
+ *
+ * \related TupleSchema
+ */
+extern int TupleSchema_match(TupleSchema *def,Tuple *query,Tuple *item);
+
+/**
+ * \brief Generic macro to determine the number of expressions in a
+ * __VA_ARGS__
+ *
+ * \related TupleSchema
+ */
+#define NUMARGS(...) (sizeof((void*[]){__VA_ARGS__})/sizeof(void*))
+
+/**
+ * \brief Create a tuple with the given values.
+ *
+ * This invokes \ref tuple_create to allocate and assign a void*
+ * array with the given values.
+ *
+ * \related TupleSchema
+ */
+#define TUPLE(...) Tuple_create( NUMARGS(__VA_ARGS__), __VA_ARGS__ )
+
+/**
+ * \brief Create a \ref TupleSchema with the given column "types".
+ *
+ * This invokes \ref TupleSchema_create to allocate and initialize a
+ * \ref TupleSchema for the given columns via the \ref TUPLE macro.
+ *
+ * \related TupleSchema
+ */
+#define TUPLESCHEMA(...) \
+    TupleSchema_create( TUPLE( __VA_ARGS__ ) )
+
+
+#endif
index d9d783f1469c32c27431c8e7bd6eb1afbd25a77c..e86108ff4d63e5ee2055620aee326e8a07f191b8 100644 (file)
@@ -1,7 +1,11 @@
 default: socket-sniff
 
-CFLAGS = -Wall -I../vector -g -fmax-errors=1
-LDLIBS = -L../vector -lvector
+RRQLIBS = typing vector
+INCDIRS = $(addprefix -I../,$(RRQLIBS))
+
+CFLAGS = -Wall $(INCDIRS)
+CFLAGS += -g -fmax-errors=1
+LDLIBS = -L../vector -lvector -lm
 
 .INTERMEDIATE: socket-sniff.o
 
index 545c9f7019690413caded5f65221667a781d5a0d..4bcc8a254c42d438fe254902f2b6d9734fab9a98 100644 (file)
@@ -12,7 +12,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <hashvector.h>
+#include <HashVector.h>
+#include <stringitem.h>
 
 // Seconds between outputs
 static int DELAY = 5;
@@ -47,29 +48,41 @@ static void die(char *m) {
     exit( 1 );
 }
 
-// Return pointer to the key for an item
-static void *Countp_itemkey(void *item) {
+// Returns the hashcode for a key
+static unsigned long Countp_hashcode(void *this,void *key) {
+    return HashVector_hashcode( key, IPBUFMAX );
+}
+
+// Return pointer a key for an item (could be temporary allocation)
+static void *Countp_itemkey(void *this,void *item) {
     return ((Count*) item)->ip;
 }
 
 // Return 1 if the item has the key, or 0 otherwise.
-static int Countp_haskey(void *item,void *key) {
-    return memcmp( key, Countp_itemkey( item ), IPBUFMAX ) == 0;
+static int Countp_haskey(void *this,void *item,void *key) {
+    return memcmp( key, Countp_itemkey( this, item ), IPBUFMAX ) == 0;
 }
 
-// Returns the hashcode for a key
-static unsigned long Countp_hashcode(void *key) {
-    return hashvector_hashcode( key, IPBUFMAX );
+#if 0
+// Releasing a key does nothing
+static void Countp_releasekey(void *this,void *item) {
 }
+#endif
 
-// The hashvector of seen IP
-static hashvector TBL = {
-    .table = { VECTOR_SLOTS, 0 },
+static ItemKeyFun Countp_itemkeyfun = {
+    .hashcode = Countp_hashcode,
+    .haskey = Countp_haskey,
+    .itemkey = Countp_itemkey,
+    //.releasekey = Countp_releasekey,
+    //.tostring = Countp_tostring
+};
+
+// The HashVector of seen IP
+static HashVector TBL = {
+    .table = { Nibble_index_levels, 16, 0 },
     .fill = 0,
     .holes = 0,
-    .keyhashcode = Countp_hashcode,
-    .itemkey = Countp_itemkey,
-    .haskey = Countp_haskey
+    .type = &Countp_itemkeyfun,
 };
 
 // The Count records in time order
@@ -84,28 +97,28 @@ static char buffer[ IPBUFMAX ];
 /*============================================================
  * Reading ignore lines.
  */
+#if 0
 // Return pointer to the key for an item
-static void *charp_itemkey(void *item) {
+static void *charp_itemkey(void *this,void *item) {
     return item;
 }
 
 // Return 1 if the item has the key, or 0 otherwise.
-static int charp_haskey(void *item,void *key) {
+static int charp_haskey(void *this,void *item,void *key) {
     return strcmp( key, item ) == 0;
 }
 
 // Returns the hashcode for a key
-static unsigned long charp_hashcode(void *key) {
-    return hashvector_hashcode( key, strlen( (const char *) key ) );
+static unsigned long charp_hashcode(void *this,void *key) {
+    return HashVector_hashcode( key, strlen( (const char *) key ) );
 }
+#endif
 
-static hashvector IGN = {
+static HashVector IGN = {
     .table = { 256, 0 },
     .fill = 0,
     .holes = 0,
-    .keyhashcode = charp_hashcode,
-    .itemkey = charp_itemkey,
-    .haskey = charp_haskey
+    .type = &stringitem
 };
 
 static void read_ignore_file(char *filename) {
@@ -144,7 +157,7 @@ static void read_ignore_file(char *filename) {
        char *ip = calloc( 1, p - cur + 1 );
        memcpy( ip, cur, p - cur );
        cur = p + 1;
-       hashvector_add( &IGN, ip );
+       HashVector_add( &IGN, ip );
     }
 }
 
@@ -166,7 +179,7 @@ static int Countp_compare(const void *ax, const void *bx) {
     return a->last - b->last;
 }
 
-static int Countp_fade_and_print(unsigned long index,void *x,void *d) {
+static int Countp_fade_and_print(VectorIndex index,void *x,void *d) {
     if ( x ) {
        Count *item = (Count *) x;
        item->last = item->accum;
@@ -182,7 +195,7 @@ static int Countp_fade_and_print(unsigned long index,void *x,void *d) {
     return 0;
 }
 
-static int Countp_reclaim(vector *pv,unsigned long ix,void *item,void *data) {
+static int Countp_reclaim(Vector *pv,unsigned long ix,void *item,void *data) {
     return 0;
 }
 
@@ -190,21 +203,21 @@ static int Countp_reclaim(vector *pv,unsigned long ix,void *item,void *data) {
 // ip points to [ IPBUFMAX ] of ip address in text
 static void add_show_table(char *ip,size_t length) {
     static time_t show = 0;
-    Count *item;
-    int i = hashvector_find( &TBL, ip, (void**) &item );
+    Count *item = HashVector_find( &TBL, ip );
     struct timeval now;
     if ( gettimeofday( &now, 0 ) ) {
        perror( "gettimeofday" );
        exit( 1 );
     }
-    if ( i == 0 ) {
+    if ( item == 0 ) {
        item = (Count *) calloc( 1, sizeof( Count ) );
        memcpy( item->ip, ip, strlen( ip ) );
-       hashvector_add( &TBL, item );
-       item->ignore = hashvector_find( &IGN, ip, 0 );
+       HashVector_add( &TBL, item );
+       item->ignore = (HashVector_find( &IGN, ip ) != 0);
+       int i;
        for ( i = strlen( ip )-1; i > 1; i-- ) {
            if ( ip[i] == '.' || ip[i] == ':' ) {
-               item->ignore |= hashvector_find( &IGN, ip, 0 );
+               item->ignore |= (HashVector_find( &IGN, ip ) != 0);
            }
            ip[i] = 0;
        }
@@ -243,7 +256,7 @@ static void add_show_table(char *ip,size_t length) {
            trail.head->prev = 0;
        }
        fprintf( stdout, "drop %s\n", old->ip );
-       hashvector_delete( &TBL, old );
+       HashVector_delete( &TBL, old );
        free( old );
     }
     if ( now.tv_sec < show ) {
@@ -253,11 +266,11 @@ static void add_show_table(char *ip,size_t length) {
        show = now.tv_sec;
     }
     show += DELAY; // Time for next output
-    vector ordered = { 0, 0 };
-    hashvector_contents( &TBL, &ordered );
-    vector_qsort( &ordered, Countp_compare );
-    vector_iterate( &ordered, Countp_fade_and_print, 0 );
-    vector_resize( &ordered, 0, Countp_reclaim, 0 );
+    Vector ordered = { Nibble_index_levels, 0, 0 };
+    HashVector_contents( &TBL, Nibble_index_levels, &ordered );
+    Vector_qsort( &ordered, Countp_compare );
+    Vector_iterate( &ordered, 0, Countp_fade_and_print, 0 );
+    Vector_resize( &ordered, 0, Countp_reclaim, 0 );
     fprintf( stdout, "==%ld/%ld/%ld\n", TBL.fill, TBL.holes, TBL.table.size );
 }
 
index 6da4dd77f1d9d2cba77b8b9004ddb6b0b30cf425..ab5fcc2811b59aa9886124acf6449e0a17cfce49 100644 (file)
@@ -4,7 +4,11 @@ BIN = ${SRC:.c=}
 
 default: ${BIN}
 
-CFLAGS = -Wall -I../vector -g -fmax-errors=1
+RRQLIBS = typing vector logic
+INCDIRS = $(addprefix -I../,$(RRQLIBS))
+
+CFLAGS = -Wall $(INCDIRS)
+CFLAGS += -g -fmax-errors=1
 LDLIBS = -L../vector -lvector -lm
 
 .INTERMEDIATE: ${OBJ}
index 73b0dc0b66b94fd1c21aac82b6dcf9d2f28ab990..a70714c12f420285a523f9233c088a0d8f89b153 100644 (file)
@@ -53,7 +53,7 @@ typedef union {
 int main(int argc,char **argv) {
     Relation *rltn2 = Relation_create(
        TupleSchema_create(
-           2, Tuple_create( 2, (void*) &stringitem, (void*) &stringitem ) ) );
+           Tuple_create( 2, (void*) &stringitem, (void*) &stringitem ) ) );
     Relation_add_constraint( rltn2, 0, 1 );
     add_Relation( rltn2, "benton", "holly" );
     add_Relation( rltn2, "benton", "molly");
diff --git a/typing/ItemKeyFun.c b/typing/ItemKeyFun.c
new file mode 100644 (file)
index 0000000..81e4b9a
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * Trampoline functions for the ItemKeyFun callbacks.
+ */
+
+#include <assert.h>
+#include <ItemKeyFun.h>
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.hashcode callback.
+ *
+ * The default is to use the pointer itself.
+ */
+unsigned long ItemKeyFun_hashcode(void *this,void *key) {
+    ItemKeyFun *type = (ItemKeyFun*) this;
+    assert( type );
+    return type->hashcode? type->hashcode( type, key ) : (unsigned long) key;
+}
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.itemkey callback.
+ */
+void *ItemKeyFun_itemkey(void *this,void *item) {
+    ItemKeyFun *type = (ItemKeyFun*) this;
+    assert( type );
+    return type->itemkey? type->itemkey( type, item ) : item;
+}
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.haskey callback.
+ */
+int ItemKeyFun_haskey(void *this,void *item,void *key) {
+    ItemKeyFun *type = (ItemKeyFun*) this;
+    assert( type );
+    if ( type->haskey ) {
+       return type->haskey( this, item, key );
+    }
+    void *ikey = ItemKeyFun_itemkey( this, item );
+    int n = ikey == key;
+    ItemKeyFun_releasekey( this, ikey );
+    return n;
+}
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.releasekey callback.
+ */
+void ItemKeyFun_releasekey(void *this,void *key) {
+    ItemKeyFun *type = (ItemKeyFun*) this;
+    assert( type );
+    if ( type->releasekey ) {
+       type->releasekey( type, key );
+    }
+}
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.tostring callback.
+ */
+int ItemKeyFun_tostring(void *this,void *item,char *buffer,int limit) {
+    ItemKeyFun *type = (ItemKeyFun*) this;
+    assert( type );
+    if ( type->tostring ) {
+       return type->tostring( type, item, buffer, limit );
+    }
+    void *key = ItemKeyFun_itemkey( this, item );
+    int n = snprintf( buffer, limit, "{%p/%p@%p}", type, key, item );
+    ItemKeyFun_releasekey( this, key );
+    return n;
+}
diff --git a/typing/ItemKeyFun.h b/typing/ItemKeyFun.h
new file mode 100644 (file)
index 0000000..8a83f9b
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef ItemKeyFun_H
+#define ItemKeyFun_H
+
+#include <stdio.h>
+
+/**
+ * \struct ItemKeyFun
+ *
+ * ItemKeyFun provides a meta-level representation for abstracting
+ * items as pairs of keys and payload, and having a hashcode mapping
+ * for keys. The key part is used for identifying items under the idea
+ * that all items that have the same key are the same; distinct
+ * representations of the same abstract entity. The hashcode scrambles
+ * the key part in a consistent way into an ideal table index for the
+ * items that have that key. Different keys may yield the same
+ * hashcode.
+ */
+typedef struct {
+
+    /**
+     * This callback function should return the hashcode of a key. The
+     * hashcode is used for indexing into the backing Vector for
+     * finding the an item via its key. The same key must map
+     * consistently to the same hashcode while the hashtable contains
+     * an item with that key. Different keys map map to the same
+     * hashcode, in which case the Vector placement is made at the
+     * first empty or hole slot following the hashcode index.
+     */
+    unsigned long (*hashcode)(void *this,void *key);
+
+    /**
+     * This callback function should determine whether an item has a
+     * given key or not.
+     */
+    int (*haskey)(void *this,void *item,void *key);
+
+    /**
+     * This callback function should return a (possibly temporary) key
+     * of an item. It can be anything (i.e., with or without internal
+     * structure) as it is treated as an identifier that other
+     * callbacks recognize. It is merely understood as a value in an
+     * identity domain.
+     */
+    void *(*itemkey)(void *this,void *item);
+
+    /**
+     * This callback function should handle a key obtained from the
+     * itemkey callback function, e.g., reclaim temporary allocation.
+     */
+    void (*releasekey)(void *this,void *key);
+
+    /**
+     * This callback function writes a representation of an item into
+     * a character buffer.
+     */
+    int (*tostring)(void *this,void *item,char *buffer,int limit);
+
+} ItemKeyFun;
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.hashcode callback.
+ *
+ * The default is to use the pointer itself.
+ */
+extern unsigned long ItemKeyFun_hashcode(void *this,void *key);
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.haskey callback.
+ */
+extern int ItemKeyFun_haskey(void *this,void *item,void *key);
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.itemkey callback.
+ */
+extern void *ItemKeyFun_itemkey(void *this,void *item);
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.releasekey callback.
+ */
+extern void ItemKeyFun_releasekey(void *this,void *key);
+
+/**
+ * \brief Trampoline function for the ItemKeyFun.tostring callback.
+ */
+extern int ItemKeyFun_tostring(void *this,void *item,char *buffer,int limit);
+
+#endif
diff --git a/typing/Makefile b/typing/Makefile
new file mode 100644 (file)
index 0000000..91272e5
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY = librrqtyping.a
+LIBOBJS += ItemKeyFun.o integeritem.o stringitem.o
+
+default: $(LIBRARY)
+
+all: default
+
+include ../common.mk
diff --git a/typing/integeritem.c b/typing/integeritem.c
new file mode 100644 (file)
index 0000000..221fb70
--- /dev/null
@@ -0,0 +1,53 @@
+#include <integeritem.h>
+
+/**
+ * This callback function returns the hashcode of a key. The hashcode
+ * is used for indexing into the backing Vector for finding the an
+ * item via its key. The same key must map consistently to the same
+ * hashcode while the hashtable contains an item with that key.
+ * Different keys map map to the same hashcode, in which case the
+ * Vector placement is made at the first empty or hole slot following
+ * the hashcode index.
+ */
+static unsigned long integeritem_hashcode(void *this,void *key) {
+    return (unsigned long) key;
+}
+
+/**
+ * This callback function determines whether an item has a
+ * given key or not.
+ */
+static int integeritem_haskey(void *this,void *item,void *key) {
+    return item == key;
+}
+
+/**
+ * This callback function returns the key of an item by considering
+ * the arity and schema.
+ */
+static void *integeritem_itemkey(void *this,void *item) {
+    return item;
+}
+
+/**
+ * This callback function handles a key obtained from the itemkey
+ * callback function to reclaim temporary allocation.
+ */
+static void integeritem_releasekey(void *this,void *key) {
+}
+
+/**
+ * This callback function writes a representation of an item into
+ * a character buffer.
+ */
+static int integeritem_tostring(void *this,void *item,char *buffer,int limit) {
+    return snprintf( buffer, limit, "%lld", (long long) item );
+}
+
+ItemKeyFun integeritem = {
+    .hashcode = integeritem_hashcode,
+    .haskey = integeritem_haskey,
+    .itemkey = integeritem_itemkey,
+    .releasekey = integeritem_releasekey,
+    .tostring = integeritem_tostring
+};
diff --git a/typing/integeritem.h b/typing/integeritem.h
new file mode 100644 (file)
index 0000000..efa5323
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef integeritem_H
+#define integeritem_H
+
+#include <ItemKeyFun.h>
+
+/**
+ * The stringitem record declares the ItemKeyFun functions for integer
+ * items.
+ */
+extern ItemKeyFun integeritem;
+
+#endif
diff --git a/typing/stringitem.c b/typing/stringitem.c
new file mode 100644 (file)
index 0000000..ee8f2cb
--- /dev/null
@@ -0,0 +1,58 @@
+#include <string.h>
+#include <stringitem.h>
+#include <HashVector.h>
+
+/**
+ * This callback function returns the hashcode of a key. The hashcode
+ * is used for indexing into the backing Vector for finding the an
+ * item via its key. The same key must map consistently to the same
+ * hashcode while the hashtable contains an item with that key.
+ * Different keys map map to the same hashcode, in which case the
+ * Vector placement is made at the first empty or hole slot following
+ * the hashcode index.
+ */
+static unsigned long stringitem_hashcode(void *this,void *key) {
+    return HashVector_hashcode( (unsigned char*)key, strlen( (char*)key ) );
+}
+
+/**
+ * This callback function determines whether an item has a
+ * given key or not.
+ */
+static int stringitem_haskey(void *this,void *item,void *key) {
+    return strcmp( item, key ) == 0;
+}
+
+/**
+ * This callback function returns the key of an item by considering
+ * the arity and schema.
+ */
+static void *stringitem_itemkey(void *this,void *item) {
+    return item;
+}
+
+/**
+ * This callback function handles a key obtained from the itemkey
+ * callback function to reclaim temporary allocation.
+ */
+static void stringitem_releasekey(void *this,void *key) {
+}
+
+/**
+ * This callback function writes a representation of an item into
+ * a character buffer.
+ */
+static int stringitem_tostring(void *this,void *item,char *buffer,int limit) {
+    if ( item ) {
+       return snprintf( buffer, limit, "\"%s\"", (char*) item );
+    }
+    return snprintf( buffer, limit, "(null)" );
+}
+
+ItemKeyFun stringitem = {
+    .hashcode = stringitem_hashcode,
+    .haskey = stringitem_haskey,
+    .itemkey = stringitem_itemkey,
+    .releasekey = stringitem_releasekey,
+    .tostring = stringitem_tostring
+};
diff --git a/typing/stringitem.h b/typing/stringitem.h
new file mode 100644 (file)
index 0000000..5cc1a32
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef stringitem_H
+#define stringitem_H
+
+#include <ItemKeyFun.h>
+
+/**
+ * The stringitem record declares the ItemKeyFun functions for string
+ * items.
+ */
+extern ItemKeyFun stringitem;
+
+#endif
diff --git a/vector/AndQuery.c b/vector/AndQuery.c
deleted file mode 100644 (file)
index 169ff9e..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <AndQuery.h>
-
-static void AndQuery_reclaim(Query *this) {
-    AndQuery *q = (AndQuery*) this;
-    int i;
-    for ( i = 0; i < q->size; i++ ) {
-       Query_reclaim( q->conjuncts[i] );
-    }
-    free( q->conjuncts );
-    free( this );
-}
-
-static int AndQuery_next(
-    Query *this,BindingTable *bt,enum NextState state)
-{
-    AndQuery *q = (AndQuery*) 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 ( Query_next( q->conjuncts[i], bt, s ) ) {
-               continue;
-           }
-           Query_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-- ) {
-               Query_next( q->conjuncts[i], bt, restore );
-           }
-       }
-       q->active = 0;
-       return 0;
-    }
-    return 0;
-}
-
-static void AndQuery_variables(Query *this,HashVector *hv) {
-    AndQuery *q = (AndQuery*) this;
-    int i; 
-    for ( i = 0; i < q->size; i++ ) {
-       Query_variables( q->conjuncts[i], hv );
-    }
-}
-
-static struct QueryCallbacks AndQuery_def = {
-    .reclaim = AndQuery_reclaim,
-    .next = AndQuery_next,
-    .variables = AndQuery_variables
-};
-
-Query *Query_and(int n,...) {
-    va_list args;
-    AndQuery *q = (AndQuery *)
-       malloc( sizeof( AndQuery ) );
-    (*q) = (AndQuery) {
-       .def = &AndQuery_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;
-}
-
diff --git a/vector/AndQuery.h b/vector/AndQuery.h
deleted file mode 100644 (file)
index 7871eea..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef AndQuery_H
-#define AndQuery_H
-
-#include <Query.h>
-
-/**
- * AndQuery represents a conjunction of sub queries.
- * \extends Query
- * \related Query
- */
-typedef struct {
-    struct QueryCallbacks *def;
-    int active;
-    int size;
-    Query **conjuncts;
-} AndQuery;
-
-
-#endif
diff --git a/vector/AssignQuery.c b/vector/AssignQuery.c
deleted file mode 100644 (file)
index bb264aa..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <AssignQuery.h>
-
-// Release any memory.
-static void AssignQuery_reclaim(Query *this) {
-    AssignQuery *q = (AssignQuery*) this;
-    free( q->saved );
-    free( this );
-}
-
-static int AssignQuery_check(Tuple *a,Tuple *b) {
-    int i;
-    for ( i = 0; i < a->size; i++ ) {
-       char *value = a->elements[i];
-       char *current = b->elements[i];
-       if ( value && current && current != value &&
-            strcmp( current, value ) != 0 ) {
-           return 0;
-       }
-    }
-    return 1;
-}
-
-// Make names have given values and return 1. If any name has a
-// different value then return 0. Values are strings.
-static int AssignQuery_next(
-    Query *this,BindingTable *bt,enum NextState state) {
-    AssignQuery *q = (AssignQuery*) this;
-    switch ( state ) {
-    case initial:
-       if ( q->saved == 0 ) {
-           q->saved = Tuple_clone( q->names );
-       } else {
-           memcpy( q->saved, q->names, q->names->size * sizeof( void* ) );
-       }
-       BindingTable_deref( bt, q->saved );
-       // Check with new values
-       if ( AssignQuery_check( q->values, q->saved ) ) {
-           BindingTable_set_all( bt, q->names, q->values, 0 );
-           return 1;
-       }
-       // Fall through
-    case subsequent:
-    case restore:
-       if ( q->saved ) {
-           BindingTable_set_all( bt, q->names, q->saved, 1 );
-           free( q->saved );
-           q->saved = 0;
-       }
-       return 0;
-    }
-    return 0;
-}
-
-static void AssignQuery_variables(Query *this,HashVector *hv) {
-    AssignQuery *q = (AssignQuery*) this;
-    unsigned long i;
-    for ( i = 0; i < q->names->size; i++ ) {
-       HashVector_add( hv, q->names->elements[i] );
-    }
-}
-
-static struct QueryCallbacks AssignQuery_def = {
-    .reclaim = AssignQuery_reclaim,
-    .next = AssignQuery_next,
-    .variables = AssignQuery_variables
-};
-
-/**
- * Return a Query object representing an assignment of one or more
- * variables.
- */
-Query *Query_assign(int arity,Tuple *names,Tuple *values) {
-    AssignQuery *q = (AssignQuery*)
-       malloc( sizeof( AssignQuery ) );
-    (*q) = (AssignQuery) {
-       .def = &AssignQuery_def,
-       .names = names,
-       .values = values,
-       .saved = 0
-    };
-    return (Query*) q;
-}
diff --git a/vector/AssignQuery.h b/vector/AssignQuery.h
deleted file mode 100644 (file)
index 2e38b87..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef AssignQuery_H
-#define AssignQuery_H
-
-#include <QueryCallbacks.h>
-#include <Tuple.h>
-
-/**
- * AssignQuery represents an assignment of values to names.
- *
- * \extends Query
- * \related Query
- */
-typedef struct {
-    struct QueryCallbacks *def;
-    Tuple *names;
-    Tuple *values;
-    Tuple *saved;
-} AssignQuery;
-
-void AssignQuery_assign(
-    BindingTable *bt,Tuple *names,Tuple *values,int all);
-
-#endif
diff --git a/vector/Binding.c b/vector/Binding.c
deleted file mode 100644 (file)
index 9bcc0c1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <string.h>
-#include <HashVector.h>
-#include <Binding.h>
-
-/**
- * This callback function returns the hashcode of a Binding key, which
- * is its name string.
- */
-static unsigned long Binding_hashcode(void *this,void *key) {
-    return HashVector_hashcode(
-       (unsigned char *) key, strlen( (char*) key ) );
-}
-
-/**
- * This callback function determines whether a Binding item has a
- * given key or not.
- */
-static int Binding_haskey(void *this,void *item,void *key) {
-    Binding *b = (Binding*) item;
-    char *name = (char *) key;
-    return strcmp( name, (char*) b->name ) == 0;
-}
-
-/**
- * This callback function returns the key of a Binding itme, which is
- * its name string.
- */
-static void *Binding_itemkey(void *this,void *item) {
-    return ((Binding*) item)->name;
-}
-    
-
-/**
- * This callback function handles the "release" of a Binding key,
- * which is to do nothing, since the name string memory is not managed
- * here.
- */
-static void Binding_releasekey(void *this,void *key) {
-}
-
-/**
- * This callback function writes a representation of a Binding item
- * into a character buffer.
- */
-static int Binding_tostring(void *this,void *item,char *buffer,int limit) {
-    Binding *b = (Binding*) item;
-    return snprintf( buffer, limit, "{%s,%p}", b->name, b->value );
-}
-
-/**
- * This is the "item type" for Binding items.
- */
-ItemKeyFun Bindingitem = {
-    .hashcode = Binding_hashcode,
-    .haskey = Binding_haskey,
-    .itemkey = Binding_itemkey,
-    .releasekey = Binding_releasekey,
-    .tostring = Binding_tostring
-};
-
diff --git a/vector/Binding.h b/vector/Binding.h
deleted file mode 100644 (file)
index 2d1a0b3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef Binding_H
-#define Binding_H
-
-#include <ItemKeyFun.h>
-
-/**
- * \brief A Binding is an association of a (var*) name with a (void*)
- * value.
- *
- * A \b (void*)0 value marks an "unbound" value.
- */
-typedef struct Binding {
-    char *name;
-    void *value;
-} Binding;
-
-/**
- * \brief This is the applicable ItemKeyFun callbacks for a Binding
- * item.
- */
-extern ItemKeyFun Bindingitem;
-
-#endif
diff --git a/vector/BindingTable.c b/vector/BindingTable.c
deleted file mode 100644 (file)
index 2728516..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <BindingTable.h>
-#include <string.h>
-#include <stdlib.h>
-
-BindingTable *BindingTable_create() {
-    BindingTable *this = (BindingTable*) malloc( sizeof( BindingTable ) );
-    (*this) = (HashVector) {
-       .table = (Vector) {
-           .variant = Nibble_index_levels, .size = 16, .entries = 0
-       }, .fill = 0, .holes = 0, .type = &Bindingitem
-    };
-    return this;
-}
-
-void BindingTable_release(BindingTable *bt) {
-    if ( bt ) {
-       Vector_resize( &bt->table, 0, Vector_free_any, 0 );
-       free( bt );
-    }
-}
-
-void BindingTable_set(BindingTable *bt,char *name,void *value) {
-    Binding *b = (Binding*) HashVector_find( bt, name );
-    if ( b == 0 ) {
-       b = (Binding*) malloc( sizeof( Binding ) );
-       b->name = name;
-       HashVector_add( bt, b );
-    }
-    b->value = value;
-}
-
-void *BindingTable_get(BindingTable *bt,char *name) {
-    Binding *b = (Binding*) HashVector_find( bt, name );
-    return b? b->value : 0;
-}
-
-void BindingTable_deref(BindingTable *bt,Tuple *t) {
-    unsigned long i;
-    for ( i = 0; i < t->size; i++ ) {
-       if ( t->elements[i] ) {
-           t->elements[i] = BindingTable_get( bt, t->elements[i] );
-       }
-    }
-}
-
-#if 0
-int BindingTable_unify(
-    BindingTable *bt,char *n1,char *n2,int (*eq)(void*,void*)) {
-    void *v1 = BindingTable_get( bt, n1 );
-    void *v2 = BindingTable_get( bt, n2 );
-    if ( v2 && v1 == 0 ) {
-       BindingTable_set( bt, n1, v2 );
-    }
-    if ( v1 && v2 == 0 ) {
-       BindingTable_set( bt, n2, v1 );
-    }
-    return ( v1 && v2 )? ( eq? ( eq( v1, v2 ) == 0 ) : ( v1 == v2 ) ) : 1;
-}
-#endif
-
-Tuple *BindingTable_get_all(BindingTable *bt,Tuple *t) {
-    Tuple *vt = Tuple_clone( t );
-    BindingTable_deref( bt, vt );
-    return vt;
-}
-
-void BindingTable_set_all(BindingTable *bt,Tuple *nm,Tuple *vs,int all) {
-    int i;
-    for ( i = 0; i < nm->size; i++ ) {
-       BindingTable_set( bt, nm->elements[i], vs->elements[i] );
-    }
-}
diff --git a/vector/BindingTable.h b/vector/BindingTable.h
deleted file mode 100644 (file)
index aa4ee6e..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef BindingTable_H
-#define BindingTable_H
-
-#include <HashVector.h>
-#include <TupleSchema.h>
-#include <Binding.h>
-
-/**
- * A BindingTable is a chain of \ref HashVector "HashVectors" of
- * Binding items that associate a (char*) name with a (void*) value.
- */
-typedef HashVector/*<Binding>*/ BindingTable;
-
-/**
- * \brief Allocate a new \ref BindingTable.
- *
- * \returns the allocated \ref bandingtable.
- *
- * \related BindingTable
- */
-extern BindingTable *BindingTable_create();
-
-/**
- * \brief Reclaim a \ref BindingTable with all its bindings.
- *
- * \param bt is the \ref BindingTable to reclaim.
- *
- * \related BindingTable
- */
-extern void BindingTable_release(BindingTable *bt);
-
-/**
- * \brief Set a Binding in a \ref BindingTable.
- *
- * \param bt is the \ref BindingTable concerned.
- *
- * \param name is the Binding name.
- *
- * \param value is the Binding value.
- *
- * \note Binding names are equal or not by means of strcmp, and each
- * name has a at most single Binding.
- *
- * The name and the value are held as given with all memory management
- * the callers responsibility. This function will however create new
- * Binding objects and reclaim the old ones as needed.
- *
- * A value of \b 0 indicates "unbound".
- *
- * \related BindingTable
- */
-extern void BindingTable_set(BindingTable *bt,char *name,void *value);
-
-/**
- * \brief Get a Binding from a BindingTable chain.
- *
- * \param bt is the first BindingTable concerned.
- *
- * \param name is the Binding variable name.
- *
- * \returns the value of the found Binding, or \b 0 if none is found.
- *
- * \note Binding names are equal or not by means of strcmp, and each
- * name has a at most single Binding.
- *
- * \note Not also that a name can be made unbound on top of being
- * bound by setting it to \b 0.
- *
- * \related BindingTable
- */
-extern void *BindingTable_get(BindingTable *bt,char *name);
-
-/**
- * \brief Replace all names with their values.
- *
- * \param bt is the BindingTable concerned.
- *
- * \param t is the tuple of (char*) names to dereference.
- */
-extern void BindingTable_deref(BindingTable *bt,Tuple *t);
-
-/**
- * \brief Set values for names, optionally unbinding names as well.
- *
- * \param bt is the bindingtable concerned.
- *
- * \param nm is the Tuple of names to bind.
- *
- * \param vs is the Tuple of values.
- *
- * \param all is a flag to assign all (1) or only non-zero (0) values.
- *
- * \note The values tuple must be as wide as the names tuple.
- */
-extern void BindingTable_set_all(BindingTable *bt,Tuple *nm,Tuple *vs,int all);
-
-#endif
index ec0e0b41a38e18aed3b4e7f48de3180a66fc4810..a07a9169b2c1167cff10c9ba8c37430f6b15898b 100644 (file)
@@ -1,8 +1,6 @@
 #include <stdlib.h>
 #include <HashVector.h>
 
-#define SELF hv->type
-
 // Find the slot for the keyed element, and return pointer to it, or
 // to the first of holes encountered while considering collisions.
 // Returns a pointer to the place for the item, or 0 in case of OOM or
@@ -14,9 +12,9 @@ static void **HashVector_find_slot(
 {
     if ( itemkey ) {
         // Get actual key from keying item
-       key = hv->type->itemkey( SELF, key );
+       key = ItemKeyFun_itemkey( hv->type, key );
     }
-    unsigned long index = hv->type->hashcode( SELF, key ) % hv->table.size;
+    unsigned long index = ItemKeyFun_hashcode( hv->type, key ) % hv->table.size;
     *i = index;
     void **hole = 0;
     void **p = 0;
@@ -24,13 +22,13 @@ static void **HashVector_find_slot(
        p = Vector_entry( &hv->table, (*i) );
        if ( p == 0 ) {
            if ( itemkey ) {
-               hv->type->releasekey( SELF, key );
+               ItemKeyFun_releasekey( hv->type, key );
            }
            return 0; // This basically means OOM, and is a failure condition.
        }
        if ( (*p) == 0 ) {
            if ( itemkey ) {
-               hv->type->releasekey( SELF, key );
+               ItemKeyFun_releasekey( hv->type, key );
            }
            return ( hole )? hole : p; // Not found; it's place is here.
        }
@@ -38,9 +36,9 @@ static void **HashVector_find_slot(
            if ( hole == 0 ) {
                hole = p; // Remember the first hole
            }
-       } else if ( hv->type->haskey( SELF, (*p), key ) ) {
+       } else if ( ItemKeyFun_haskey( hv->type, (*p), key ) ) {
            if ( itemkey ) {
-               hv->type->releasekey( SELF, key );
+               ItemKeyFun_releasekey( hv->type, key );
            }
            return p; // Found
        }
@@ -49,7 +47,7 @@ static void **HashVector_find_slot(
        }
        if ( (*i) == index ) {
            if ( itemkey ) {
-               hv->type->releasekey( SELF, key );
+               ItemKeyFun_releasekey( hv->type, key );
            }
            return 0; // Overfull HashVector!
        }
diff --git a/vector/ItemKeyFun.h b/vector/ItemKeyFun.h
deleted file mode 100644 (file)
index 93c0200..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef ItemKeyFun_H
-#define ItemKeyFun_H
-
-#include <stdio.h>
-
-/**
- * \struct ItemKeyFun
- *
- * ItemKeyFun provides a meta-level representation for abstracting
- * items as pairs of keys and payload, and having a hashcode mapping
- * for keys. The key part is used for identifying items under the idea
- * that all items that have the same key are the same; distinct
- * representations of the same abstract entity. The hashcode scrambles
- * the key part in a consistent way into an ideal table index for the
- * items that have that key. Different keys may yield the same
- * hashcode.
- */
-typedef struct {
-
-#define SELF void *this
-    /**
-     * This callback function should return the hashcode of a key. The
-     * hashcode is used for indexing into the backing Vector for
-     * finding the an item via its key. The same key must map
-     * consistently to the same hashcode while the hashtable contains
-     * an item with that key. Different keys map map to the same
-     * hashcode, in which case the Vector placement is made at the
-     * first empty or hole slot following the hashcode index.
-     */
-    unsigned long (*hashcode)(SELF,void *key);
-
-    /**
-     * This callback function should determine whether an item has a
-     * given key or not.
-     */
-    int (*haskey)(SELF,void *item,void *key);
-
-    /**
-     * This callback function should return a (possibly temporary) key
-     * of an item. It can be anything (i.e., with or without internal
-     * structure) as it is treated as an identifier that other
-     * callbacks recognize. It is merely understood as a value in an
-     * identity domain.
-     */
-    void *(*itemkey)(SELF,void *item);
-
-    /**
-     * This callback function should handle a key obtained from the
-     * itemkey callback function, e.g., reclaim temporary allocation.
-     */
-    void (*releasekey)(SELF,void *key);
-
-    /**
-     * This callback function writes a representation of an item into
-     * a character buffer.
-     */
-    int (*tostring)(SELF,void *item,char *buffer,int limit);
-
-#undef SELF
-} ItemKeyFun;
-
-#endif
index a3feec435d9f38d957cc082763f0d6ad8760801f..ea8e8de71a6b93c5d3f34c91553d173110fee597 100644 (file)
@@ -1,34 +1,7 @@
-LIBRARY = libvector.a
+LIBRARY = librrqvector.a
 LIBOBJS = Vector.o HashVector.o
-LIBOBJS += Tuple.o TupleSchema.o integeritem.o stringitem.o Binding.o
-LIBOBJS += BindingTable.o Relation.o Query.o
-LIBOBJS += AssignQuery.o RelationQuery.o
-LIBOBJS += NotQuery.o AndQuery.o OrQuery.o
-#LIBOBJS += View.o
 
 default: $(LIBRARY)
-
-all: default
-
-CFLAGS = -Wall -g -fmax-errors=1 -I.
-LDLIBS = -lm
-
-%.h:
-       echo "#ifndef ${@:.h=_H}" > $@
-       echo "#define ${@:.h=_H}" >> $@
-       echo "#endif" >> $@
-
-define STDCC
-.INTERMEDIATE: $1.o
-CLEANRM += $1.o
-$1.o: $1.c | $1.h
-endef
-
-$(foreach OBJ,$(LIBOBJS:.o=),$(eval $(call STDCC,$(OBJ))))
-
 CLEANRM += $(LIBRARY)
-$(LIBRARY): $(LIBOBJS)
-       $(AR) r $@ $^
 
-clean:
-       rm -f $(CLEANRM)
+include ../common.mk
diff --git a/vector/NotQuery.c b/vector/NotQuery.c
deleted file mode 100644 (file)
index 8418715..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <stdlib.h>
-#include <NotQuery.h>
-
-static void NotQuery_reclaim(Query *this) {
-    NotQuery *q = (NotQuery*) this;
-    Query_reclaim( q->query );
-    free( this );
-}
-
-static int NotQuery_next(
-    Query *this,BindingTable *bt,enum NextState state)
-{
-    NotQuery *q = (NotQuery*) this;
-    if ( state == initial ) {
-       if ( Query_next( q->query, bt, initial ) ) {
-           Query_next( q->query, bt, restore );
-           return 0;
-       }
-       return 1;
-    }
-    return 0;
-}
-
-static void NotQuery_variables(Query *this,HashVector *hv) {
-    Query_variables( ((NotQuery*) this)->query, hv );
-}
-
-static struct QueryCallbacks NotQuery_def = {
-    .reclaim = NotQuery_reclaim,
-    .next = NotQuery_next,
-    .variables = NotQuery_variables
-};
-
-Query *Query_not(Query *q) {
-    NotQuery *nq = (NotQuery*) malloc( sizeof( NotQuery ) );
-    (*nq) = (NotQuery) {
-       .def = &NotQuery_def,
-       .query = q
-    };
-    return (Query*) nq;
-}
diff --git a/vector/NotQuery.h b/vector/NotQuery.h
deleted file mode 100644 (file)
index f2bf7ed..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef NotQuery_H
-#define NotQuery_H
-
-#include <Query.h>
-
-/**
- * NotQuery represents logical negation.
- *
- * \extends Query
- */
-typedef struct NotQuery {
-    struct QueryCallbacks *def;
-    Query *query;
-} NotQuery;
-
-#endif
diff --git a/vector/OrQuery.c b/vector/OrQuery.c
deleted file mode 100644 (file)
index 5a48e5e..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <OrQuery.h>
-
-static void OrQuery_reclaim(Query *this) {
-    OrQuery *q = (OrQuery*) this;
-    int i;
-    for ( i = 0; i < q->size; i++ ) {
-       Query_reclaim( q->disjuncts[i] );
-    }
-    free( q->disjuncts );
-    free( this );
-}
-
-static int OrQuery_next( Query *this,BindingTable *bt,enum NextState state) {
-    OrQuery *q = (OrQuery*) 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 ( Query_next( q->disjuncts[i], bt, s ) ) {
-               q->index = i;
-               return 1;
-           }
-           Query_next( q->disjuncts[i], bt, restore );
-           s = initial;
-       }
-       q->index = -1;
-       return 0;
-    case restore:
-       if ( i >= 0 ) {
-           Query_next( q->disjuncts[i], bt, restore );
-           q->index = -1;
-       }
-       return 0;
-    }
-    return 0;
-}
-
-static void OrQuery_variables(Query *this,HashVector *hv) {
-    OrQuery *q = (OrQuery*) this;
-    int i; 
-    for ( i = 0; i < q->size; i++ ) {
-       Query_variables( q->disjuncts[i], hv );
-    }
-}
-
-static struct QueryCallbacks OrQuery_def = {
-    .reclaim = OrQuery_reclaim,
-    .next = OrQuery_next,
-    .variables = OrQuery_variables
-};
-
-Query *Query_or(int n,...) {
-    va_list args;
-    OrQuery *q = (OrQuery *)
-       malloc( sizeof( OrQuery ) );
-    (*q) = (OrQuery) {
-       .def = &OrQuery_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* );
-    }
-    va_end( args );
-    return (Query*) q;
-}
-
diff --git a/vector/OrQuery.h b/vector/OrQuery.h
deleted file mode 100644 (file)
index 9528356..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef OrQuery_H
-#define OrQuery_H
-
-#include <Query.h>
-
-/**
- * OrQuery represents a disjunction of sub queries.
- *
- * \extends Query
- */
-typedef struct {
-    struct QueryCallbacks *def;
-    int index;
-    int size;
-    Query **disjuncts;
-} OrQuery;
-
-#endif
diff --git a/vector/Query.c b/vector/Query.c
deleted file mode 100644 (file)
index 94a39d7..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#include <Query.h>
-
-/**
- * \brief Trampoline for the callback function to reclaim the Query
- * memory for a given Query.
- *
- * \param this is the specific \ref Query concerned.
- *
- * Ground queries recalim their own state memory. Composite
- * queries first propagate the reclaim call to its components, and
- * thereafter reclaim their local state memory.
- */
-void Query_reclaim(Query *this) {
-    this->def->reclaim( this );
-}
-
-/**
- * \brief Trampoline for the callback function to update the Binding
- * table with a succession of alternative bindings.
- *
- * \param this is the specific \ref Query concerned.
- *
- * \param bt is the Binding table to set bindings in.
- *
- * \param s is the call "sub-command" for the function.
- *
- * \returns 1 if a new Binding is provided and 0 otherwise.
- *
- * This function is called repeatedly for successively obtaining
- * the alternative bindings that satisfy the Query. The "initial"
- * state sub-command tells the function to capture the incoming
- * BindingTable state so that the function can later restore it
- * upon the "restore" sub-command. Upon the "initial" command, the
- * function also sets up the Binding table with its first Binding
- * alternative. This is followed by a series of "subsequent"
- * sub-command calls for the function to change the BindingTable
- * for its succession of Binding alternatives. The function should
- * return 1 after any successful Binding setup, and return 0 when
- * it cannot setup any (more) Binding.
- */
-int Query_next(Query *this,BindingTable *bt,enum NextState state) {
-    return this->def->next( this, bt, state );
-}
-
-/**
- * \brief Trampoline for the callback function that adds its binding
- * names to the hashvector.
- */
-void Query_variables(Query *this,HashVector *hv) {
-    this->def->variables( this, hv );
-}
-
-void Query_eval(
-    Query *q,BindingTable *bt,
-    int (*consequent)(BindingTable *bt,void *data),
-    void *data )
-{
-    if ( Query_next( q, bt, initial ) && consequent( bt, data ) ) {
-       while ( Query_next( q, bt, subsequent ) && consequent( bt, data ) );
-    }
-    (void) Query_next( q, bt, restore );
-}
-
-/* ==================== Snapshotting a query ==================== */
-
-/**
- * The data used for bindings capture in  snapshotting.
- */
-struct Query_snapshot_data {
-    Tuple *names;
-    Vector *v;
-};
-
-static int Query_snapshot_capture(BindingTable *bt,void *data) {
-    struct Query_snapshot_data *d = (struct Query_snapshot_data*) data;
-    Tuple *values = Tuple_clone( d->names );
-    BindingTable_deref( bt, values );
-    Vector_append( d->v, values );
-    return 1;
-}
-
-int Query_snapshot(Query *q,Tuple *names,Vector *v) {
-    BindingTable *bt = BindingTable_create( 0 );
-    struct Query_snapshot_data data = {        .names = names, .v = v };
-    Vector_resize( v, 0, Vector_free_any, 0 );
-    Query_eval( q, bt, Query_snapshot_capture, &data );
-    return v->size;
-}
diff --git a/vector/Query.h b/vector/Query.h
deleted file mode 100644 (file)
index 4b2fa6a..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-#ifndef Query_H
-#define Query_H
-
-#include <QueryCallbacks.h>
-#include <BindingTable.h>
-#include <Relation.h>
-
-/**
- * A Query is an implementation of a generic ABI over relations. It's
- * more or less a "virtual Relation" representing a logical composite
- * access of actual relations, and as such its active part is held in
- * a separate \ref Querytype record similar to how \ref ItemKeyFun
- * records define valye types.
- */
-typedef struct Query {
-    struct QueryCallbacks *def;
-} Query;
-
-/**
- * \brief Trampoline for the callback function to reclaim the Query
- * memory for a given Query.
- *
- * \param this is the specific \ref Query concerned.
- *
- * Ground queries recalim their own state memory. Composite
- * queries first propagate the reclaim call to its components, and
- * thereafter reclaim their local state memory.
- */
-extern void Query_reclaim(Query *this);
-
-/**
- * \brief Trampoline for the callback function to update the Binding
- * table with a succession of alternative bindings.
- *
- * \param this is the specific \ref Query concerned.
- *
- * \param bt is the Binding table to set bindings in.
- *
- * \param s is the call "sub-command" for the function.
- *
- * \returns 1 if a new Binding is provided and 0 otherwise.
- *
- * This function is called repeatedly for successively obtaining
- * the alternative bindings that satisfy the Query. The "initial"
- * state sub-command tells the function to capture the incoming
- * BindingTable state so that the function can later restore it
- * upon the "restore" sub-command. Upon the "initial" command, the
- * function also sets up the Binding table with its first Binding
- * alternative. This is followed by a series of "subsequent"
- * sub-command calls for the function to change the BindingTable
- * for its succession of Binding alternatives. The function should
- * return 1 after any successful Binding setup, and return 0 when
- * it cannot setup any (more) Binding.
- */
-extern int Query_next(Query *this,BindingTable *bt,enum NextState state);
-
-/**
- * \brief Trampoline for the callback function that adds its binding
- * names to the hashvector.
- *
- * \param this is the query concerned.
- *
- * \param hv is the HashVector for collating names.
- */
-extern void Query_variables(Query *this,HashVector *hv);
-
-
-
-
-/**
- * \brief Creates an assignment Query.
- *
- * \param arity is the assignment tuple arity.
- *
- * \param names is the (char*) names to assign.
- *
- * \param values is the (void*) values to asign.
- *
- * The two tuples must have the same arity for assigning names[i] to
- * values[i]. This Query makes the given names have the given values,
- * once for each (*next) call following a (*reset) call.
- *
- * \related Query
- */
-extern Query *Query_assign(int arity,Tuple *names,Tuple *values);
-
-/**
- * \brief Create a Query record for lookup data in a Relation.
- *
- * \param r is the relation being queried.
- *
- * \param names is a same-arity tuple of binding names for the
- * columns, using \b 0 for unnamed columns.
- *
- * \param values is a same--arity tuple of query values, using \b 0 for
- * columns to enumerate.
- *
- * The names and values tuples identify bindings and values to use for
- * the search query, and which bindings to set up from the successive
- * results. Names that are bound beforhand identify constraining
- * values, and the names that are unbound gain successive values from
- * the matching tuples.
- *
- * \related Query
- */
-extern Query *Query_Relation(Relation *r,Tuple *names,Tuple *values);
-
-/**
- * \brief Create a Query record for a conjunction of queries.
- *
- * \param n is the number of sub queries.
- *
- * \param ... are the sub queries.
- *
- * The conjunction query processes the sub queries in order resulting
- * in the sequence of their combined bindings.
- *
- * \related Query
- */
-extern Query *Query_and(int n,...);
-
-/**
- * \brief Create a Query record for a disjunction of queries.
- *
- * \param n is the number of sub queries.
- *
- * \param ... are the sub queries.
- *
- * The disjunction query processed the sub queries in order to find
- * all their individual "true" binding combinations. It processes one
- * sub query at a time to exhaustion and provide their individudal
- * binding sequences separately.
- *
- * \related Query
- */
-extern Query *Query_or(int n,...);
-
-/**
- * \brief Invoke a consequent callback function for each successful
- * binding of a query.
- *
- * \param q is the antecedent query to process.
- *
- * \param bt is the binding table to use.
- *
- * \param consequent is the callback function to invoke for each
- * binding.
- * \param data is the caller's context data.
- *
- * This function prrocesses the Query for establishing its binding
- * sequence and inokes the consequent callback function for each
- * binding as it is provided.
- * 
- * \related Query
- */
-extern void Query_eval(
-    Query *q,BindingTable *bt,
-    int (*consequent)(BindingTable *bt,void *data),
-    void *data );
-
-/**
- * \brief Collect all bindings of query.
- *
- * \param q is the query to enumerate.
- *
- * \param names is the binding names to track.
- *
- * \param results is the result store of bindings for the names.
- *
- * \returns the number of results.
- *
- * This function evaluates the query for one round of bindings, and
- * stores their value \ref Tuple Tuples in the given vector. The given
- * vector is first cleared, and any item is reclaimed with \b free.
- * Correspondingly the binding \ref Tuple Tuples are allocated with \b
- * malloc for the caller to reclaim (possibly via a successive call to
- * this function).
- */
-//extern int Query_snapshot(Query *q,Tuple *names,Vector *v);
-
-/**
- * \brief Creates an NotQuery.
- *
- * \param query is the query to negate.
- *
- * \related Query
- */
-extern Query *Query_not(Query *values);
-
-#endif
diff --git a/vector/QueryCallbacks.h b/vector/QueryCallbacks.h
deleted file mode 100644 (file)
index 5d36e0b..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef QueryCallbacks_H
-#define QueryCallbacks_H
-
-#include <BindingTable.h>
-
-typedef struct Query Query; // forward
-
-enum NextState {
-    /**
-     * This state tells the "next" function that it should capture the
-     * incoming BindingTable state and provide the initial Binding of
-     * a new sucession of bindings.
-     */
-    initial, 
-    /**
-     * This state tells the "next" function that it should update the
-     * bidning table with a subsequent Binding in the current
-     * succession of bindings.
-     */
-    subsequent,
-    /**
-     * This state tells the "next" function that it should just
-     * restore the Binding table to its incoming state.
-     */
-    restore
-};
-
-/**
- * A struct Query_callbacks record defines the callbacks for a
- * specific Query type.
- */
-typedef struct QueryCallbacks {
-    /**
-     * \brief Callback function to reclaim the Query memory for a
-     * given Query.
-     *
-     * \param this is the specific \ref Query concerned.
-     *
-     * Ground queries recalim their own state memory. Composite
-     * queries first propagate the reclaim call to its components, and
-     * thereafter reclaim their local state memory.
-     */
-    void (*reclaim)(Query *this);
-
-    /**
-     * \brief Callback function to update the Binding table with a
-     * succession of alternative bindings.
-     *
-     * \param this is the specific \ref Query concerned.
-     *
-     * \param bt is the Binding table to set bindings in.
-     *
-     * \param s is the call "sub-command" for the function.
-     *
-     * \returns 1 if a new Binding is provided and 0 otherwise.
-     *
-     * This function is called repeatedly for successively obtaining
-     * the alternative bindings that satisfy the Query. The "initial"
-     * state sub-command tells the function to capture the incoming
-     * BindingTable state so that the function can later restore it
-     * upon the "restore" sub-command. Upon the "initial" command, the
-     * function also sets up the Binding table with its first Binding
-     * alternative. This is followed by a series of "subsequent"
-     * sub-command calls for the function to change the BindingTable
-     * for its succession of Binding alternatives. The function should
-     * return 1 after any successful Binding setup, and return 0 when
-     * it cannot setup any (more) Binding.
-     */
-    int (*next)(Query *this,BindingTable *bt,enum NextState state);
-
-    /**
-     * \brief This callback function adds its binding names to the
-     * hashvector.
-     */
-    void (*variables)(Query *this,HashVector *hv);
-} QueryCallbacks;
-
-#endif
diff --git a/vector/Relation.c b/vector/Relation.c
deleted file mode 100644 (file)
index 868a477..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <Relation.h>
-
-Relation *Relation_create(TupleSchema *schema) {
-    Relation *r = (Relation *) malloc( sizeof( Relation ) );
-    (*r) = (Relation) {
-       .content = (HashVector) {
-           .table = (Vector) {
-               .variant = Nibble_index_levels,
-               .size = 16,
-               .entries = 0
-           },
-           .fill = 0, .holes = 0, .type = (ItemKeyFun*) schema
-       },
-       .constraints = (Vector) {
-           .variant = single_index_level,
-           .size = 0,
-           .entries = 0
-       },
-    };
-    return r;
-}
-
-#define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
-#define COPY(T,P) COPYA(T,P,1)
-
-// Add an indexing HashVector to the Relation using the given column
-// flags with 1 indicating key column and 0 indicating value column.
-int Relation_add_constraint(Relation *r,...) {
-    va_list ap;
-    TupleSchema *ts = (TupleSchema *) r->content.type;
-    Tuple *columns = Tuple_clone( ts->columns );
-    int i = 0;
-    va_start( ap, r );
-    for ( ; i < columns->size; i++ ) {
-       if ( va_arg( ap, int ) == 0 ) {
-           columns->elements[i] = 0;
-       }
-    }
-    va_end( ap );
-    ts = TupleSchema_create( columns );
-    i = (int) r->constraints.size;
-    Vector_append(
-       &r->constraints,
-       HashVector_create( Nibble_index_levels, (ItemKeyFun*) ts ) );
-    return i;
-}
-
-//============== Adding an item =============
-// Iteration context for adding or Querying a Relation
-typedef struct {
-    Relation *rel;
-    HashVector knockouts;
-    void *item;
-} Knockout;
-
-// Determine matches to ((Knockout*)data)->key in
-// (HashVector*)item, optionally using ((Knockout*)data)->columns
-// for ignoring full matches to the key tuple.
-static int knockout_check(VectorIndex index,void *item,void *data) {
-    Knockout *kod = (Knockout*) data;
-    void *key = kod->item;
-    HashVector *hv = (HashVector*) item;
-    TupleSchema *type = (TupleSchema *)hv->type;
-    VectorIndex i = 0;
-    for ( ; i < hv->table.size; i++ ) {
-       void *old = HashVector_next( hv, &i );
-       if ( old ) {
-           if ( key && type->base.haskey( type, old, key ) == 0 ) {
-               continue;
-           }
-           HashVector_add( &kod->knockouts, old );
-       }
-    }
-    return 0;
-}
-
-// delete the (tuple*)item from the (HashVector*)data
-static int knockout_delete(VectorIndex index,void *item,void *data) {
-    HashVector_delete( (HashVector*) item, data );
-    return 0;
-}
-
-// add the (tuple*)data to the (HashVector*)item
-static int knockout_add(VectorIndex index,void *item,void *data) {
-    HashVector_add( (HashVector*)item, data );
-    return 0;
-}
-
-// Find and remove all collisions for a Query, unless "add" is
-// non-zero in which case the function aborts if there is any match in
-// the main content.
-static int knockout_clear(Knockout *this,Relation *r,Tuple *item,int add) {
-    (*this) = (Knockout) {
-       .rel = r,
-       .knockouts = {
-           .table = {
-               .variant = Nibble_index_levels, .size = 16, .entries = 0
-           },
-           .fill = 0, .holes = 0, .type = r->content.type,
-       },
-       .item = item
-    };
-    knockout_check( 0, &r->content, this );
-    if ( add ) {
-       if ( this->knockouts.fill > 0 ) {
-           return 0;
-       }
-       // Find all constraint knockouts for addition
-       Vector_iterate( &r->constraints, 0, knockout_check, this );
-    }
-    if ( this->knockouts.fill > 0 ) {
-       // Delete them from all tables
-       VectorIndex i;
-       for ( i = 0; i < this->knockouts.table.size; i++ ) {
-           void *t = HashVector_next( &this->knockouts, &i );
-           if ( t ) {
-               HashVector_delete( &r->content, t );
-               Vector_iterate( &r->constraints, 0, knockout_delete, t );
-           }
-       }
-    }
-    return 1;
-}
-
-// add a tuple to a Relation and return a Vector of knocked out
-// tuples, if any, or 0 otherwise.
-Vector *Relation_add(Relation *r,Tuple *item) {
-    Knockout data;
-    if ( knockout_clear( &data, r, item, 1 ) ) {
-       // Add the new tuple
-       HashVector_add( &r->content, item );
-       Vector_iterate( &r->constraints, 0, knockout_add, item );
-       return HashVector_contents( &data.knockouts, single_index_level, 0 );
-    }
-    return 0;
-}
-
-Vector *Relation_delete(Relation *r,Tuple *item) {
-    Knockout data;
-    (void) knockout_clear( &data, r, item, 0 );
-    return HashVector_contents( &data.knockouts, single_index_level, 0 );
-}
-
-void *Relation_next(Relation *r,VectorIndex *index,Tuple *query) {
-    HashVector *hv = &r->content;
-    void *key = query;
-    TupleSchema *type = (TupleSchema *) hv->type;
-    for ( ; (*index) < hv->table.size; (*index)++ ) {
-       void *old = HashVector_next( hv, index );
-       if ( old ) {
-           if ( key && type->base.haskey( type, old, key ) == 0 ) {
-               continue;
-           }
-           return old;
-       }
-    }
-    (*index) = hv->table.size;
-    return 0;
-}
-
diff --git a/vector/Relation.h b/vector/Relation.h
deleted file mode 100644 (file)
index 852101a..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifndef Relation_H
-#define Relation_H
-
-#include <HashVector.h>
-#include <TupleSchema.h>
-
-/**
- * A Relation is an implementation of a tuple set with (optional) key
- * constraints. The store is a \ref HashVector whose \b type is a \ref
- * TupleSchema that defines the columns. The key constraints are
- * represented as additional \ref HashVector "HashVectors" whose \ref
- * TupleSchema "TupleSchemas" are clones of the column schema with
- * some columns excluded.
- *
- * \extends HashVector
- */
-typedef struct {
-    /**
-     * This is the primary content store for the Relation. Its type
-     * should be a TupleSchema declaring the "item types" for the
-     * Relation columns.
-     */
-    HashVector content;
-
-    /**
-     * This is a collection of relational constraints, if any, which
-     * are represented as HashVectors whose TupleSchemas are clones of
-     * the content TupleSchema with some columns excluded.
-     */
-    Vector constraints;
-} Relation;
-
-/**
- * \brief Create a Relation for the given TupleSchema.
- *
- * \param schema is the column schema
- *
- * \returns the allocated Relation record.
- *
- * The given TupleSchema is set up as the type of the content
- * HashVector, which also is initialised as a Nibble_index_levels
- * variant Vector.
- *
- * \related Relation
- */
-extern Relation *Relation_create(TupleSchema *schema);
-
-/**
- * \brief Add a key constraint to a \ref Relation.
- *
- * \param r is the Relation concerned.
- *
- * \param ... are the column flags indicating key (1) or value (0)
- * column for all columns.
- *
- * \returns the index into the constraints \ref Vector for the added
- * constraint.
- *
- * This function adds a \ref HashVector with a \ref TupleSchema as its
- * item type cloned from the content type and then modified to
- * represent the constraint. Namely that the key columns have their
- * "column type" set while value columsn are reset.
- *
- * The \b constraint \ref HashVectors are used when \ref tuple
- * "tuples" are added to the \ref Relation so as to identify the
- * already contained \ref tuple "tuples" that contradict the addition
- * by means of having the same constraint key. The already contained
- * \ref tuple "tuples" are then "knocked out" from the Relation by the
- * new addition.
- *
- * \see Relation_add
- * \related Relation
- */
-extern int Relation_add_constraint(Relation *r,...);
-
-/**
- * \brief Add the tuple to the Relation.
- *
- * \param r is the \ref Relation concerned.
- *
- * \param t is the \ref tuple to add.
- *
- * \returns a Vector of all knocked out tuples.
- *
- * This function adds the \ref tuple \b t to the \ref Relation \b r,
- * and it returns a \ref Vector (single_index_level variant) of all
- * same-key constraint tuples. The returned Vector is malloc-ed and it
- * must be free-ed by the caller. If the tuple is already contained or
- * there are no other same-key tuples knocked out, then \b 0 is
- * returned.
- *
- * \related Relation
- */
-extern Vector *Relation_add(Relation *r,Tuple *t);
-
-/**
- * \brief Delete all tuples matching to the Query \ref tuple fromt the
- * \ref Relation.
- *
- * \param r is the \ref Relation concerned.
- *
- * \param t is the \ref tuple to delete.
- *
- * \returns a \Vector Vector of all knocked out tuples, i.e. the
- * same-key tuples, if any, contained in the Relation
- *
- * Note that deletion uses a "Query" tuple, which means that some
- * columns may be null to mark that them match to any value.
- *
- * \related Relation
- */
-extern Vector *Relation_delete(Relation *r,Tuple *query);
-
-/**
- * \brief Return the next \ref tuple in the \ref Relation that matches
- * to the Query \ref tuple, at or after the index.
- *
- * \param r is the \ref Relation concerned.
- *
- * \param index is a pointer to the \ref Vector index to update.
- *
- * \param Query is a Query \tuple tuple for selection of certain
- * column values.
- *
- * \returns any such matching \tuple tuple and an updateed *index.
- *
- * \related Relation
- */
-extern void *Relation_next(Relation *r,VectorIndex *index,Tuple *query);
-
-/**
- * \brief Lay out a dynamic \ref Relation initializer for a Relation
- * wth the given column "types".
- *
- * This defines a \ref Relation intializer that creates the \ref
- * TupleSchema for the given columns.
- *
- * \note The initializer cannot be used statically.
- *
- * The \b content \ref HashVector is a \ref Nibble_index_level variant
- * with an initial size of 16 slots.
- *
- * The constraints \ref Vector is a \ref BitPair_index_level variant
- * with initial size 0.
- *
- * The \b content \ref HashVector \b type is set up with an allocated
- * \ref TupleSchema that has an allocated \ref tuple that declares the
- * column "types" view the given \ref ItemKeyFun pointers. Any add
- * constraints will need to clone that \ref TupleSchema and then clear
- * the column slots for the constraint value columns, typically by
- * using \ref TupleSchema_mask for this.
- *
- * \related Relation
- */
-#define RELATION(...) (Relation) { \
-    .content = { \
-        .table = { .variant = Nibble_index_levels, .size=16, .entries=0 }, \
-        .fill = 0, .holes = 0, \
-       .type = (ItemKeyFun*) TUPLESCHEMA( __VA_ARGS__ )        \
-    }, \
-    .constraints = { .variant = BitPair_index_levels, .size=0, .entries=0 } \
-}
-
-#endif
diff --git a/vector/RelationQuery.c b/vector/RelationQuery.c
deleted file mode 100644 (file)
index aa4bdbd..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <RelationQuery.h>
-
-// Release any memory.
-static void RelationQuery_reclaim(Query *this) {
-    RelationQuery *q = (RelationQuery*) this;
-    free( q->saved );
-    free( this );
-}
-
-// Make names have given values and return 1. If any name has a
-// different value then return 0. Values are strings.
-static int RelationQuery_next(
-    Query *this,BindingTable *bt,enum NextState state) {
-    RelationQuery *q = (RelationQuery*) this;
-    VectorIndex index = q->index + 1;
-    switch ( state ) {
-    case initial:
-       if ( q->saved == 0 ) {
-           q->saved = Tuple_clone( q->names );
-       } else {
-           memcpy( q->saved, q->names, q->names->size * sizeof( void* ) );
-       }
-       BindingTable_deref( bt, q->saved );
-       index = 0;
-       // Fall through
-    case subsequent:
-       for ( ; index < q->rel->content.table.size; index++ ) {
-           Tuple *values = Relation_next( q->rel, &index, q->values );
-           if ( values ) {
-               q->index = index;
-               BindingTable_set_all( bt, q->names, values, 1 );
-               return 1;
-           }
-       }
-    case restore:
-       if ( q->saved ) {
-           BindingTable_set_all( bt, q->names, q->saved, 1 );
-           free( q->saved );
-           q->saved = 0;
-       }
-       return 0;
-    }
-    return 0;
-}
-
-static void RelationQuery_variables(Query *this,HashVector *hv) {
-    RelationQuery *q = (RelationQuery*) this;
-    unsigned long i;
-    for ( i = 0; i < q->names->size; i++ ) {
-       HashVector_add( hv, q->names->elements[i] );
-    }
-}
-
-static struct QueryCallbacks RelationQuery_def = {
-    .reclaim = RelationQuery_reclaim,
-    .next = RelationQuery_next,
-    .variables = RelationQuery_variables
-};
-
-/**
- * Return a Query object representing an Relation of one or more
- * variables.
- */
-Query *Query_relation(Relation *r,Tuple *names,Tuple *values) {
-    RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) );
-    (*q) = (RelationQuery) {
-       .def = &RelationQuery_def,
-       .rel = r,
-       .names = names,
-       .values = values,
-       .saved = 0
-    };
-    return (Query*) q;
-}
-
diff --git a/vector/RelationQuery.h b/vector/RelationQuery.h
deleted file mode 100644 (file)
index 4c50a53..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef RelationQuery_H
-#define RelationQuery_H
-
-#include <Relation.h>
-#include <Query.h>
-
-/**
- * RelationQuery represents a ground query on a relation.
- * \extends Query
- * \related Query
- */
-typedef struct {
-    struct QueryCallbacks *def;
-    Relation *rel;
-    VectorIndex index;
-    Tuple *names;
-    Tuple *values;
-    Tuple *saved;
-} RelationQuery;
-
-#endif
diff --git a/vector/Tuple.c b/vector/Tuple.c
deleted file mode 100644 (file)
index 2b5b04e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <Tuple.h>
-
-// Allocate zero-ed
-Tuple *Tuple_calloc(unsigned long arity) {
-    Tuple *t = (Tuple *) malloc( sizeof( Tuple ) + arity * sizeof( void* ) );
-    t->size = arity;
-    memset( t->elements, 0, arity * sizeof( void* ) );
-    return t;
-}
-
-// Allocate with values
-Tuple *Tuple_create(int arity,...) {
-    va_list ap;
-    int i;
-    Tuple *t = (Tuple *) malloc( sizeof( Tuple ) + arity * sizeof( void* ) );
-    t->size = arity;
-    va_start( ap, arity );
-    for ( i = 0; i < arity; i++ ) {
-       t->elements[i] = va_arg( ap, void* );
-    }
-    va_end( ap );
-    return t;
-}
-
-// Duplicate
-Tuple *Tuple_clone(Tuple *t) {
-    unsigned long size = t->size * sizeof( void* );
-    Tuple *ct = (Tuple *) malloc( sizeof( Tuple ) + size );
-    memcpy( ct, t, size );
-    return ct;
-}
diff --git a/vector/Tuple.h b/vector/Tuple.h
deleted file mode 100644 (file)
index ea439c5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef Tuple_H
-#define Tuple_H
-
-#include <ItemKeyFun.h>
-
-typedef struct TupleSchema TupleSchema;
-
-/**
- * A Tuple is a "self typed" array of elements.
- */
-typedef struct {
-    /**
-     * The number of elements.
-     */
-    unsigned long size;
-    /**
-     * Base address for element pointers, which thus follow this
-     * struct in memory.
-     */
-    void *elements[];
-} Tuple;
-
-/**
- * \brief Create an untyped tuple with given values.
- *
- * \related Tuple
- */
-extern Tuple *Tuple_create(int arity,...);
-
-/**
- * \brief Create an untyped tuple with 0 values.
- *
- * \related Tuple
- */
-extern Tuple *Tuple_calloc(unsigned long arity);
-
-/**
- * \brief Create a tuple as a clone of a given tuple.
- *
- * \related Tuple
- */
-extern Tuple *Tuple_clone(Tuple *t);
-
-#endif
diff --git a/vector/TupleSchema.c b/vector/TupleSchema.c
deleted file mode 100644 (file)
index 5a92b64..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <TupleSchema.h>
-
-/**
- * This callback function returns the hashcode of a key.
- *
- * \param this is a pointer to the ItemKeyFun record from where this
- * callback got invoked
- *
- * \param key is the key to produce a hascode for
- *
- * \returns the hashcode which is a VectorIndex (i.e. unsigned long)
- *
- * The hashcode is used for indexing into the backing Vector for
- * finding the an item via its key. The same key must map consistently
- * to the same hashcode while the hashtable contains an item with that
- * key. Different keys map map to the same hashcode, in which case the
- * Vector placement is made at the first empty or hole slot following
- * the hashcode index.
- */
-static unsigned long TupleSchema_hashcode(void *this,void *key) {
-    TupleSchema *def = (TupleSchema *) this;
-    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
-    Tuple *kp = (Tuple*) key;
-    int i = 0;
-    unsigned long value = 5381;
-    for ( ; i < def->columns->size; i++ ) {
-       if ( columns[i] ) {
-           value <<= 3;
-           if ( kp->elements[i] ) {
-               value += columns[i]->hashcode( columns[i], kp->elements[i] );
-           }
-       }
-       value += 17;
-    }
-    return value;
-}
-
-/**
- * This callback function determines whether an item has a
- * given key or not.
- */
-static int TupleSchema_haskey(void *this,void *item,void *key) {
-    TupleSchema *def = (TupleSchema *) this;
-    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
-    Tuple *kp = (Tuple*) key;
-    Tuple *tp = (Tuple*) item;
-    int i = 0;
-    for ( ; i < def->columns->size; i++ ) {
-       if ( columns[i] && kp->elements[i] ) {
-           if ( columns[i]->haskey(
-                    columns[i], tp->elements[i], kp->elements[i] ) == 0 ) {
-               return 0;
-           }
-       }
-    }
-    return 1;
-}
-
-
-/**
- * This callback function returns the key of an item by considering
- * the arity and mask.
- */
-static void *TupleSchema_itemkey(void *this,void *item) {
-    TupleSchema *def = (TupleSchema *) this;
-    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
-    Tuple *tp = (Tuple*) item;
-    Tuple *key = Tuple_clone( tp );
-    int i;
-    for ( i = 0; i < def->columns->size; i++ ) {
-       if ( columns[i] ) {
-           key->elements[i] = columns[i]->itemkey(
-               columns[i], tp->elements[i] );
-       } else {
-           key->elements[i] = 0;
-       }
-    }
-    return (void*) key;
-}
-
-/**
- * This callback function handles a key obtained from the itemkey
- * callback function to reclaim temporary allocation.
- */
-static void TupleSchema_releasekey(void *this,void *key) {
-    TupleSchema *def = (TupleSchema *) this;
-    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
-    Tuple *kp = (Tuple*) key;
-    int i;
-    for ( i = 0; i < def->columns->size; i++ ) {
-       if ( columns[i] ) {
-           columns[i]->releasekey( columns[i], kp->elements[i] );
-       }
-    }
-    free( key );
-}
-
-#define OUT(X) a = X; if ( a > limit ) return 0; buffer += a; limit -= a
-
-/**
- * This callback function writes a representation of an item into
- * a character buffer.
- */
-static int TupleSchema_tostring(void *this,void *item,char *buffer,int limit) {
-    TupleSchema *def = (TupleSchema *) this;
-    ItemKeyFun **columns = (ItemKeyFun**) def->columns->elements;
-    Tuple *t = (Tuple*) item;
-    char *x = "<";
-    int a, i;
-    for ( i = 0; i < def->columns->size; i++ ) {
-       OUT( snprintf( buffer, limit, x ) );
-       x = ",";
-       OUT( columns[i]->tostring(
-                columns[i], t->elements[i], buffer, limit ) );
-    }
-    OUT( snprintf( buffer, limit, ">" ) );
-    return a;
-}
-
-ItemKeyFun TupleSchema_callbacks = {
-    .hashcode = TupleSchema_hashcode,
-    .haskey = TupleSchema_haskey,
-    .itemkey = TupleSchema_itemkey,
-    .releasekey = TupleSchema_releasekey,
-    .tostring = TupleSchema_tostring
-};
-
-TupleSchema *TupleSchema_create(Tuple *columns) {
-    TupleSchema *ts = (TupleSchema*) malloc( sizeof( TupleSchema ) );
-    (*ts) = (TupleSchema) {
-       .base = TupleSchema_callbacks,
-       .columns = columns
-    };
-    return ts;
-}
-
-#define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
-#define COPY(T,P) COPYA(T,P,1)
-
-// Duplicate a TupleSchema with optionally some columns reset.
-TupleSchema *TupleSchema_mask(TupleSchema *schema,...) {
-    TupleSchema *masked = COPY(TupleSchema,schema);
-    masked->columns = Tuple_clone( schema->columns );
-    va_list ap;
-    int i;
-    va_start( ap, schema );
-    for ( ;; ) {
-       i = va_arg( ap, int );
-       if ( i < 0 || i >= schema->columns->size ) {
-           break;
-       }
-       masked->columns->elements[i] = 0;
-    };
-    va_end( ap );
-    return masked;
-}
diff --git a/vector/TupleSchema.h b/vector/TupleSchema.h
deleted file mode 100644 (file)
index 7bfb67d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef tupleitem_H
-#define tupleitem_H
-
-#include <Tuple.h>
-
-/**
- * A TupleSchema record declares the ItemKeyFun functions for tuple
- * items together with applicable arity and domain combinations.
- * Records are created dynamically via the \ref TupleSchema_create
- * function or the \ref TUPLESCHEMA convenience macro.
- *
- * \extends ItemKeyFun
- */
-typedef struct TupleSchema {
-    /**
-     * These are the ItemKeyFun callback functions to support
-     * HashVector use for tuple items. The functions expects their
-     * ItemKeyFun pointer to be within a TupleSchema record so as to
-     * provide the handling of the tuple columns.
-     */
-    ItemKeyFun base;
-
-    /**
-     * This points to tuple whose elements is array of pointers to the
-     * tuple item domains as represented by their associated
-     * ItemKeyFun records.
-     */
-    Tuple *columns;
-} TupleSchema;
-
-/**
- * Create a tuples with given values.
- *
- * \related TupleSchema
- */
-extern TupleSchema *TupleSchema_create(Tuple *columns);
-
-/**
- * Copy the given TupleSchema into a new TupleSchema with some columns
- * masked. This represents a sub-index type using the unmasked columns
- * for indexing.
- *
- * \related TupleSchema
- */
-extern TupleSchema *TupleSchema_mask(TupleSchema *schema,...);
-
-/**
- * \brief Return 1/0 to indicate whether the Query matches the item.
- *
- * \related TupleSchema
- */
-extern int TupleSchema_match(TupleSchema *def,Tuple *query,Tuple *item);
-
-/**
- * \brief Generic macro to determine the number of expressions in a
- * __VA_ARGS__
- *
- * \related TupleSchema
- */
-#define NUMARGS(...) (sizeof((void*[]){__VA_ARGS__})/sizeof(void*))
-
-/**
- * \brief Create a tuple with the given values.
- *
- * This invokes \ref tuple_create to allocate and assign a void*
- * array with the given values.
- *
- * \related TupleSchema
- */
-#define TUPLE(...) Tuple_create( NUMARGS(__VA_ARGS__), __VA_ARGS__ )
-
-/**
- * \brief Create a \ref TupleSchema with the given column "types".
- *
- * This invokes \ref TupleSchema_create to allocate and initialize a
- * \ref TupleSchema for the given columns via the \ref TUPLE macro.
- *
- * \related TupleSchema
- */
-#define TUPLESCHEMA(...) \
-    TupleSchema_create( NUMARGS( __VA_ARGS__ ), TUPLE( __VA_ARGS__ ) )
-
-
-#endif
diff --git a/vector/integeritem.c b/vector/integeritem.c
deleted file mode 100644 (file)
index 221fb70..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <integeritem.h>
-
-/**
- * This callback function returns the hashcode of a key. The hashcode
- * is used for indexing into the backing Vector for finding the an
- * item via its key. The same key must map consistently to the same
- * hashcode while the hashtable contains an item with that key.
- * Different keys map map to the same hashcode, in which case the
- * Vector placement is made at the first empty or hole slot following
- * the hashcode index.
- */
-static unsigned long integeritem_hashcode(void *this,void *key) {
-    return (unsigned long) key;
-}
-
-/**
- * This callback function determines whether an item has a
- * given key or not.
- */
-static int integeritem_haskey(void *this,void *item,void *key) {
-    return item == key;
-}
-
-/**
- * This callback function returns the key of an item by considering
- * the arity and schema.
- */
-static void *integeritem_itemkey(void *this,void *item) {
-    return item;
-}
-
-/**
- * This callback function handles a key obtained from the itemkey
- * callback function to reclaim temporary allocation.
- */
-static void integeritem_releasekey(void *this,void *key) {
-}
-
-/**
- * This callback function writes a representation of an item into
- * a character buffer.
- */
-static int integeritem_tostring(void *this,void *item,char *buffer,int limit) {
-    return snprintf( buffer, limit, "%lld", (long long) item );
-}
-
-ItemKeyFun integeritem = {
-    .hashcode = integeritem_hashcode,
-    .haskey = integeritem_haskey,
-    .itemkey = integeritem_itemkey,
-    .releasekey = integeritem_releasekey,
-    .tostring = integeritem_tostring
-};
diff --git a/vector/integeritem.h b/vector/integeritem.h
deleted file mode 100644 (file)
index efa5323..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef integeritem_H
-#define integeritem_H
-
-#include <ItemKeyFun.h>
-
-/**
- * The stringitem record declares the ItemKeyFun functions for integer
- * items.
- */
-extern ItemKeyFun integeritem;
-
-#endif
diff --git a/vector/mainpage.dox b/vector/mainpage.dox
deleted file mode 100644 (file)
index 2a4c45e..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/** \mainpage rrq C hacks: Vectors And Such
-
-This software is an implementation platform for vector based
-representations.
-
-- \ref itemkeyfun is an implementation of an abstracted type notion
-  that is focussed on what the \ref hashvector needs in terms of
-  callbacks for its separation between the hash management
-  functionality and the contained items. This name is choosen so as to
-  avoid some connotations common to the term "type".
-
-- \ref array and \ref vector are two implementations of an abstract
-  array notion using an indexing tree of 16 and 256 pointers
-  respectively. The indexing tree is balanced into levels matching to
-  the needs of the vector size. When the size of a vector is changed
-  then indexing levels are added or removed as needed. However
-  indexing pages are allocated on a needs basis. The level 0 indexing
-  pages hold the actual data as void* pointers
-
-- \ref hasharray and \ref hashvector are two implementations of an
-  abstract hashtable using \ref array and \ref vector as backing store
-  respectively. It also uses the \ref itemkeyfn type abstraction of
-  items being compunded as pairs of key and payload. This separates
-  the hashing code from the type abstraction.
-
-\subsubsection s0 itemkeyfun actualizations
-
-- \ref integeritem is an plain actualization of an itemkeyfun record
-  for integer items other than 0 and 1, i.e. where the void* slots of
-  a tuple are reinterpreted as 64-bit integers rather than "item
-  pointers".
-
-\note Note that a hashvector cannot directly contain integer items
-  since 0 and 1 are treated as indicating unused and holed slots.
-
-- stringitem is a plain actualization of an itemkeyfun record for
-  null-terminated character strings.
-
-- tupleschema is a specialization of the itemkeyfun type scheme
-  intended for tuple items that are arrays of items that are further
-  type via itemkeyfun records. A tupleschema actualization includes
-  the applicable arity and an array of pointers to itemkeyfun
-  actualizations that declare the itemkeyfun types of the parts
-  (columns).
-
-*/
diff --git a/vector/stringitem.c b/vector/stringitem.c
deleted file mode 100644 (file)
index ee8f2cb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <string.h>
-#include <stringitem.h>
-#include <HashVector.h>
-
-/**
- * This callback function returns the hashcode of a key. The hashcode
- * is used for indexing into the backing Vector for finding the an
- * item via its key. The same key must map consistently to the same
- * hashcode while the hashtable contains an item with that key.
- * Different keys map map to the same hashcode, in which case the
- * Vector placement is made at the first empty or hole slot following
- * the hashcode index.
- */
-static unsigned long stringitem_hashcode(void *this,void *key) {
-    return HashVector_hashcode( (unsigned char*)key, strlen( (char*)key ) );
-}
-
-/**
- * This callback function determines whether an item has a
- * given key or not.
- */
-static int stringitem_haskey(void *this,void *item,void *key) {
-    return strcmp( item, key ) == 0;
-}
-
-/**
- * This callback function returns the key of an item by considering
- * the arity and schema.
- */
-static void *stringitem_itemkey(void *this,void *item) {
-    return item;
-}
-
-/**
- * This callback function handles a key obtained from the itemkey
- * callback function to reclaim temporary allocation.
- */
-static void stringitem_releasekey(void *this,void *key) {
-}
-
-/**
- * This callback function writes a representation of an item into
- * a character buffer.
- */
-static int stringitem_tostring(void *this,void *item,char *buffer,int limit) {
-    if ( item ) {
-       return snprintf( buffer, limit, "\"%s\"", (char*) item );
-    }
-    return snprintf( buffer, limit, "(null)" );
-}
-
-ItemKeyFun stringitem = {
-    .hashcode = stringitem_hashcode,
-    .haskey = stringitem_haskey,
-    .itemkey = stringitem_itemkey,
-    .releasekey = stringitem_releasekey,
-    .tostring = stringitem_tostring
-};
diff --git a/vector/stringitem.h b/vector/stringitem.h
deleted file mode 100644 (file)
index 5cc1a32..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef stringitem_H
-#define stringitem_H
-
-#include <ItemKeyFun.h>
-
-/**
- * The stringitem record declares the ItemKeyFun functions for string
- * items.
- */
-extern ItemKeyFun stringitem;
-
-#endif