From 5a88db596f9e4586399dff19db3f3178abdbabdf Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Wed, 2 Dec 2015 13:36:33 -0500 Subject: [PATCH] #416 Added filtering support on replicator output --- packages/corto/lang/src/corto_select.c | 72 +++++++++++-------- .../corto/lang/test/src/test_ListReplicator.c | 1 + .../lang/test/src/test_ReplicatorRequest.c | 56 ++++++++++++++- packages/corto/lang/test/test.cx | 2 + 4 files changed, 99 insertions(+), 32 deletions(-) diff --git a/packages/corto/lang/src/corto_select.c b/packages/corto/lang/src/corto_select.c index 7eba38f4..b21a7f62 100644 --- a/packages/corto/lang/src/corto_select.c +++ b/packages/corto/lang/src/corto_select.c @@ -389,41 +389,51 @@ static void corto_selectRequestReplicators( } } -static void corto_selectIterateReplicators(corto_selectData *data) { +static void corto_selectIterateReplicators( + corto_selectData *data, + corto_selectStack *frame) +{ if (data->activeReplicators) { if (data->currentReplicator < 0) { data->currentReplicator = 0; } - + /* Walk over iterators until one with data available has been found */ while ((data->currentReplicator < data->activeReplicators)) { corto_resultIter *iter = &data->replicators[data->currentReplicator]; - if (corto_iterHasNext(iter)) { + while (corto_iterHasNext(iter)) { corto_result *result = corto_iterNext(iter); - data->next = &data->item; + if (!frame->filter || + corto_selectMatch(frame->filter, result->name)) + { + data->next = &data->item; + + /* Copy data, so replicator can safely release it */ + if (result->name) { + strcpy(data->item.name, result->name); + } else { + data->item.name[0] = '\0'; + } + if (result->parent) { + strcpy(data->item.parent, result->name); + } else { + data->item.parent[0] = '\0'; + } + if (result->type) { + strcpy(data->item.type, result->name); + } else { + data->item.type[0] = '\0'; + } - /* Copy data, so replicator can safely release it */ - if (result->name) { - strcpy(data->item.name, result->name); - } else { - data->item.name[0] = '\0'; - } - if (result->parent) { - strcpy(data->item.parent, result->name); - } else { - data->item.parent[0] = '\0'; - } - if (result->type) { - strcpy(data->item.type, result->name); - } else { - data->item.type[0] = '\0'; + break; } + } - /* Return item */ - break; - } else { + if (!data->next) { corto_iterRelease(iter); data->currentReplicator ++; + } else { + break; } } } @@ -459,7 +469,7 @@ static void corto_selectScope( /* Handle replicator iteration outside of scope lock */ if (!data->next) { - corto_selectIterateReplicators(data); + corto_selectIterateReplicators(data, frame); } } @@ -558,19 +568,19 @@ static int corto_selectRun(corto_selectData *data) { case TOKEN_IDENTIFIER: explicitRef = TRUE; if (!op->containsWildcard) { - frame->next = corto_selectThis; corto_object o = corto_lookup(frame->o, op->start); - corto_setref(&frame->o, o); if (o) { + frame->next = corto_selectThis; + corto_setref(&frame->o, o); corto_release(o); - } else { - corto_seterr("unresolved identifier '%s'", op->start); - goto error; + break; } - break; - } else { - frame->filter = op->start; } + + /* If expression contains wildcard OR does not resolve to an object, + * lookup object in scope (and replicators) */ + frame->filter = op->start; + case TOKEN_WILDCARD: if (op->token == TOKEN_WILDCARD) { frame->filter = "?"; diff --git a/packages/corto/lang/test/src/test_ListReplicator.c b/packages/corto/lang/test/src/test_ListReplicator.c index 3a3a6ee9..f5be6496 100644 --- a/packages/corto/lang/test/src/test_ListReplicator.c +++ b/packages/corto/lang/test/src/test_ListReplicator.c @@ -11,6 +11,7 @@ corto_resultIter _test_ListReplicator_onRequest(test_ListReplicator this, corto_object parent, corto_string expr) { /* $begin(test/ListReplicator/onRequest) */ + /* Return persistent iterator to request */ return corto_llIterAlloc(this->items); /* $end */ diff --git a/packages/corto/lang/test/src/test_ReplicatorRequest.c b/packages/corto/lang/test/src/test_ReplicatorRequest.c index 3ecfc2b9..cf2eae2d 100644 --- a/packages/corto/lang/test/src/test_ReplicatorRequest.c +++ b/packages/corto/lang/test/src/test_ReplicatorRequest.c @@ -18,7 +18,7 @@ corto_void _test_ReplicatorRequest_setup(test_ReplicatorRequest this) { /* Create list of dummy 'remote' objects */ corto_resultList items = corto_llNew(); - *(corto_resultListAppendAlloc(items)) = (corto_result){corto_strdup("x"), NULL, NULL}; + *(corto_resultListAppendAlloc(items)) = (corto_result){corto_strdup("x")}; *(corto_resultListAppendAlloc(items)) = (corto_result){corto_strdup("yz")}; *(corto_resultListAppendAlloc(items)) = (corto_result){corto_strdup("xyz")}; @@ -67,6 +67,37 @@ corto_void _test_ReplicatorRequest_tc_selectScope(test_ReplicatorRequest this) { /* $end */ } +corto_void _test_ReplicatorRequest_tc_selectScopeFilter(test_ReplicatorRequest this) { +/* $begin(test/ReplicatorRequest/tc_selectScopeFilter) */ + corto_resultIter iter; + corto_result *result; + corto_int16 ret; + + ret = corto_select(root_o, "a/*z", &iter); + + test_assert(ret == 0); + + test_assert(corto_iterHasNext(&iter)); + result = corto_iterNext(&iter); + test_assert(result != NULL); + test_assert(result->name != NULL); + test_assert(!strcmp(result->name, "yz")); + test_assert(!strlen(result->parent)); + test_assert(!strlen(result->type)); + + test_assert(corto_iterHasNext(&iter)); + result = corto_iterNext(&iter); + test_assert(result != NULL); + test_assert(result->name != NULL); + test_assert(!strcmp(result->name, "xyz")); + test_assert(!strlen(result->parent)); + test_assert(!strlen(result->type)); + + test_assert(!corto_iterHasNext(&iter)); + +/* $end */ +} + corto_void _test_ReplicatorRequest_tc_selectScopeMixed(test_ReplicatorRequest this) { /* $begin(test/ReplicatorRequest/tc_selectScopeMixed) */ corto_resultIter iter; @@ -138,6 +169,29 @@ corto_void _test_ReplicatorRequest_tc_selectScopeMixed(test_ReplicatorRequest th /* $end */ } +corto_void _test_ReplicatorRequest_tc_selectSingle(test_ReplicatorRequest this) { +/* $begin(test/ReplicatorRequest/tc_selectSingle) */ + corto_resultIter iter; + corto_result *result; + corto_int16 ret; + + ret = corto_select(root_o, "a/xyz", &iter); + + test_assert(ret == 0); + + test_assert(corto_iterHasNext(&iter)); + result = corto_iterNext(&iter); + test_assert(result != NULL); + test_assert(result->name != NULL); + test_assert(!strcmp(result->name, "xyz")); + test_assert(!strlen(result->parent)); + test_assert(!strlen(result->type)); + + test_assert(!corto_iterHasNext(&iter)); + +/* $end */ +} + corto_void _test_ReplicatorRequest_teardown(test_ReplicatorRequest this) { /* $begin(test/ReplicatorRequest/teardown) */ diff --git a/packages/corto/lang/test/test.cx b/packages/corto/lang/test/test.cx index 2203d852..7906c1e9 100644 --- a/packages/corto/lang/test/test.cx +++ b/packages/corto/lang/test/test.cx @@ -228,8 +228,10 @@ test::Suite ReplicatorRequest:: void setup() method void teardown() method replicator: ListReplicator + void tc_selectSingle() void tc_selectScope() void tc_selectScopeMixed() + void tc_selectScopeFilter() // Test Event scenarios class EventTest::