Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add z_(owned_)keyexpr_t autocanonize initializers #282

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Key expression
.. autocstruct:: zenoh_commons.h::z_owned_keyexpr_t

.. autocfunction:: zenoh_commons.h::z_keyexpr
.. autocfunction:: zenoh_commons.h::z_keyexpr_autocanonize
.. autocfunction:: zenoh_commons.h::z_keyexpr_unchecked
.. autocfunction:: zenoh_commons.h::z_keyexpr_to_string
.. autocfunction:: zenoh_commons.h::z_keyexpr_as_bytes
Expand All @@ -120,6 +121,7 @@ Key expression
.. autocfunction:: zenoh_commons.h::z_keyexpr_intersects

.. autocfunction:: zenoh_commons.h::z_keyexpr_new
.. autocfunction:: zenoh_commons.h::z_keyexpr_new_autocanonize
.. autocfunction:: zenoh_commons.h::z_keyexpr_loan
.. autocfunction:: zenoh_commons.h::z_keyexpr_check
.. autocfunction:: zenoh_commons.h::z_keyexpr_drop
Expand Down
22 changes: 22 additions & 0 deletions include/zenoh_commons.h
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,14 @@ ZENOHC_API struct z_keyexpr_t z_keyexpr(const char *name);
* Currently exclusive to zenoh-c
*/
ZENOHC_API struct z_bytes_t z_keyexpr_as_bytes(struct z_keyexpr_t keyexpr);
/**
* Constructs a :c:type:`z_keyexpr_t` departing from a string.
* It is a loaned key expression that aliases `name`.
* The string is canonized in-place before being passed to keyexpr.
* May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do).
*/
ZENOHC_API
struct z_keyexpr_t z_keyexpr_autocanonize(char *name);
/**
* Canonizes the passed string in place, possibly shortening it by modifying `len`.
*
Expand Down Expand Up @@ -1639,6 +1647,11 @@ ZENOHC_API struct z_keyexpr_t z_keyexpr_loan(const struct z_owned_keyexpr_t *key
* Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string.
*/
ZENOHC_API struct z_owned_keyexpr_t z_keyexpr_new(const char *name);
/**
* Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized.
*/
ZENOHC_API
struct z_owned_keyexpr_t z_keyexpr_new_autocanonize(const char *name);
/**
* Constructs a null safe-to-drop value of 'z_owned_keyexpr_t' type
*/
Expand Down Expand Up @@ -2174,6 +2187,15 @@ ZENOHC_API void zc_init_logger(void);
* It is a loaned key expression that aliases `name`.
*/
ZENOHC_API struct z_keyexpr_t zc_keyexpr_from_slice(const char *name, size_t len);
/**
* Constructs a :c:type:`z_keyexpr_t` departing from a string.
* It is a loaned key expression that aliases `name`.
* The string is canonized in-place before being passed to keyexpr.
* May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do).
*/
ZENOHC_API
struct z_keyexpr_t zc_keyexpr_from_slice_autocanonize(char *name,
size_t *len);
/**
* Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions:
* - `name` MUST be valid UTF8.
Expand Down
56 changes: 56 additions & 0 deletions src/keyexpr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,32 @@ pub unsafe extern "C" fn z_keyexpr_new(name: *const c_char) -> z_owned_keyexpr_t
}
}

/// Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized.
#[allow(clippy::missing_safety_doc)]
#[no_mangle]
pub unsafe extern "C" fn z_keyexpr_new_autocanonize(name: *const c_char) -> z_owned_keyexpr_t {
if name.is_null() {
return z_owned_keyexpr_t::null();
}
let name = std::slice::from_raw_parts(name as _, libc::strlen(name));
match std::str::from_utf8(name) {
Ok(name) => {
let name_owned = name.to_owned();
match KeyExpr::autocanonize(name_owned) {
Ok(v) => v.into_owned().into(),
Err(e) => {
log::error!("Couldn't construct a keyexpr from {:02x?}: {}", name, e);
z_owned_keyexpr_t::null()
}
}
}
Err(e) => {
log::error!("{}", e);
z_owned_keyexpr_t::null()
}
}
}

/// Returns a :c:type:`z_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`.
#[no_mangle]
pub extern "C" fn z_keyexpr_loan(keyexpr: &z_owned_keyexpr_t) -> z_keyexpr_t {
Expand Down Expand Up @@ -309,6 +335,22 @@ pub unsafe extern "C" fn zc_keyexpr_from_slice(name: *const c_char, len: usize)
}
}

/// Constructs a :c:type:`z_keyexpr_t` departing from a string.
/// It is a loaned key expression that aliases `name`.
/// The string is canonized in-place before being passed to keyexpr.
/// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do).
#[allow(clippy::missing_safety_doc)]
#[no_mangle]
pub unsafe extern "C" fn zc_keyexpr_from_slice_autocanonize(
name: *mut c_char,
len: &mut usize,
) -> z_keyexpr_t {
if z_keyexpr_canonize(name, len) < 0 {
return z_keyexpr_t::null();
}
zc_keyexpr_from_slice(name, *len)
}

/// Constructs a :c:type:`z_keyexpr_t` departing from a string.
/// It is a loaned key expression that aliases `name`.
#[allow(clippy::missing_safety_doc)]
Expand All @@ -321,6 +363,20 @@ pub unsafe extern "C" fn z_keyexpr(name: *const c_char) -> z_keyexpr_t {
}
}

/// Constructs a :c:type:`z_keyexpr_t` departing from a string.
/// It is a loaned key expression that aliases `name`.
/// The string is canonized in-place before being passed to keyexpr.
/// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do).
#[allow(clippy::missing_safety_doc)]
#[no_mangle]
pub unsafe extern "C" fn z_keyexpr_autocanonize(name: *mut c_char) -> z_keyexpr_t {
if name.is_null() || z_keyexpr_canonize_null_terminated(name) < 0 {
z_keyexpr_t::null()
} else {
z_keyexpr(name)
}
}

/// Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions:
/// - `name` MUST be valid UTF8.
/// - `name` MUST follow the Key Expression specification, ie:
Expand Down
16 changes: 16 additions & 0 deletions tests/z_api_keyexpr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ void canonize() {
printf("'%s', err = %d\n", keyexpr, err);
assert(err == 0);
assert(strcmp(keyexpr, "a/**/c") == 0);

strcpy(keyexpr, "a/**/**/c");
z_keyexpr_t key_expr_canonized = z_keyexpr_autocanonize(keyexpr);
assert(z_keyexpr_check(keyexpr) == true);
assert(strcmp(keyexpr, "a/**/c") == 0);
assert(z_keyexpr_as_bytes(key_expr_canonized).len == len_new);
assert(strncmp(z_keyexpr_as_bytes(key_expr_canonized).start, "a/**/c", len_new) == 0);

strcpy(keyexpr, "a/**/**/c");
len_new = len_old;
key_expr_canonized = zc_keyexpr_from_slice_autocanonize(keyexpr, &len_new);
assert(z_keyexpr_check(keyexpr) == true);
assert(len_new == len_old - 3);
assert(strncmp(keyexpr, "a/**/c", len_new) == 0);
assert(z_keyexpr_as_bytes(key_expr_canonized).len == len_new);
assert(strncmp(z_keyexpr_as_bytes(key_expr_canonized).start, "a/**/c", len_new) == 0);
}

void includes() {
Expand Down
Loading