From: Sebastian Harl Date: Sun, 23 Feb 2014 04:12:05 +0000 (-0800) Subject: store_lookup: Made logical operators public. X-Git-Tag: sysdb-0.1.0~187 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=4e6a5f2d7cb3796f92dd3d89e6090de80494f816 store_lookup: Made logical operators public. --- diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index 305a513..d4fef03 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -433,6 +433,32 @@ host_matcher_destroy(sdb_object_t *obj) sdb_object_deref(SDB_OBJ(HOST_M(obj)->attr)); } /* host_matcher_destroy */ +static int +op_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + if ((M(obj)->type != MATCHER_OR) && (M(obj)->type != MATCHER_AND)) + return -1; + + OP_M(obj)->left = va_arg(ap, sdb_store_matcher_t *); + sdb_object_ref(SDB_OBJ(OP_M(obj)->left)); + OP_M(obj)->right = va_arg(ap, sdb_store_matcher_t *); + sdb_object_ref(SDB_OBJ(OP_M(obj)->right)); + + if ((! OP_M(obj)->left) || (! OP_M(obj)->right)) + return -1; + return 0; +} /* op_matcher_init */ + +static void +op_matcher_destroy(sdb_object_t *obj) +{ + if (OP_M(obj)->left) + sdb_object_deref(SDB_OBJ(OP_M(obj)->left)); + if (OP_M(obj)->right) + sdb_object_deref(SDB_OBJ(OP_M(obj)->right)); +} /* op_matcher_destroy */ + static sdb_type_t attr_type = { /* size = */ sizeof(attr_matcher_t), /* init = */ attr_matcher_init, @@ -451,6 +477,12 @@ static sdb_type_t host_type = { /* destroy = */ host_matcher_destroy, }; +static sdb_type_t op_type = { + /* size = */ sizeof(op_matcher_t), + /* init = */ op_matcher_init, + /* destroy = */ op_matcher_destroy, +}; + /* * public API */ @@ -480,6 +512,20 @@ sdb_store_host_matcher(const char *host_name, const char *host_name_re, host_name, host_name_re, service_matcher, attr_matcher)); } /* sdb_store_host_matcher */ +sdb_store_matcher_t * +sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right) +{ + return M(sdb_object_create("dis-matcher", op_type, MATCHER_OR, + left, right)); +} /* sdb_store_dis_matcher */ + +sdb_store_matcher_t * +sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right) +{ + return M(sdb_object_create("con-matcher", op_type, MATCHER_AND, + left, right)); +} /* sdb_store_con_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 a327ae9..8c46eb7 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -168,6 +168,20 @@ sdb_store_host_matcher(const char *host_name, const char *host_name_re, sdb_store_matcher_t *service_matcher, sdb_store_matcher_t *attr_matcher); +/* + * sdb_store_dis_matcher: + * Creates a matcher matching the disjunction (logical OR) of two matchers. + */ +sdb_store_matcher_t * +sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); + +/* + * sdb_store_con_matcher: + * Creates a matcher matching the conjunction (logical AND) of two matchers. + */ +sdb_store_matcher_t * +sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); + /* * 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 3d567ac..48bb483 100644 --- a/t/core/store_lookup_test.c +++ b/t/core/store_lookup_test.c @@ -249,6 +249,72 @@ START_TEST(test_store_match) } END_TEST +START_TEST(test_store_match_op) +{ + sdb_store_base_t *obj; + + sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL); + sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL); + + struct { + const char *op; + sdb_store_matcher_t *left; + sdb_store_matcher_t *right; + int expected; + } golden_data[] = { + { "OR", always, always, 0 }, + { "OR", always, never, 0 }, + { "OR", never, always, 0 }, + { "OR", never, never, -1 }, + { "AND", always, always, 0 }, + { "AND", always, never, -1 }, + { "AND", never, always, -1 }, + { "AND", never, never, -1 }, + }; + + int status; + size_t i; + + obj = sdb_store_get_host("a"); + + status = sdb_store_matcher_matches(always, obj); + fail_unless(status == 0, + "INTERNAL ERROR: 'always' did not match host"); + status = sdb_store_matcher_matches(never, obj); + fail_unless(status < 0, + "INTERNAL ERROR: 'never' matches host"); + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { + sdb_store_matcher_t *m; + + if (! strcmp(golden_data[i].op, "OR")) + m = sdb_store_dis_matcher(golden_data[i].left, + golden_data[i].right); + else if (! strcmp(golden_data[i].op, "AND")) + m = sdb_store_con_matcher(golden_data[i].left, + golden_data[i].right); + else + fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op); + +#define TO_NAME(v) (((v) == always) ? "always" \ + : ((v) == never) ? "never" : "") + + status = sdb_store_matcher_matches(m, obj); + fail_unless(status == golden_data[i].expected, + "%s(%s, %s) = %d; expected: %d", golden_data[i].op, + TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right), + status, golden_data[i].expected); + +#undef TO_NAME + + sdb_object_deref(SDB_OBJ(m)); + } + + sdb_object_deref(SDB_OBJ(always)); + sdb_object_deref(SDB_OBJ(never)); +} +END_TEST + Suite * core_store_lookup_suite(void) { @@ -258,6 +324,7 @@ core_store_lookup_suite(void) tc = tcase_create("core"); tcase_add_checked_fixture(tc, populate, sdb_store_clear); tcase_add_test(tc, test_store_match); + tcase_add_test(tc, test_store_match_op); suite_add_tcase(s, tc); return s;