Skip to content

Commit

Permalink
handle verbatims in inclusions
Browse files Browse the repository at this point in the history
  • Loading branch information
p-avital committed Jan 22, 2024
1 parent cfa4a00 commit a3d0a7f
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 89 deletions.
148 changes: 59 additions & 89 deletions src/protocol/keyexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <string.h>

#include "zenoh-pico/protocol/core.h"
Expand Down Expand Up @@ -292,8 +293,9 @@ _Bool _z_ke_isdoublestar(_z_str_se_t s) {
/*------------------ Inclusion helpers ------------------*/
_Bool _z_ke_chunk_includes_nodsl(_z_str_se_t l, _z_str_se_t r) {
size_t llen = l.end - l.start;
_Bool result = ((llen == (size_t)1) && (l.start[0] == '*') &&
(((_z_ptr_char_diff(r.end, r.start) == 2) && (r.start[0] == '*') && (r.start[1] == '*')) == false));
_Bool result =
!(r.start[0] == _Z_VERBATIM) && ((llen == (size_t)1) && (l.start[0] == '*') &&
(((_z_ptr_char_diff(r.end, r.start) == 2) && (r.start[0] == '*')) == false));
if ((result == false) && (llen == _z_ptr_char_diff(r.end, r.start))) {
result = strncmp(l.start, r.start, llen) == 0;
}
Expand All @@ -303,7 +305,7 @@ _Bool _z_ke_chunk_includes_nodsl(_z_str_se_t l, _z_str_se_t r) {

_Bool _z_ke_chunk_includes_stardsl(_z_str_se_t l1, _z_str_se_t r) {
_Bool result = _z_ke_chunk_includes_nodsl(l1, r);
if (result == false) {
if (result == false && l1.start[0] != _Z_VERBATIM && r.start[0] != _Z_VERBATIM) {
_z_splitstr_t lcs = {.s = l1, .delimiter = _Z_DOLLAR_STAR};
_z_str_se_t split_l = _z_splitstr_next(&lcs);
result = (_z_ptr_char_diff(r.end, r.start) >= _z_ptr_char_diff(split_l.end, split_l.start));
Expand Down Expand Up @@ -340,6 +342,57 @@ _Bool _z_ke_chunk_includes_stardsl(_z_str_se_t l1, _z_str_se_t r) {

return result;
}

_Bool _z_keyexpr_is_wild_chunk(_z_str_se_t s) { return _z_ptr_char_diff(s.end, s.start) == 1 && s.start[0] == '*'; }

_Bool _z_keyexpr_is_superwild_chunk(_z_str_se_t s) {
return _z_ptr_char_diff(s.end, s.start) == 2 && s.start[0] == '*';
}

_Bool _z_keyexpr_has_verbatim(_z_str_se_t s) {
_z_splitstr_t it = {.s = s, .delimiter = _Z_DELIMITER};
_z_str_se_t chunk = _z_splitstr_next(&it);
while (chunk.start != NULL) {
if (chunk.start[0] == _Z_VERBATIM) {
return true;
}
chunk = _z_splitstr_next(&it);
}
return false;
}

_Bool _z_keyexpr_includes_superwild(_z_str_se_t left, _z_str_se_t right, _z_ke_chunk_matcher chunk_includer) {
for (;;) {
_z_str_se_t lchunk = {0};
_z_str_se_t lrest = _z_splitstr_split_once((_z_splitstr_t){.s = left, .delimiter = _Z_DELIMITER}, &lchunk);
_Bool lempty = lrest.start == NULL;
if (_z_keyexpr_is_superwild_chunk(lchunk)) {
if (lempty ? !_z_keyexpr_has_verbatim(right)
: _z_keyexpr_includes_superwild(lrest, right, chunk_includer)) {
return true;
}
if (right.start[0] == _Z_VERBATIM) {
return false;
}
right = _z_splitstr_split_once((_z_splitstr_t){.s = right, .delimiter = _Z_DELIMITER}, &lrest);
if (right.start == NULL) {
return false;
}
} else {
_z_str_se_t rchunk = {0};
_z_str_se_t rrest = _z_splitstr_split_once((_z_splitstr_t){.s = right, .delimiter = _Z_DELIMITER}, &rchunk);
if (rchunk.start == NULL || _z_keyexpr_is_superwild_chunk(rchunk) || !chunk_includer(lchunk, rchunk)) {
return false;
}
if (lempty) {
return rrest.start == NULL;
}
left = lrest;
right = rrest;
}
}
}

/*------------------ Zenoh-Core helpers ------------------*/
_Bool _z_keyexpr_includes(const char *lstart, const size_t llen, const char *rstart, const size_t rlen) {
_Bool result = ((llen == rlen) && (strncmp(lstart, rstart, llen) == 0));
Expand All @@ -351,88 +404,20 @@ _Bool _z_keyexpr_includes(const char *lstart, const size_t llen, const char *rst
int8_t lwildness = _zp_ke_wildness(l, &ln_chunks, &ln_verbatim);
int8_t rwildness = _zp_ke_wildness(r, &rn_chunks, &rn_verbatim);
int8_t wildness = lwildness | rwildness;
_z_ke_chunk_matcher chunk_intersector =
_z_ke_chunk_matcher chunk_includer =
((wildness & (int8_t)_ZP_WILDNESS_SUBCHUNK_DSL) == (int8_t)_ZP_WILDNESS_SUBCHUNK_DSL)
? _z_ke_chunk_includes_stardsl
: _z_ke_chunk_includes_nodsl;
if ((lwildness & (int8_t)_ZP_WILDNESS_SUPERCHUNKS) == (int8_t)_ZP_WILDNESS_SUPERCHUNKS) {
result = true;
_z_splitstr_t rchunks = {.s = r, .delimiter = _Z_DELIMITER};
_z_splitstr_t lsplitatsuper = {.s = l, .delimiter = _Z_DOUBLE_STAR};
_z_str_se_t lnosuper = _z_splitstr_next(&lsplitatsuper);
_z_str_se_t rchunk;
if (lnosuper.start != lnosuper.end) {
_z_splitstr_t pchunks = {.s = {.start = lnosuper.start, .end = _z_cptr_char_offset(lnosuper.end, -1)},
.delimiter = _Z_DELIMITER};
_z_str_se_t lchunk = _z_splitstr_next(&pchunks);
while ((result == true) && (lchunk.start != NULL)) {
rchunk = _z_splitstr_next(&rchunks);
result = ((rchunk.start != NULL) && (chunk_intersector(lchunk, rchunk) == true));
lchunk = _z_splitstr_next(&pchunks);
}
}
if (result == true) {
lnosuper = _z_splitstr_nextback(&lsplitatsuper);
if (lnosuper.start != lnosuper.end) {
_z_splitstr_t schunks = {
.s = {.start = _z_cptr_char_offset(lnosuper.start, 1), .end = lnosuper.end},
.delimiter = _Z_DELIMITER};
_z_str_se_t lchunk = _z_splitstr_nextback(&schunks);
while ((result == true) && (lchunk.start != NULL)) {
rchunk = _z_splitstr_nextback(&rchunks);
result = rchunk.start && chunk_intersector(lchunk, rchunk);
lchunk = _z_splitstr_nextback(&schunks);
}
}
}
while (result == true) {
lnosuper = _z_splitstr_next(&lsplitatsuper);
if (lnosuper.start == NULL) {
break;
}
_z_splitstr_t needle = {.s = {.start = _z_cptr_char_offset(lnosuper.start, 1),
.end = _z_cptr_char_offset(lnosuper.end, -1)},
.delimiter = _Z_DELIMITER};
_z_splitstr_t haystack = rchunks;
_z_str_se_t needle_start = _z_splitstr_next(&needle);
_Bool needle_found = false;
_z_str_se_t h = _z_splitstr_next(&haystack);
while ((needle_found == false) && (h.start != NULL)) {
if (chunk_intersector(needle_start, h) == true) {
needle_found = true;
_z_splitstr_t needlecp = needle;
_z_str_se_t n = _z_splitstr_next(&needlecp);
_z_splitstr_t haystackcp = haystack;
while ((needle_found == true) && (n.start != NULL)) {
h = _z_splitstr_next(&haystackcp);
if (h.start != NULL) {
if (chunk_intersector(n, h) == false) {
needle_found = false;
} else {
n = _z_splitstr_next(&needlecp);
}
} else {
needle_found = false;
haystack.s = (_z_str_se_t){.start = NULL, .end = NULL};
}
}
if (needle_found == true) {
rchunks = haystackcp;
}
} else {
needle_found = false;
}
h = _z_splitstr_next(&haystack);
}
}
return _z_keyexpr_includes_superwild(l, r, chunk_includer);
} else if (((rwildness & (int8_t)_ZP_WILDNESS_SUPERCHUNKS) == 0) && (ln_chunks == rn_chunks)) {
_z_splitstr_t lchunks = {.s = l, .delimiter = _Z_DELIMITER};
_z_splitstr_t rchunks = {.s = r, .delimiter = _Z_DELIMITER};
_z_str_se_t lchunk = _z_splitstr_next(&lchunks);
_z_str_se_t rchunk = _z_splitstr_next(&rchunks);
result = true;
while ((result == true) && (lchunk.start != NULL)) {
result = chunk_intersector(lchunk, rchunk);
result = chunk_includer(lchunk, rchunk);
lchunk = _z_splitstr_next(&lchunks);
rchunk = _z_splitstr_next(&rchunks);
}
Expand Down Expand Up @@ -610,21 +595,6 @@ _Bool _z_ke_intersect_rhassuperchunks(_z_str_se_t l, _z_str_se_t r, _z_ke_chunk_
return result;
}

_Bool _z_keyexpr_is_superwild_chunk(_z_str_se_t s) {
return _z_ptr_char_diff(s.end, s.start) == 2 && s.start[0] == '*';
}

_Bool _z_keyexpr_has_verbatim(_z_str_se_t s) {
_z_splitstr_t it = {.s = s, .delimiter = _Z_DELIMITER};
_z_str_se_t chunk = _z_splitstr_next(&it);
while (chunk.start != NULL) {
if (chunk.start[0] == _Z_VERBATIM) {
return true;
}
}
return false;
}

_Bool _z_keyexpr_intersect_bothsuper(_z_str_se_t l, _z_str_se_t r, _z_ke_chunk_matcher chunk_intersector) {
_z_splitstr_t it1 = {.s = l, .delimiter = _Z_DELIMITER};
_z_splitstr_t it2 = {.s = r, .delimiter = _Z_DELIMITER};
Expand Down
15 changes: 15 additions & 0 deletions tests/z_keyexpr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,21 @@ int main(void) {
assert(zp_keyexpr_includes_null_terminated("a/**/b$*", "a/ebc") == -1);
assert(zp_keyexpr_includes_null_terminated("a/**/$*b", "a/cbc") == -1);

assert((zp_keyexpr_includes_null_terminated("@a", "@a") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a", "@ab") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/b") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/*") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/*/**") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a$*/**", "@a") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/**") == 0));
assert((zp_keyexpr_includes_null_terminated("@a/**", "@a") == 0));
assert(!(zp_keyexpr_includes_null_terminated("**/xyz$*xyz", "@a/b/xyzdefxyz") == 0));
assert((zp_keyexpr_includes_null_terminated("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a/*", "@a/@b") == 0));
assert(!(zp_keyexpr_includes_null_terminated("@a/**", "@a/@b") == 0));
assert((zp_keyexpr_includes_null_terminated("@a/**/@b", "@a/@b") == 0));
assert((zp_keyexpr_includes_null_terminated("@a/@b/**", "@a/@b") == 0));

// clang-format off

#define N 31
Expand Down

0 comments on commit a3d0a7f

Please sign in to comment.