From c3cffe0ff4c8d37cbe2df874743a59e1ec514c71 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 6 Apr 2014 19:17:51 +0200 Subject: [PATCH] store_lookup: Added sdb_store_inv_matcher(). This creates a matcher objects which matches the inverse (logical NOT) of the specified matcher. --- src/core/store-private.h | 12 +++++++++- src/core/store_lookup.c | 46 ++++++++++++++++++++++++++++++++++++++ src/include/core/store.h | 7 ++++++ t/core/store_lookup_test.c | 18 ++++++++++++++- 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/core/store-private.h b/src/core/store-private.h index 22f6e07..823cd18 100644 --- a/src/core/store-private.h +++ b/src/core/store-private.h @@ -95,6 +95,7 @@ enum { enum { MATCHER_OR, MATCHER_AND, + MATCHER_NOT, MATCHER_ATTR, MATCHER_SERVICE, MATCHER_HOST, @@ -114,7 +115,7 @@ struct sdb_store_matcher { }; #define M(m) ((sdb_store_matcher_t *)(m)) -/* logical operator matcher */ +/* logical infix operator matcher */ typedef struct { sdb_store_matcher_t super; @@ -124,6 +125,15 @@ typedef struct { } op_matcher_t; #define OP_M(m) ((op_matcher_t *)(m)) +/* logical unary operator matcher */ +typedef struct { + sdb_store_matcher_t super; + + /* operand */ + sdb_store_matcher_t *op; +} uop_matcher_t; +#define UOP_M(m) ((uop_matcher_t *)(m)) + /* match any type of object by it's base information */ typedef struct { sdb_store_matcher_t super; diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index b730684..d43b9e3 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -78,6 +78,8 @@ lookup_iter(sdb_store_base_t *obj, void *user_data) static int match_logical(sdb_store_matcher_t *m, sdb_store_base_t *obj); static int +match_unary(sdb_store_matcher_t *m, sdb_store_base_t *obj); +static int match_obj(sdb_store_matcher_t *m, sdb_store_base_t *obj); /* specific matchers */ @@ -210,6 +212,7 @@ typedef int (*matcher_cb)(sdb_store_matcher_t *, sdb_store_base_t *); static matcher_cb matchers[] = { match_logical, match_logical, + match_unary, match_obj, match_obj, match_obj, @@ -233,6 +236,15 @@ match_logical(sdb_store_matcher_t *m, sdb_store_base_t *obj) return sdb_store_matcher_matches(OP_M(m)->right, obj); } /* match_logical */ +static int +match_unary(sdb_store_matcher_t *m, sdb_store_base_t *obj) +{ + assert(m && obj); + assert(UOP_M(m)->op); + + return !sdb_store_matcher_matches(UOP_M(m)->op, obj); +} /* match_unary */ + static int match_obj(sdb_store_matcher_t *m, sdb_store_base_t *obj) { @@ -416,6 +428,28 @@ op_matcher_destroy(sdb_object_t *obj) sdb_object_deref(SDB_OBJ(OP_M(obj)->right)); } /* op_matcher_destroy */ +static int +uop_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + if (M(obj)->type != MATCHER_NOT) + return -1; + + UOP_M(obj)->op = va_arg(ap, sdb_store_matcher_t *); + sdb_object_ref(SDB_OBJ(UOP_M(obj)->op)); + + if (! UOP_M(obj)->op) + return -1; + return 0; +} /* uop_matcher_init */ + +static void +uop_matcher_destroy(sdb_object_t *obj) +{ + if (UOP_M(obj)->op) + sdb_object_deref(SDB_OBJ(UOP_M(obj)->op)); +} /* uop_matcher_destroy */ + static sdb_type_t attr_type = { /* size = */ sizeof(attr_matcher_t), /* init = */ attr_matcher_init, @@ -440,6 +474,12 @@ static sdb_type_t op_type = { /* destroy = */ op_matcher_destroy, }; +static sdb_type_t uop_type = { + /* size = */ sizeof(uop_matcher_t), + /* init = */ uop_matcher_init, + /* destroy = */ uop_matcher_destroy, +}; + /* * public API */ @@ -524,6 +564,12 @@ sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right) left, right)); } /* sdb_store_con_matcher */ +sdb_store_matcher_t * +sdb_store_inv_matcher(sdb_store_matcher_t *m) +{ + return M(sdb_object_create("inv-matcher", uop_type, MATCHER_NOT, m)); +} /* sdb_store_inv_matcher */ + int sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_base_t *obj) { diff --git a/src/include/core/store.h b/src/include/core/store.h index 9f23275..cde6ad0 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -195,6 +195,13 @@ sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); sdb_store_matcher_t * sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); +/* + * sdb_store_con_matcher:: + * Creates a matcher matching the inverse (logical NOT) of a matcher. + */ +sdb_store_matcher_t * +sdb_store_inv_matcher(sdb_store_matcher_t *m); + /* * sdb_store_matcher_matches: * Check whether the specified matcher matches the specified store object. diff --git a/t/core/store_lookup_test.c b/t/core/store_lookup_test.c index 15a67b1..977bd95 100644 --- a/t/core/store_lookup_test.c +++ b/t/core/store_lookup_test.c @@ -213,7 +213,7 @@ START_TEST(test_store_match) "sdb_store_get_host(a) = NULL; expected: "); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { - sdb_store_matcher_t *h, *s, *a; + sdb_store_matcher_t *h, *s, *a, *n; int status; s = sdb_store_service_matcher(golden_data[i].service_name, @@ -245,7 +245,23 @@ START_TEST(test_store_match) golden_data[i].attr_value, golden_data[i].attr_value_re, status, golden_data[i].expected); + n = sdb_store_inv_matcher(h); + fail_unless(n != NULL, + "sdb_store_inv_matcher() = NULL; expected: "); sdb_object_deref(SDB_OBJ(h)); + + /* now match the inverted set of objects */ + status = sdb_store_matcher_matches(n, obj); + fail_unless(status == !golden_data[i].expected, + "sdb_store_matcher_matches(NOT{{%s, %s},{%s, %s}," + "{%s, %s, %s, %s}}, ) = %d; expected: %d", + golden_data[i].hostname, golden_data[i].hostname_re, + golden_data[i].service_name, golden_data[i].service_name_re, + golden_data[i].attr_name, golden_data[i].attr_name_re, + golden_data[i].attr_value, golden_data[i].attr_value_re, + status, !golden_data[i].expected); + + sdb_object_deref(SDB_OBJ(n)); } } END_TEST -- 2.30.2