commit 44ab702792c70b43dea76c372e49d4777bebaedc
parent 1fdf234c46c1f73501cfead8072d2c971fb2733c
Author: William Casarin <jb55@jb55.com>
Date: Sun, 3 Nov 2024 07:18:28 -0800
nostrdb: add ndb_filter_eq
filter equality testing. this works because field elements are sorted
Changelog-Added: Add ndb_filter_eq for filter equality testing
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
2 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/nostrdb/src/nostrdb.c b/nostrdb/src/nostrdb.c
@@ -1154,6 +1154,62 @@ static void sort_filter_elements(struct ndb_filter *filter,
els->elements[i] -= (uint64_t)filter->data_buf.start;
}
+static int ndb_filter_field_eq(struct ndb_filter *a_filt,
+ struct ndb_filter_elements *a_field,
+ struct ndb_filter *b_filt,
+ struct ndb_filter_elements *b_field)
+{
+ int i;
+ const char *a_str, *b_str;
+ unsigned char *a_id, *b_id;
+ uint64_t a_int, b_int;
+
+ if (a_field->count != b_field->count)
+ return 0;
+
+ if (a_field->field.type != b_field->field.type) {
+ ndb_debug("UNUSUAL: field types do not match in ndb_filter_field_eq\n");
+ return 0;
+ }
+
+ if (a_field->field.elem_type != b_field->field.elem_type) {
+ ndb_debug("UNUSUAL: field element types do not match in ndb_filter_field_eq\n");
+ return 0;
+ }
+
+ if (a_field->field.elem_type == NDB_ELEMENT_UNKNOWN) {
+ ndb_debug("UNUSUAL: field element types are unknown\n");
+ return 0;
+ }
+
+ for (i = 0; i < a_field->count; i++) {
+ switch (a_field->field.elem_type) {
+ case NDB_ELEMENT_UNKNOWN:
+ return 0;
+ case NDB_ELEMENT_STRING:
+ a_str = ndb_filter_get_string_element(a_filt, a_field, i);
+ b_str = ndb_filter_get_string_element(b_filt, b_field, i);
+ if (strcmp(a_str, b_str))
+ return 0;
+ break;
+ case NDB_ELEMENT_ID:
+ a_id = ndb_filter_get_id_element(a_filt, a_field, i);
+ b_id = ndb_filter_get_id_element(b_filt, b_field, i);
+ if (memcmp(a_id, b_id, 32))
+ return 0;
+ break;
+ case NDB_ELEMENT_INT:
+ a_int = ndb_filter_get_int_element(a_field, i);
+ b_int = ndb_filter_get_int_element(b_field, i);
+ if (a_int != b_int)
+ return 0;
+ break;
+ }
+ }
+
+ return 1;
+}
+
void ndb_filter_end_field(struct ndb_filter *filter)
{
int cur_offset;
@@ -2616,6 +2672,29 @@ ndb_filter_find_elements(struct ndb_filter *filter, enum ndb_filter_fieldtype ty
return NULL;
}
+int ndb_filter_eq(struct ndb_filter *a, struct ndb_filter *b)
+{
+ int i;
+ struct ndb_filter_elements *a_els, *b_els;
+
+ if (a->num_elements != b->num_elements)
+ return 0;
+
+ for (i = 0; i < a->num_elements; i++) {
+ a_els = ndb_filter_get_elements(a, i);
+ b_els = ndb_filter_find_elements(b, a_els->field.type);
+
+ if (b_els == NULL)
+ return 0;
+
+ if (!ndb_filter_field_eq(a, a_els, b, b_els))
+ return 0;
+ }
+
+ return 1;
+}
+
+
static uint64_t *
ndb_filter_get_elem(struct ndb_filter *filter, enum ndb_filter_fieldtype typ)
{
diff --git a/nostrdb/src/nostrdb.h b/nostrdb/src/nostrdb.h
@@ -257,6 +257,9 @@ struct ndb_filter {
int current;
// struct ndb_filter_elements offsets into elem_buf
+ //
+ // TODO(jb55): this should probably be called fields. elements are
+ // the things within fields
int elements[NDB_NUM_FILTERS];
};
@@ -494,6 +497,7 @@ int ndb_filter_init(struct ndb_filter *);
int ndb_filter_add_id_element(struct ndb_filter *, const unsigned char *id);
int ndb_filter_add_int_element(struct ndb_filter *, uint64_t integer);
int ndb_filter_add_str_element(struct ndb_filter *, const char *str);
+int ndb_filter_eq(struct ndb_filter *, struct ndb_filter *);
// filters from json
int ndb_filter_from_json(const char *, int len, struct ndb_filter *filter, unsigned char *buf, int bufsize);