From e626980de573de7cc50b5a9653ee9f403410a507 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 21 Aug 2024 10:20:04 +0200 Subject: [PATCH] merge main branch into dev/1.0.0 (after "moved_as_ptr" update) (#600) * fix: Rename `bump.bash` to `bump-and-tag.bash` * feat: Add `version.txt` and infer version in `bump-and-tag.bash` * fix: Clone repository using actions/checkout * fix: Add `CMakeFiles` to `.gitignore` * fix: Add `debug` and `release` to `.gitignore` * fix: Provide default release number for testing * fix: Don't bump deps when pattern is undefined * fix sizes of zcu_owned_matching_listener_t and z_owned_reply_t * build: Sync with eclipse-zenoh/zenoh@580f0b6 from 2024-04-11 (#330) Co-authored-by: eclipse-zenoh-bot * fix: Specify git remote when pushing the tag * fix: Require `VERSION`in `bump-and-tag.bash` * fix: Override release tag if it already exists * feat(tracing): using tracing and zenoh-util init_log (#308) * feat(tracing): using tracing and zenoh-util init_log Signed-off-by: gabrik * chore: adding Cargo.lock Signed-off-by: gabrik * chore: updated Cargo.toml.in Signed-off-by: gabrik * feat(tracing): using zenoh main branch Signed-off-by: gabrik --------- Signed-off-by: gabrik * build: Sync with eclipse-zenoh/zenoh@580f0b6 from 2024-04-11 (#335) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@23c5932 from 2024-04-16 (#337) Co-authored-by: eclipse-zenoh-bot * fix: Support jq 1.6 ubuntu-22.04 runners use jq 1.6 which doesn't recognize a dot for `[]` value iterator. See: jqlang/jq#1168. * chore: using new try_init_log_from_env Signed-off-by: gabrik * Align examples and remove reading from stdin (#255) * Remove reading from stdin, align example implementations * Add argument parsing implementation for examples * Add argument parsing to examples, format files * Replace getchar with sleep in z_pong example * Fix typo in include * Use null-pointers instead of empty strings, remove unnecessary mallocs * Free returned pointer after parse_pos_args usage * Add common and positional args parsing to z_ping example * Add formatting for parsed config options * Add const to function parameters * Update mode option help * Fix pos_args memory leak * Refactor parse_args, remove possible strcpy buffer overflow * Change parse_args function returns to const where applicable * Fix const initialization warning * Remove redundant const for value parameters * Fix buf variable memory leak * Update insert json-list config error message * Add usage example for -e and -l arguments in help * Update example notation in help message Co-authored-by: Alexander * Update example notation in help message (2/2) * Fix parameter in error message Co-authored-by: Alexander --------- Co-authored-by: Alexander * Bugfix: Unable to build z_queryable_with_channels.c (#340) Signed-off-by: ChenYing Kuo * build: Sync with eclipse-zenoh/zenoh@0283aaa from 2024-04-19 (#341) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@e8916bf from 2024-04-26 (#343) Co-authored-by: eclipse-zenoh-bot * Update README and specify Rust version (#342) * Clean up the Markdown format. Signed-off-by: ChenYing Kuo * Specify Rust version in README. Signed-off-by: ChenYing Kuo --------- Signed-off-by: ChenYing Kuo * build: Sync with eclipse-zenoh/zenoh@ea604b6 from 2024-04-29 (#344) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@371ca6b from 2024-04-30 (#347) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@7a47445 from 2024-05-03 (#348) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@f5195c0 from 2024-05-03 (#350) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@e53364f from 2024-05-04 (#351) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@7e5d5e8 from 2024-05-07 (#355) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@b8dd01d from 2024-05-07 (#356) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@45e05f0 from 2024-05-13 (#360) Co-authored-by: eclipse-zenoh-bot * Fix build with CMAKE_BUILD_TYPE=None This is the default build type for debhelper (Debian). * build: Sync with eclipse-zenoh/zenoh@763a05f from 2024-05-14 (#363) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@75aa273 from 2024-05-15 (#364) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@25f06bd from 2024-05-21 (#369) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@3118d31 from 2024-05-28 (#399) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@009f666 from 2024-05-30 (#411) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@d574654 from 2024-06-03 (#420) Co-authored-by: eclipse-zenoh-bot * chore: Update artifacts action to v4 (#421) artifacts actions v3 are deprecated * build: Sync with eclipse-zenoh/zenoh@c279982 from 2024-06-05 (#424) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@d8e66de from 2024-06-10 (#436) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@9d09742 from 2024-06-11 (#446) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@ed6c636 from 2024-06-12 (#450) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@8160b01 from 2024-06-13 (#457) Co-authored-by: eclipse-zenoh-bot * Enable releasing from any branch (#456) * build: Sync with eclipse-zenoh/zenoh@7adad94 from 2024-06-14 (#460) Co-authored-by: eclipse-zenoh-bot * Update to latest zenoh * Replace `-rc` with `-pre` and document versioning (#466) * build: Sync with eclipse-zenoh/zenoh@2500e5a from 2024-06-20 (#467) Co-authored-by: eclipse-zenoh-bot * macro generation * moved types added to decl * moved type drop * switched rust to z_moved * moved closures * build macros fixed * z_move name restored * into_rust_type for moved, payloads * tests updated * cargo fmt * moved structs in some drops/undeclares * moved as separate parameter * removed asref from moved * moved unfinished * build: Sync with eclipse-zenoh/zenoh@869ace6 from 2024-07-02 (#494) Co-authored-by: eclipse-zenoh-bot * moved type with into_rust_type trait, comiles without shm * build with shm passed * option added to some decl_c_type * clippy fix * build fix * moved types added * task moved used * build: Sync with eclipse-zenoh/zenoh@b93ca84 from 2024-07-03 (#500) Co-authored-by: eclipse-zenoh-bot * some examples fixes * macros corrected to use auto derive loaned type from owned feature * optional comma allowed in macros where forgotten * property moved get * put options move * publisher delete options made simpler * put options with moved * delete options timestamp simplified * more moved in options, timestamp simplified * examples,tests updated * tests compile fixes * fix for test failure due to calling z_moved_xxx_t destructor on unitialized memory * cargo fmt imports * build fixes * build: Sync with eclipse-zenoh/zenoh@b3e42ce from 2024-07-08 (#508) Co-authored-by: eclipse-zenoh-bot * Ensure that find_package(zenohc) can be called two times (#470) * Update CMakeLists.txt (#473) * Install zenohc.dll in /bin on Windows (#471) * build: Sync with eclipse-zenoh/zenoh@0a969cb from 2024-07-25 (#546) Co-authored-by: eclipse-zenoh-bot * build: Sync with eclipse-zenoh/zenoh@e587aa9 from 2024-07-26 (#552) Co-authored-by: eclipse-zenoh-bot * some xompile errors fixed * some build errors fixed * some build errors fixed * build fixes * cargo fmt * into_rust_type usage fixes * encoding drop fixed * restored headers * zcu renamed back to zc * zcu renamed back to zc * z_xxx_move is static inline, cpp fixes * build: Sync with eclipse-zenoh/zenoh@2d88c7b from 2024-07-29 (#556) Co-authored-by: eclipse-zenoh-bot * clang format from start * cargo fmt * macros contains funcions now, it needs types defined * removed zenoh_macros include * zenoh_macros include returned back to place * C++ build test added, fails for now * C++ enabling correction * C++ compilation for tests added * C++ build test * cargo lock update * retrun value if not void from template functions * cargo fmt * build fixes * build fix after cargo.lock update * moved types for buffer creation functions * clippy fix * clippy fix: c_char can be i8 or u8 depending on platform * headers restored * cargo fmt * -c c++ flag for clang only * c++ build fix - brackets removed * type specific take functions added, _ptr in moved * generic_take_cpp * z_take impls at the end * take funcs before generics * take moved after null * names fix * missing null functioj added * tests fixed for c++ * explicit null calls * fix generic parameter names c compilation * null call fix * misprint fixed * return removed * Rename `close` to `undeclare` for Publication Cache and Querying Subscriber * Temporarily use original pull request branch * Update to eclipse-zenoh/zenoh@ce4e9bf * Fix `z_ref_shm_client_storage_global` * Update Cargo.toml * decl_c_type corrected * cargo check run * borrow error fix * compilation fix * parse arg fix * example compilation fix * examples compile fix * examples build fixes * removed duplicated z_config_default (it's called in parsing args later) * clang format * clang format * cargo.toml restore --------- Signed-off-by: gabrik Signed-off-by: ChenYing Kuo Co-authored-by: Mahmoud Mazouz Co-authored-by: Denis Biryukov Co-authored-by: eclipse-zenoh-bot <61247838+eclipse-zenoh-bot@users.noreply.github.com> Co-authored-by: eclipse-zenoh-bot Co-authored-by: Mahmoud Mazouz Co-authored-by: Gabriele Baldoni Co-authored-by: gabrik Co-authored-by: oteffahi <70609372+oteffahi@users.noreply.github.com> Co-authored-by: Alexander Co-authored-by: ChenYing Kuo (CY) Co-authored-by: Jochen Sprickerhof Co-authored-by: Diogo Matsubara Co-authored-by: OlivierHecart Co-authored-by: Silvio Traversaro Co-authored-by: Luca Cominardi --- .gitignore | 7 +- examples/parse_args.h | 216 +++++++++++++++++++++++++++ examples/z_delete.c | 63 ++++++-- examples/z_get.c | 96 ++++++++---- examples/z_get_liveliness.c | 74 ++++++--- examples/z_info.c | 49 ++++-- examples/z_liveliness.c | 89 +++++++---- examples/z_non_blocking_get.c | 76 +++++++--- examples/z_ping.c | 87 +++++------ examples/z_pong.c | 71 +++++---- examples/z_pub.c | 99 ++++++++---- examples/z_pub_attachment.c | 79 +++++++--- examples/z_pub_cache.c | 85 ++++++++--- examples/z_pub_shm.c | 92 ++++++++---- examples/z_pub_thr.c | 71 ++++++--- examples/z_pull.c | 92 ++++++++---- examples/z_put.c | 79 +++++++--- examples/z_query_sub.c | 87 +++++++---- examples/z_queryable.c | 90 +++++++---- examples/z_queryable_with_channels.c | 85 ++++++++--- examples/z_sub.c | 91 +++++++---- examples/z_sub_attachment.c | 88 +++++++---- examples/z_sub_liveliness.c | 85 +++++++---- examples/z_sub_thr.c | 62 ++++++-- src/keyexpr.rs | 2 +- src/liveliness.rs | 2 +- 26 files changed, 1451 insertions(+), 566 deletions(-) create mode 100644 examples/parse_args.h diff --git a/.gitignore b/.gitignore index 8fbb4b478..f7b04b718 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,9 @@ include/zenoh_opaque.h # Build resources .build_resources* -src/opaque_types/mod.rs \ No newline at end of file +src/opaque_types/mod.rs + +# CMake +CMakeFiles/ +debug/ +release/ diff --git a/examples/parse_args.h b/examples/parse_args.h new file mode 100644 index 000000000..7708ba6b5 --- /dev/null +++ b/examples/parse_args.h @@ -0,0 +1,216 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#pragma once + +#include +#include +#include + +#include "zenoh.h" + +#define COMMON_HELP \ + "\ + -c (optional, string): The path to a configuration file for the session. If this option isn't passed, the default configuration will be used.\n\ + -m (optional, string, default='peer'): The zenoh session mode. [possible values: peer, client, router]\n\ + -e (optional, string): endpoint to connect to. Repeat option to pass multiple endpoints. If none are given, endpoints will be discovered through multicast-scouting if it is enabled.\n\ + e.g.: '-e tcp/192.168.1.1:7447'\n\ + -l (optional, string): locator to listen on. Repeat option to pass multiple locators. If none are given, the default configuration will be used.\n\ + e.g.: '-l tcp/192.168.1.1:7447'\n\ + --no-multicast-scouting (optional): By default zenohd replies to multicast scouting messages for being discovered by peers and clients. This option disables this feature.\n\ +" + +/** + * Parse an option of format `-f`, `--flag`, `-f ` or `--flag ` from `argv`. If found, the option and its + * eventual value are each replaced by NULL in `argv` + * @param argc: argc passed from `main` function + * @param argv: argv passed from `main` function + * @param opt: option to parse (without `-` or `--` prefix) + * @param opt_has_value: if true, the option is of format `-f ` or `--flag ` and `value` will be returned + * if found, else an error message is printed and program will exit. If false, option has no value and a non-null + * pointer will be returned if option is found. + * @returns NULL if option was not found, else a non-null value depending on if `opt_has_value`. + */ +const char* parse_opt(int argc, char** argv, const char* opt, bool opt_has_value) { + size_t optlen = strlen(opt); + for (int i = 1; i < argc; i++) { + if (argv[i] == NULL) { + continue; + } + size_t len = strlen(argv[i]); + if (len < 2) { + continue; + } + if (optlen == 1) { + if (argv[i][0] == '-' && argv[i][1] == opt[0]) { + argv[i] = NULL; + if (!opt_has_value) { + return (char*)opt; + } else if (i + 1 < argc && argv[i + 1]) { + char* value = argv[i + 1]; + argv[i + 1] = NULL; + return value; + } else { + printf("Option -%s given without a value\n", opt); + exit(-1); + } + } + } else if (optlen > 1 && len > 3 && argv[i][0] == '-' && argv[i][1] == '-') { + // Note: support for '--arg=' syntax can be added here + if (strcmp(argv[i] + 2, opt) == 0) { + argv[i] = NULL; + if (!opt_has_value) { + return (char*)opt; + } else if (i + 1 < argc && argv[i + 1]) { + char* value = argv[i + 1]; + argv[i + 1] = NULL; + return value; + } else { + printf("Option --%s given without a value\n", opt); + exit(-1); + } + } + } + } + return NULL; +} + +/** + * Check if any options remains in `argv`. Must be called after all expected options are parsed + * @param argc + * @param argv + * @returns NULL if no option was found, else the first option string that was found + */ +const char* check_unknown_opts(int argc, char** const argv) { + for (int i = 1; i < argc; i++) { + if (argv[i] && argv[i][0] == '-') { + return argv[i]; + } + } + return NULL; +} + +/** + * Parse positional arguments from `argv`. Must be called after all expected options are parsed, and after checking that + * no unknown options remain in `argv` + * @param argc + * @param argv + * @param nb_args: number of expected positional arguments + * @returns NULL if found more positional arguments than `nb_args`. Else an array of found arguments in order, followed + * by NULL values if found less positional arguments than `nb_args` + * @note Returned pointer is dynamically allocated and must be freed + */ +char** parse_pos_args(const int argc, char** argv, const size_t nb_args) { + char** pos_argv = (char**)calloc(nb_args, sizeof(char*)); + size_t pos_argc = 0; + for (int i = 1; i < argc; i++) { + if (argv[i]) { + pos_argc++; + if (pos_argc > nb_args) { + free(pos_argv); + return NULL; + } + pos_argv[pos_argc - 1] = argv[i]; + } + } + return pos_argv; +} + +/** + * Parse zenoh options that require a JSON-serialized list (-e, -l from common args) and add them to + * `config`. Prints error message and exits if fails to insert parsed values + * @param argc + * @param argv + * @param opt: option to parse (without `-` or `--` prefix) + * @param config: address of an owned zenoh configuration + * @param config_key: zenoh configuration key under which the parsed values will be inserted + */ +void parse_zenoh_json_list_config(int argc, char** argv, const char* opt, const char* config_key, + z_owned_config_t* config) { + char* buf = (char*)calloc(1, sizeof(char)); + const char* value = parse_opt(argc, argv, opt, true); + while (value) { + size_t len_newbuf = strlen(buf) + strlen(value) + 4; // value + quotes + comma + nullbyte + char* newbuf = (char*)malloc(len_newbuf); + snprintf(newbuf, len_newbuf, "%s'%s',", buf, value); + free(buf); + buf = newbuf; + value = parse_opt(argc, argv, opt, true); + } + size_t buflen = strlen(buf); + if (buflen > 0) { + // remove trailing comma + buf[buflen - 1] = '\0'; + buflen--; + // add list delimiters + size_t json_list_len = buflen + 3; // buf + brackets + nullbyte + char* json_list = (char*)malloc(json_list_len); + snprintf(json_list, json_list_len, "[%s]", buf); + // insert in config + if (zc_config_insert_json(z_loan_mut(*config), config_key, json_list) < 0) { + printf( + "Couldn't insert value `%s` in configuration at `%s`\n`%s` is either not a JSON-serialized list of " + "strings, or values within the list do not respect expected format for `%s`\n", + json_list, config_key, json_list, config_key); + free(json_list); + exit(-1); + } + free(json_list); + } + free(buf); +} + +/** + * Parse zenoh options that are common to all examples (-c, -m, -e, -l, --no-multicast-scouting) and add them to + * `config` + * @param argc + * @param argv + * @param config: address of an owned zenoh configuration + */ +void parse_zenoh_common_args(const int argc, char** argv, z_owned_config_t* config) { + // -c: A configuration file. + const char* config_file = parse_opt(argc, argv, "c", true); + if (config_file) { + zc_config_from_file(config, config_file); + } else { + z_config_default(config); + } + // -m: The Zenoh session mode [default: peer]. + const char* mode = parse_opt(argc, argv, "m", true); + if (mode) { + size_t buflen = strlen(mode) + 3; // mode + quotes + nullbyte + char* buf = (char*)malloc(buflen); + snprintf(buf, buflen, "'%s'", mode); + if (zc_config_insert_json(z_loan_mut(*config), Z_CONFIG_MODE_KEY, buf) < 0) { + printf( + "Couldn't insert value `%s` in configuration at `%s`. Value must be one of: 'client', 'peer' or " + "'router'\n", + mode, Z_CONFIG_MODE_KEY); + free(buf); + exit(-1); + } + free(buf); + } + // -e: Endpoint to connect to. Can be repeated + parse_zenoh_json_list_config(argc, argv, "e", Z_CONFIG_CONNECT_KEY, config); + // -l: Endpoint to listen on. Can be repeated + parse_zenoh_json_list_config(argc, argv, "l", Z_CONFIG_LISTEN_KEY, config); + // --no-multicast-scrouting: Disable the multicast-based scouting mechanism. + const char* no_multicast_scouting = parse_opt(argc, argv, "no-multicast-scouting", false); + if (no_multicast_scouting && + zc_config_insert_json(z_loan_mut(*config), Z_CONFIG_MULTICAST_SCOUTING_KEY, "false") < 0) { + printf("Couldn't disable multicast-scouting.\n"); + exit(-1); + } +} diff --git a/examples/z_delete.c b/examples/z_delete.c index d0478408c..67c0f083a 100644 --- a/examples/z_delete.c +++ b/examples/z_delete.c @@ -14,24 +14,19 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-put"; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-put" - if (argc > 1) keyexpr = argv[1]; +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 3) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -40,9 +35,9 @@ int main(int argc, char **argv) { exit(-1); } - printf("Deleting resources matching '%s'...\n", keyexpr); + printf("Deleting resources matching '%s'...\n", args.keyexpr); z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); int res = z_delete(z_loan(s), z_loan(ke), NULL); if (res < 0) { printf("Delete failed...\n"); @@ -51,3 +46,41 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_delete [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_get.c b/examples/z_get.c index f53c49935..c26b9cbb9 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -14,38 +14,27 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *expr = "demo/example/**"; - char *value = NULL; - switch (argc) { - default: - case 3: - value = argv[2]; - case 2: - expr = argv[1]; - break; - case 1: - value = "Test Value"; - break; - } +#define DEFAULT_SELECTOR "demo/example/**" +#define DEFAULT_VALUE NULL + +struct args_t { + char* selector; // -s + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +int main(int argc, char** argv) { + z_owned_config_t config; + struct args_t args = parse_args(argc, argv, &config); + z_view_keyexpr_t keyexpr; - if (z_view_keyexpr_from_str(&keyexpr, expr) < 0) { - printf("%s is not a valid key expression", expr); + if (z_view_keyexpr_from_str(&keyexpr, args.selector) < 0) { + printf("%s is not a valid key expression", args.selector); exit(-1); } - z_owned_config_t config; - z_config_default(&config); - if (argc > 3) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } printf("Opening session...\n"); z_owned_session_t s; @@ -54,7 +43,7 @@ int main(int argc, char **argv) { exit(-1); } - printf("Sending Query '%s'...\n", expr); + printf("Sending Query '%s'...\n", args.selector); z_owned_fifo_handler_reply_t handler; z_owned_closure_reply_t closure; z_fifo_channel_reply_new(&closure, &handler, 16); @@ -63,8 +52,8 @@ int main(int argc, char **argv) { z_get_options_default(&opts); z_owned_bytes_t payload; - if (value != NULL) { - z_bytes_from_static_str(&payload, value); + if (args.value != NULL) { + z_bytes_from_static_str(&payload, args.value); opts.payload = z_move(payload); } z_get(z_loan(s), z_loan(keyexpr), "", z_move(closure), @@ -73,7 +62,7 @@ int main(int argc, char **argv) { for (z_result_t res = z_recv(z_loan(handler), &reply); res == Z_OK; res = z_recv(z_loan(handler), &reply)) { if (z_reply_is_ok(z_loan(reply))) { - const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + const z_loaned_sample_t* sample = z_reply_ok(z_loan(reply)); z_view_string_t key_str; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_str); @@ -93,4 +82,47 @@ int main(int argc, char **argv) { z_drop(z_move(handler)); z_close(z_move(s)); return 0; -} \ No newline at end of file +} + +void print_help() { + printf( + "\ + Usage: z_get [OPTIONS]\n\n\ + Options:\n\ + -s (optional, string, default='%s'): The selection of resources to query\n\ + -v (optional, string): An optional value to put in the query\n", + DEFAULT_SELECTOR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* selector = parse_opt(argc, argv, "s", true); + if (!selector) { + selector = DEFAULT_SELECTOR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.selector = (char*)selector, .value = (char*)value}; +} diff --git a/examples/z_get_liveliness.c b/examples/z_get_liveliness.c index d7b0b6737..60e101416 100644 --- a/examples/z_get_liveliness.c +++ b/examples/z_get_liveliness.c @@ -14,30 +14,24 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *expr = "group1/**"; - if (argc > 1) { - expr = argv[1]; - } +#define DEFAULT_KEYEXPR "group1/**" - z_view_keyexpr_t keyexpr; - if (z_view_keyexpr_from_str(&keyexpr, expr) < 0) { - printf("%s is not a valid key expression\n", expr); - exit(-1); - } +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } + struct args_t args = parse_args(argc, argv, &config); + + z_view_keyexpr_t keyexpr; + if (z_view_keyexpr_from_str(&keyexpr, args.keyexpr) < 0) { + printf("%s is not a valid key expression\n", args.keyexpr); + exit(-1); } z_owned_session_t s; @@ -47,7 +41,7 @@ int main(int argc, char **argv) { exit(-1); } - printf("Sending liveliness query '%s'...\n", expr); + printf("Sending liveliness query '%s'...\n", args.keyexpr); z_owned_fifo_handler_reply_t handler; z_owned_closure_reply_t closure; z_fifo_channel_reply_new(&closure, &handler, 16); @@ -55,7 +49,7 @@ int main(int argc, char **argv) { z_owned_reply_t reply; for (z_result_t res = z_recv(z_loan(handler), &reply); res == Z_OK; res = z_recv(z_loan(handler), &reply)) { if (z_reply_is_ok(z_loan(reply))) { - const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + const z_loaned_sample_t* sample = z_reply_ok(z_loan(reply)); z_view_string_t key_str; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_str); printf(">> Alive token ('%.*s')\n", (int)z_string_len(z_loan(key_str)), z_string_data(z_loan(key_str))); @@ -69,3 +63,41 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_get_liveliness [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to query\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_info.c b/examples/z_info.c index 584bf5d05..c3eb28d43 100644 --- a/examples/z_info.c +++ b/examples/z_info.c @@ -13,27 +13,21 @@ #include +#include "parse_args.h" #include "zenoh.h" -void print_zid(const z_id_t *id, void *ctx) { +void parse_args(int argc, char** argv, z_owned_config_t* config); + +void print_zid(const z_id_t* id, void* ctx) { for (int i = 0; i < 16; i++) { printf("%02x", id->id[i]); } printf("\n"); } -int main(int argc, char **argv) { +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 1) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[1], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -60,3 +54,34 @@ int main(int argc, char **argv) { z_close(z_move(s)); } + +void print_help() { + printf( + "\ + Usage: z_info [OPTIONS]\n\n\ + Options:\n"); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +void parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); +} diff --git a/examples/z_liveliness.c b/examples/z_liveliness.c index ab82bc4ff..de0dd95db 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -14,30 +14,24 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *expr = "group1/zenoh-c"; - if (argc > 1) { - expr = argv[1]; - } +#define DEFAULT_KEYEXPR "group1/zenoh-rs" - z_view_keyexpr_t keyexpr; - if (z_view_keyexpr_from_str(&keyexpr, expr) < 0) { - printf("%s is not a valid key expression\n", expr); - exit(-1); - } +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } + struct args_t args = parse_args(argc, argv, &config); + + z_view_keyexpr_t keyexpr; + if (z_view_keyexpr_from_str(&keyexpr, args.keyexpr) < 0) { + printf("%s is not a valid key expression\n", args.keyexpr); + exit(-1); } printf("Opening session...\n"); @@ -47,26 +41,61 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring liveliness token '%s'...\n", expr); + printf("Declaring liveliness token '%s'...\n", args.keyexpr); zc_owned_liveliness_token_t token; if (zc_liveliness_declare_token(&token, z_loan(s), z_loan(keyexpr), NULL) < 0) { printf("Unable to create liveliness token!\n"); exit(-1); } - printf("Enter 'd' to undeclare liveliness token, 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } else if (c == 'd') { - printf("Undeclaring liveliness token...\n"); - z_drop(z_move(token)); - } + printf("Press CTRL-C to undeclare liveliness token and quit...\n"); + while (1) { + z_sleep_s(1); } + // LivelinessTokens are automatically closed when dropped + // Use the code below to manually undeclare it if needed + printf("Undeclaring liveliness token...\n"); z_drop(z_move(token)); + z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_liveliness [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression the liveliness token\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_non_blocking_get.c b/examples/z_non_blocking_get.c index 7a76bc692..1f834d769 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -14,29 +14,25 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *expr = "demo/example/**"; - if (argc > 1) { - expr = argv[1]; - } +#define DEFAULT_SELECTOR "demo/example/**" + +struct args_t { + char* selector; // -s +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +int main(int argc, char** argv) { + z_owned_config_t config; + struct args_t args = parse_args(argc, argv, &config); + z_view_keyexpr_t keyexpr; - if (z_view_keyexpr_from_str(&keyexpr, expr) < 0) { - printf("%s is not a valid key expression", expr); + if (z_view_keyexpr_from_str(&keyexpr, args.selector) < 0) { + printf("%s is not a valid key expression", args.selector); exit(-1); } - z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } printf("Opening session...\n"); z_owned_session_t s; @@ -45,7 +41,7 @@ int main(int argc, char **argv) { exit(-1); } - printf("Sending Query '%s'...\n", expr); + printf("Sending Query '%s'...\n", args.selector); z_get_options_t opts; z_get_options_default(&opts); opts.target = Z_QUERY_TARGET_ALL; @@ -62,7 +58,7 @@ int main(int argc, char **argv) { continue; } if (z_reply_is_ok(z_loan(reply))) { - const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + const z_loaned_sample_t* sample = z_reply_ok(z_loan(reply)); z_view_string_t key_str; z_owned_string_t payload_string; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_str); @@ -78,4 +74,42 @@ int main(int argc, char **argv) { z_drop(z_move(handler)); z_close(z_move(s)); return 0; -} \ No newline at end of file +} + +void print_help() { + printf( + "\ + Usage: z_non_blocking_get [OPTIONS]\n\n\ + Options:\n\ + -s (optional, string, default='%s'): The selection of resources to query\n", + DEFAULT_SELECTOR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* selector = parse_opt(argc, argv, "s", true); + if (!selector) { + selector = DEFAULT_SELECTOR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.selector = (char*)selector}; +} diff --git a/examples/z_ping.c b/examples/z_ping.c index c5ab59364..436feeb6d 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -3,6 +3,7 @@ #include #include +#include "parse_args.h" #include "zenoh.h" #define DEFAULT_PKT_SIZE 8 @@ -27,32 +28,15 @@ struct args_t { unsigned int size; // -s unsigned int number_of_pings; // -n unsigned int warmup_ms; // -w - char* config_path; // -c - uint8_t help_requested; // -h }; -struct args_t parse_args(int argc, char** argv); +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); int main(int argc, char** argv) { - struct args_t args = parse_args(argc, argv); - if (args.help_requested) { - printf( - "\ - -n (optional, int, default=%d): the number of pings to be attempted\n\ - -s (optional, int, default=%d): the size of the payload embedded in the ping and repeated by the pong\n\ - -w (optional, int, default=%d): the warmup time in ms during which pings will be emitted but not measured\n\ - -c (optional, string): the path to a configuration file for the session. If this option isn't passed, the default configuration will be used.\n\ - ", - DEFAULT_PING_NB, DEFAULT_PKT_SIZE, DEFAULT_WARMUP_MS); - return 1; - } + z_owned_config_t config; + struct args_t args = parse_args(argc, argv, &config); + z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config; - if (args.config_path) { - zc_config_from_file(&config, args.config_path); - } else { - z_config_default(&config); - } z_owned_session_t session; z_open(&session, z_move(config)); z_view_keyexpr_t ping; @@ -110,44 +94,53 @@ int main(int argc, char** argv) { z_close(z_move(session)); } -char* getopt(int argc, char** argv, char option) { - for (int i = 0; i < argc; i++) { - size_t len = strlen(argv[i]); - if (len >= 2 && argv[i][0] == '-' && argv[i][1] == option) { - if (len > 2 && argv[i][2] == '=') { - return argv[i] + 3; - } else if (i + 1 < argc) { - return argv[i + 1]; - } - } - } - return NULL; +void print_help() { + printf( + "\ + Usage: z_ping [OPTIONS]\n\n\ + Options:\n\ + -n (optional, int, default=%d): The number of pings to be attempted\n\ + -s (optional, int, default=%d): The size of the payload embedded in the ping and repeated by the pong\n\ + -w (optional, int, default=%d): The warmup time in ms during which pings will be emitted but not measured\n", + DEFAULT_PKT_SIZE, DEFAULT_PING_NB, DEFAULT_WARMUP_MS); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); } -struct args_t parse_args(int argc, char** argv) { - for (int i = 0; i < argc; i++) { - if (strcmp(argv[i], "-h") == 0) { - return (struct args_t){.help_requested = 1}; - } +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); } - char* arg = getopt(argc, argv, 's'); + const char* arg = parse_opt(argc, argv, "s", true); unsigned int size = DEFAULT_PKT_SIZE; if (arg) { size = atoi(arg); } - arg = getopt(argc, argv, 'n'); + arg = parse_opt(argc, argv, "n", true); unsigned int number_of_pings = DEFAULT_PING_NB; if (arg) { number_of_pings = atoi(arg); } - arg = getopt(argc, argv, 'w'); + arg = parse_opt(argc, argv, "w", true); unsigned int warmup_ms = DEFAULT_WARMUP_MS; if (arg) { warmup_ms = atoi(arg); } - return (struct args_t){.help_requested = 0, - .size = size, - .number_of_pings = number_of_pings, - .warmup_ms = warmup_ms, - .config_path = getopt(argc, argv, 'c')}; -} \ No newline at end of file + parse_zenoh_common_args(argc, argv, config); + arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.size = size, .number_of_pings = number_of_pings, .warmup_ms = warmup_ms}; +} diff --git a/examples/z_pong.c b/examples/z_pong.c index e3a312035..f58a3fe96 100644 --- a/examples/z_pong.c +++ b/examples/z_pong.c @@ -1,8 +1,11 @@ #include #include +#include "parse_args.h" #include "zenoh.h" +void parse_args(int argc, char** argv, z_owned_config_t* config); + void callback(const z_loaned_sample_t* sample, void* context) { const z_loaned_publisher_t* pub = z_loan(*(z_owned_publisher_t*)context); z_owned_bytes_t payload; @@ -17,26 +20,10 @@ void drop(void* context) { // which makes passing a pointer to the stack safe as long as `sub` is dropped in a scope where `pub` is still // valid. } -struct args_t { - char* config_path; // -c - uint8_t help_requested; // -h -}; -struct args_t parse_args(int argc, char** argv); int main(int argc, char** argv) { - struct args_t args = parse_args(argc, argv); - if (args.help_requested) { - printf( - "-c (optional, string): the path to a configuration file for the session. If this option isn't passed, the " - "default configuration will be used.\n"); - return 1; - } z_owned_config_t config; - if (args.config_path) { - zc_config_from_file(&config, args.config_path); - } else { - z_config_default(&config); - } + parse_args(argc, argv, &config); z_owned_session_t session; z_open(&session, z_move(config)); @@ -50,31 +37,41 @@ int main(int argc, char** argv) { z_closure(&respond, callback, drop, (void*)&pub); z_owned_subscriber_t sub; z_declare_subscriber(&sub, z_loan(session), z_loan(ping), z_move(respond), NULL); - while (getchar() != 'q') { + + while (1) { + z_sleep_s(1); } z_undeclare_subscriber(z_move(sub)); z_close(z_move(session)); } -char* getopt(int argc, char** argv, char option) { - for (int i = 0; i < argc; i++) { - size_t len = strlen(argv[i]); - if (len >= 2 && argv[i][0] == '-' && argv[i][1] == option) { - if (len > 2 && argv[i][2] == '=') { - return argv[i] + 3; - } else if (i + 1 < argc) { - return argv[i + 1]; - } - } - } - return NULL; +void print_help() { + printf( + "\ + Usage: z_pong [OPTIONS]\n\n\ + Options:\n"); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); } -struct args_t parse_args(int argc, char** argv) { - for (int i = 0; i < argc; i++) { - if (strcmp(argv[i], "-h") == 0) { - return (struct args_t){.help_requested = 1}; - } +void parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); } - return (struct args_t){.help_requested = 0, .config_path = getopt(argc, argv, 'c')}; -} \ No newline at end of file + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); +} diff --git a/examples/z_pub.c b/examples/z_pub.c index 05d5ae2ab..6aa478a30 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -14,10 +14,21 @@ #include #include +#include "parse_args.h" #include "zenoh.h" +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-pub" +#define DEFAULT_VALUE "Pub from C!" + +struct args_t { + char* keyexpr; // -k + char* value; // -v + bool add_matching_listener; // --add-matching-listener +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + #ifdef UNSTABLE -void matching_status_handler(const zc_matching_status_t *matching_status, void *arg) { +void matching_status_handler(const zc_matching_status_t* matching_status, void* arg) { if (matching_status->matching) { printf("Subscriber matched\n"); } else { @@ -26,26 +37,9 @@ void matching_status_handler(const zc_matching_status_t *matching_status, void * } #endif -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-pub"; - char *value = "Pub from C!"; - bool add_matching_listener = false; - - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; - if (argc > 3) add_matching_listener = atoi(argv[3]); - +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 4) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[4]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[4], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -54,10 +48,10 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); z_owned_publisher_t pub; z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare Publisher for key expression!\n"); exit(-1); @@ -65,23 +59,24 @@ int main(int argc, char **argv) { #ifdef UNSTABLE zc_owned_matching_listener_t listener; - if (add_matching_listener) { + if (args.add_matching_listener) { zc_owned_closure_matching_status_t callback; z_closure(&callback, matching_status_handler, NULL, NULL); zc_publisher_matching_listener_declare(&listener, z_loan(pub), z_move(callback)); } #else - if (add_matching_listener) { + if (args.add_matching_listener) { printf("To enable matching listener you must compile Zenoh-c with unstable feature support!\n"); exit(-1); } #endif + printf("Press CTRL-C to quit...\n"); char buf[256] = {}; for (int idx = 0; 1; ++idx) { z_sleep_s(1); - sprintf(buf, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + sprintf(buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); z_publisher_put_options_t options; z_publisher_put_options_default(&options); @@ -91,7 +86,7 @@ int main(int argc, char **argv) { z_publisher_put(z_loan(pub), z_move(payload), &options); } #ifdef UNSTABLE - if (add_matching_listener) { + if (args.add_matching_listener) { zc_publisher_matching_listener_undeclare(z_move(listener)); } #endif @@ -100,3 +95,53 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_pub [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n\ + -v (optional, string, default='%s'): The value to write\n\ + --add-matching-listener (optional): Add matching listener\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + const char* arg = parse_opt(argc, argv, "add-matching-listener", false); + bool add_matching_listener = false; + if (arg) { + add_matching_listener = true; + } + parse_zenoh_common_args(argc, argv, config); + arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){ + .keyexpr = (char*)keyexpr, .value = (char*)value, .add_matching_listener = add_matching_listener}; +} diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index ca13d1c2a..ed947262b 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -14,8 +14,12 @@ #include #include +#include "parse_args.h" #include "zenoh.h" +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-pub" +#define DEFAULT_VALUE "Pub from C!" + typedef struct kv_pair_t { const char* key; const char* value; @@ -39,24 +43,15 @@ bool create_attachment_iter(z_owned_bytes_t* kv_pair, void* context) { return true; }; -int main(int argc, char** argv) { - char* keyexpr = "demo/example/zenoh-c-pub"; - char* value = "Pub from C!"; - - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; +struct args_t { + char* keyexpr; // -k + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 3) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -65,9 +60,9 @@ int main(int argc, char** argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); z_owned_publisher_t pub; if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL)) { printf("Unable to declare Publisher for key expression!\n"); @@ -84,6 +79,7 @@ int main(int argc, char** argv) { z_owned_bytes_t attachment; z_owned_bytes_t payload; + printf("Press CTRL-C to quit...\n"); char buf[256]; char buf_ind[16]; for (int idx = 0; 1; ++idx) { @@ -96,8 +92,8 @@ int main(int argc, char** argv) { z_bytes_from_iter(&attachment, create_attachment_iter, (void*)&it); options.attachment = z_move(attachment); - sprintf(buf, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + sprintf(buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); z_bytes_serialize_from_str(&payload, buf); z_publisher_put(z_loan(pub), z_move(payload), &options); @@ -109,3 +105,46 @@ int main(int argc, char** argv) { return 0; } + +void print_help() { + printf( + "\ + Usage: z_pub_attachement [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n\ + -v (optional, string, default='%s'): The value to write\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr, .value = (char*)value}; +} diff --git a/examples/z_pub_cache.c b/examples/z_pub_cache.c index db931ae4e..e2de9caf9 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -14,26 +14,23 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-pub"; - char *value = "Pub from C!"; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-pub" +#define DEFAULT_VALUE "Pub from C!" +#define DEFAULT_HISTORY 1 - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; +struct args_t { + char* keyexpr; // -k + char* value; // -v + unsigned int history; // -i +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 3) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_ADD_TIMESTAMP_KEY, "true") < 0) { printf("Unable to configure timestamps!\n"); @@ -52,21 +49,22 @@ int main(int argc, char **argv) { pub_cache_opts.history = 42; pub_cache_opts.queryable_complete = false; - printf("Declaring publication cache on '%s'...\n", keyexpr); + printf("Declaring publication cache on '%s'...\n", args.keyexpr); ze_owned_publication_cache_t pub_cache; z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); if (ze_declare_publication_cache(&pub_cache, z_loan(s), z_loan(ke), &pub_cache_opts) != Z_OK) { printf("Unable to declare publication cache for key expression!\n"); exit(-1); } + printf("Press CTRL-C to quit...\n"); char buf[256]; for (int idx = 0; 1; ++idx) { z_sleep_s(1); - sprintf(buf, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + sprintf(buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); z_owned_bytes_t payload; z_bytes_serialize_from_str(&payload, buf); @@ -78,3 +76,52 @@ int main(int argc, char **argv) { return 0; } + +void print_help() { + printf( + "\ + Usage: z_pub_cache [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n\ + -v (optional, string, default='%s'): The value to write\n\ + -i (optional, int, default='%d'): The number of publications to keep in cache\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE, DEFAULT_HISTORY); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + const char* arg = parse_opt(argc, argv, "i", true); + unsigned int history = DEFAULT_HISTORY; + if (arg) { + history = atoi(arg); + } + parse_zenoh_common_args(argc, argv, config); + arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr, .value = (char*)value, .history = history}; +} diff --git a/examples/z_pub_shm.c b/examples/z_pub_shm.c index 7c0098912..461816aca 100644 --- a/examples/z_pub_shm.c +++ b/examples/z_pub_shm.c @@ -14,39 +14,22 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -#ifdef UNSTABLE -void matching_status_handler(const zc_matching_status_t *matching_status, void *arg) { - if (matching_status->matching) { - printf("Subscriber matched\n"); - } else { - printf("No Subscribers matched\n"); - } -} -#endif - -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-pub"; - char *value = "Pub from C SHM!"; - bool add_matching_listener = false; +#define N 10 +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-pub-shm" +#define DEFAULT_VALUE "Pub from C!" - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; - if (argc > 3) add_matching_listener = atoi(argv[3]); +struct args_t { + char* keyexpr; // -k + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - - if (argc > 4) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[4]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[4], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -55,10 +38,10 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); z_owned_publisher_t pub; z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare Publisher for key expression!\n"); exit(-1); @@ -95,9 +78,9 @@ int main(int argc, char **argv) { z_shm_provider_alloc_gc_defrag_blocking(&alloc, z_loan(provider), buf_ok_size, alignment); if (z_check(alloc.buf)) { { - uint8_t *buf = z_shm_mut_data_mut(z_loan_mut(alloc.buf)); - sprintf((char *)buf, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + uint8_t* buf = z_shm_mut_data_mut(z_loan_mut(alloc.buf)); + sprintf((char*)buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); } z_publisher_put_options_t options; @@ -127,3 +110,46 @@ int main(int argc, char **argv) { return 0; } + +void print_help() { + printf( + "\ + Usage: z_pub_shm [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n\ + -v (optional, string, default='%s'): The value to write\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr, .value = (char*)value}; +} diff --git a/examples/z_pub_thr.c b/examples/z_pub_thr.c index 83601ef5d..ebd1d7f0f 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -14,30 +14,21 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - if (argc < 2) { - printf("USAGE:\n\tz_pub_thr []\n\n"); - exit(-1); - } +struct args_t { + unsigned int size; // positional_1 +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); - char *keyexpr = "test/thr"; - size_t len = atoi(argv[1]); - uint8_t *value = (uint8_t *)z_malloc(len); - memset(value, 1, len); +int main(int argc, char** argv) { + char* keyexpr = "test/thr"; z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); + uint8_t* value = (uint8_t*)z_malloc(args.size); + memset(value, 1, args.size); z_owned_session_t s; if (z_open(&s, z_move(config)) < 0) { @@ -57,12 +48,52 @@ int main(int argc, char **argv) { exit(-1); } + printf("Press CTRL-C to quit...\n"); z_owned_bytes_t payload; while (1) { - z_bytes_from_buf(&payload, value, len, NULL, NULL); + z_bytes_from_buf(&payload, value, args.size, NULL, NULL); z_publisher_put(z_loan(pub), z_move(payload), NULL); } z_undeclare_publisher(z_move(pub)); z_close(z_move(s)); } + +void print_help() { + printf( + "\ + Usage: z_pub_thr [OPTIONS] \n\n\ + Arguments:\n\ + (required, int): Size of the payload to publish\n\n\ + Options:\n"); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args) { + printf("Unexpected additional positional arguments\n"); + exit(-1); + } + if (!pos_args[0]) { + printf(" argument is required\n"); + free(pos_args); + exit(-1); + } + unsigned int size = atoi(pos_args[0]); + free(pos_args); + return (struct args_t){.size = size}; +} diff --git a/examples/z_pull.c b/examples/z_pull.c index b24ca82fa..722b67f12 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -13,20 +13,19 @@ // #include +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind) { - switch (kind) { - case Z_SAMPLE_KIND_PUT: - return "PUT"; - case Z_SAMPLE_KIND_DELETE: - return "DELETE"; - default: - return "UNKNOWN"; - } -} +#define DEFAULT_KEYEXPR "demo/example/**" -void handle_sample(const z_loaned_sample_t *sample) { +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +const char* kind_to_str(z_sample_kind_t kind); + +void handle_sample(const z_loaned_sample_t* sample) { z_view_string_t keystr; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); z_owned_string_t payload_value; @@ -37,23 +36,9 @@ void handle_sample(const z_loaned_sample_t *sample) { z_drop(z_move(payload_value)); } -int main(int argc, char **argv) { - char *expr = "demo/example/**"; - if (argc > 1) { - expr = argv[1]; - } - +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -66,9 +51,9 @@ int main(int argc, char **argv) { z_owned_ring_handler_sample_t handler; z_owned_closure_sample_t closure; - printf("Declaring Subscriber on '%s'...\n", expr); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, expr); + z_view_keyexpr_from_str(&ke, args.keyexpr); z_owned_subscriber_t sub; if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { @@ -96,3 +81,52 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +const char* kind_to_str(z_sample_kind_t kind) { + switch (kind) { + case Z_SAMPLE_KIND_PUT: + return "PUT"; + case Z_SAMPLE_KIND_DELETE: + return "DELETE"; + default: + return "UNKNOWN"; + } +} + +void print_help() { + printf( + "\ + Usage: z_pull [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to subscribe to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_put.c b/examples/z_put.c index 26f1910d8..9117be365 100644 --- a/examples/z_put.c +++ b/examples/z_put.c @@ -14,27 +14,21 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-put"; - char *value = "Put from C!"; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-put" +#define DEFAULT_VALUE "Put from C!" - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; +struct args_t { + char* keyexpr; // -k + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - - if (argc > 3) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -43,17 +37,17 @@ int main(int argc, char **argv) { exit(-1); } - printf("Putting Data ('%s': '%s')...\n", keyexpr, value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, args.value); z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); z_owned_bytes_t payload; - z_bytes_from_static_str(&payload, value); + z_bytes_from_static_str(&payload, args.value); z_owned_bytes_t attachment, key, val; - z_bytes_from_static_str(&key, (char *)"hello"); - z_bytes_from_static_str(&val, (char *)"there"); + z_bytes_from_static_str(&key, (char*)"hello"); + z_bytes_from_static_str(&val, (char*)"there"); z_bytes_from_pair(&attachment, z_move(key), z_move(val)); z_put_options_t options; @@ -69,3 +63,46 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_put [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to write to\n\ + -v (optional, string, default='%s'): The value to write\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr, .value = (char*)value}; +} diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index 957860512..e17a48b43 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -13,14 +13,21 @@ // #include +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind); +#define DEFAULT_KEYEXPR "demo/example/**" -void data_handler(const z_loaned_sample_t *sample, void *arg) { +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +const char* kind_to_str(z_sample_kind_t kind); + +void data_handler(const z_loaned_sample_t* sample, void* arg) { z_view_string_t key_string; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); - z_owned_string_t payload_string; z_bytes_deserialize_into_string(z_sample_payload(sample), &payload_string); @@ -30,23 +37,9 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { z_drop(z_move(payload_string)); } -int main(int argc, char **argv) { - char *keyexpr = "demo/example/**"; - if (argc > 1) { - keyexpr = argv[1]; - } - +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -56,28 +49,22 @@ int main(int argc, char **argv) { } z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); ze_querying_subscriber_options_t sub_opts; ze_querying_subscriber_options_default(&sub_opts); - z_owned_closure_sample_t callback; z_closure(&callback, data_handler, NULL, NULL); - printf("Declaring querying subscriber on '%s'...\n", keyexpr); - + printf("Declaring querying subscriber on '%s'...\n", args.keyexpr); ze_owned_querying_subscriber_t sub; if (ze_declare_querying_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), &sub_opts) < 0) { printf("Unable to declare querying subscriber.\n"); exit(-1); } - printf("Enter 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } ze_undeclare_querying_subscriber(z_move(sub)); @@ -86,7 +73,7 @@ int main(int argc, char **argv) { return 0; } -const char *kind_to_str(z_sample_kind_t kind) { +const char* kind_to_str(z_sample_kind_t kind) { switch (kind) { case Z_SAMPLE_KIND_PUT: return "PUT"; @@ -96,3 +83,41 @@ const char *kind_to_str(z_sample_kind_t kind) { return "UNKNOWN"; } } + +void print_help() { + printf( + "\ + Usage: z_query_sub [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to subscribe to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_queryable.c b/examples/z_queryable.c index 7b86fcab2..5f5f48b71 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -14,12 +14,22 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -const char *keyexpr = "demo/example/zenoh-c-queryable"; -const char *value = "Queryable from C!"; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-queryable" +#define DEFAULT_VALUE "Queryable from C!" z_view_keyexpr_t ke; +struct args_t { + char *keyexpr; // -k + char *value; // -v +}; + +char *value; + +struct args_t parse_args(int argc, char **argv, z_owned_config_t *config); + void query_handler(const z_loaned_query_t *query, void *context) { z_view_string_t key_string; z_keyexpr_as_view_string(z_query_keyexpr(query), &key_string); @@ -53,20 +63,9 @@ void query_handler(const z_loaned_query_t *query, void *context) { } int main(int argc, char **argv) { - if (argc > 1) { - keyexpr = argv[1]; - } z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); + value = args.value; printf("Opening session...\n"); z_owned_session_t s; @@ -75,14 +74,14 @@ int main(int argc, char **argv) { exit(-1); } - if (z_view_keyexpr_from_str(&ke, keyexpr)) { - printf("%s is not a valid key expression", keyexpr); + if (z_view_keyexpr_from_str(&ke, args.keyexpr)) { + printf("%s is not a valid key expression", args.keyexpr); exit(-1); } - printf("Declaring Queryable on '%s'...\n", keyexpr); + printf("Declaring Queryable on '%s'...\n", args.keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler, NULL, (void *)keyexpr); + z_closure(&callback, query_handler, NULL, (void *)args.keyexpr); z_owned_queryable_t qable; if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { @@ -90,16 +89,55 @@ int main(int argc, char **argv) { exit(-1); } - printf("Enter 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } z_undeclare_queryable(z_move(qable)); z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_queryable [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression matching queries to reply to\n\ + -v (optional, string, default='%s'): The value to reply to queries with\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char **argv, z_owned_config_t *config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char *keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char *value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char *arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char **pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char *)keyexpr, .value = (char *)value}; +} diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 6ead46766..4e8b6b856 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -14,27 +14,23 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -const char *keyexpr = "demo/example/zenoh-c-queryable"; -const char *value = "Queryable from C!"; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-queryable" +#define DEFAULT_VALUE "Queryable from C!" + +struct args_t { + char* keyexpr; // -k + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + z_view_keyexpr_t ke; -int main(int argc, char **argv) { - if (argc > 1) { - keyexpr = argv[1]; - } +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); printf("Opening session...\n"); z_owned_session_t s; @@ -43,12 +39,12 @@ int main(int argc, char **argv) { exit(-1); } - if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { - printf("%s is not a valid key expression", keyexpr); + if (z_view_keyexpr_from_str(&ke, args.keyexpr) < 0) { + printf("%s is not a valid key expression", args.keyexpr); exit(-1); } - printf("Declaring Queryable on '%s'...\n", keyexpr); + printf("Declaring Queryable on '%s'...\n", args.keyexpr); z_owned_fifo_handler_query_t handler; z_owned_closure_query_t closure; z_fifo_channel_query_new(&closure, &handler, 16); @@ -59,17 +55,17 @@ int main(int argc, char **argv) { exit(-1); } - printf("^C to quit...\n"); + printf("Press CTRL-C to quit...\n"); z_owned_query_t oquery; for (z_result_t res = z_recv(z_loan(handler), &oquery); res == Z_OK; res = z_recv(z_loan(handler), &oquery)) { - const z_loaned_query_t *query = z_loan(oquery); + const z_loaned_query_t* query = z_loan(oquery); z_view_string_t key_string; z_keyexpr_as_view_string(z_query_keyexpr(query), &key_string); z_view_string_t params; z_query_parameters(query, ¶ms); - const z_loaned_bytes_t *payload = z_query_payload(query); + const z_loaned_bytes_t* payload = z_query_payload(query); if (payload != NULL && z_bytes_len(payload) > 0) { z_owned_string_t payload_string; z_bytes_deserialize_into_string(payload, &payload_string); @@ -87,7 +83,7 @@ int main(int argc, char **argv) { z_query_reply_options_default(&options); z_owned_bytes_t reply_payload; - z_bytes_from_static_str(&reply_payload, value); + z_bytes_from_static_str(&reply_payload, args.value); z_query_reply(query, z_loan(ke), z_move(reply_payload), &options); z_drop(z_move(oquery)); } @@ -97,3 +93,46 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_queryable_with_channels [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression matching queries to reply to\n\ + -v (optional, string, default='%s'): The value to reply to queries with\n", + DEFAULT_KEYEXPR, DEFAULT_VALUE); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + const char* value = parse_opt(argc, argv, "v", true); + if (!value) { + value = DEFAULT_VALUE; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr, .value = (char*)value}; +} diff --git a/examples/z_sub.c b/examples/z_sub.c index 07ae9111b..41dfdeff5 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -13,8 +13,16 @@ // #include +#include "parse_args.h" #include "zenoh.h" +#define DEFAULT_KEYEXPR "demo/example/**" + +struct args_t { + char *keyexpr; // -k +}; +struct args_t parse_args(int argc, char **argv, z_owned_config_t *config); + const char *kind_to_str(z_sample_kind_t kind); void data_handler(const z_loaned_sample_t *sample, void *arg) { @@ -31,26 +39,23 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { } int main(int argc, char **argv) { - char *keyexpr = "demo/example/**"; - if (argc > 1) { - keyexpr = argv[1]; - } - + z_owned_config_t config; + struct args_t args = parse_args(argc, argv, &config); z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); + z_view_keyexpr_from_str(&ke, args.keyexpr); - z_owned_config_t config; - z_config_default(&config); - - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } +#ifdef SHARED_MEMORY + // A probing procedure for shared memory is performed upon session opening. To enable `z_pub_shm` to operate + // over shared memory (and to not fallback on network mode), shared memory needs to be enabled also on the + // subscriber side. By doing so, the probing procedure will succeed and shared memory will operate as expected. + if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_SHARED_MEMORY_KEY, "true") < 0) { + printf( + "Couldn't insert value `true` in configuration at `%s`. This is likely because `%s` expects a " + "JSON-serialized value\n", + Z_CONFIG_SHARED_MEMORY_KEY, Z_CONFIG_SHARED_MEMORY_KEY); + exit(-1); } +#endif printf("Opening session...\n"); z_owned_session_t s; @@ -61,20 +66,16 @@ int main(int argc, char **argv) { z_owned_closure_sample_t callback; z_closure(&callback, data_handler, NULL, NULL); - printf("Declaring Subscriber on '%s'...\n", keyexpr); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); z_owned_subscriber_t sub; if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } - printf("Enter 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } z_undeclare_subscriber(z_move(sub)); @@ -91,4 +92,42 @@ const char *kind_to_str(z_sample_kind_t kind) { default: return "UNKNOWN"; } -} \ No newline at end of file +} + +void print_help() { + printf( + "\ + Usage: z_sub [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to subscribe to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char **argv, z_owned_config_t *config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char *keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char *arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char **pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char *)keyexpr}; +} diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index 7736ce442..20cef431e 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -14,11 +14,18 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind); +#define DEFAULT_KEYEXPR "demo/example/**" -void data_handler(const z_loaned_sample_t *sample, void *arg) { +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); +const char* kind_to_str(z_sample_kind_t kind); + +void data_handler(const z_loaned_sample_t* sample, void* arg) { z_view_string_t key_string; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); @@ -29,7 +36,7 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { (int)z_string_len(z_loan(key_string)), z_string_data(z_loan(key_string)), (int)z_string_len(z_loan(payload_string)), z_string_data(z_loan(payload_string))); - const z_loaned_bytes_t *attachment = z_sample_attachment(sample); + const z_loaned_bytes_t* attachment = z_sample_attachment(sample); // checks if attachment exists if (attachment != NULL) { // reads full attachment @@ -55,26 +62,11 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { z_drop(z_move(payload_string)); } -int main(int argc, char **argv) { - char *keyexpr = "demo/example/**"; - if (argc > 1) { - keyexpr = argv[1]; - } - - z_view_keyexpr_t ke; - z_view_keyexpr_from_str(&ke, keyexpr); - +int main(int argc, char** argv) { z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } - } + struct args_t args = parse_args(argc, argv, &config); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, args.keyexpr); printf("Opening session...\n"); z_owned_session_t s; @@ -85,20 +77,16 @@ int main(int argc, char **argv) { z_owned_closure_sample_t callback; z_closure(&callback, data_handler, NULL, NULL); - printf("Declaring Subscriber on '%s'...\n", keyexpr); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); z_owned_subscriber_t sub; if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL)) { printf("Unable to declare subscriber.\n"); exit(-1); } - printf("Enter 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } z_undeclare_subscriber(z_move(sub)); @@ -106,7 +94,7 @@ int main(int argc, char **argv) { return 0; } -const char *kind_to_str(z_sample_kind_t kind) { +const char* kind_to_str(z_sample_kind_t kind) { switch (kind) { case Z_SAMPLE_KIND_PUT: return "PUT"; @@ -116,3 +104,41 @@ const char *kind_to_str(z_sample_kind_t kind) { return "UNKNOWN"; } } + +void print_help() { + printf( + "\ + Usage: z_sub_attachement [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression to subscribe to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index 1a94a6b11..bb2d4fc0f 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -13,9 +13,17 @@ // #include +#include "parse_args.h" #include "zenoh.h" -void data_handler(const z_loaned_sample_t *sample, void *arg) { +#define DEFAULT_KEYEXPR "group1/**" + +struct args_t { + char* keyexpr; // -k +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +void data_handler(const z_loaned_sample_t* sample, void* arg) { z_view_string_t key_string; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); switch (z_sample_kind(sample)) { @@ -30,30 +38,15 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { } } -int main(int argc, char **argv) { - char *keyexpr = "group1/**"; - if (argc > 1) { - keyexpr = argv[1]; - } - +int main(int argc, char** argv) { + z_owned_config_t config; + struct args_t args = parse_args(argc, argv, &config); z_view_keyexpr_t ke; - if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { - printf("%s is not a valid key expression\n", keyexpr); + if (z_view_keyexpr_from_str(&ke, args.keyexpr) < 0) { + printf("%s is not a valid key expression\n", args.keyexpr); exit(-1); } - z_owned_config_t config; - z_config_default(&config); - if (argc > 2) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } - } - printf("Opening session...\n"); z_owned_session_t s; if (z_open(&s, z_move(config)) < 0) { @@ -61,7 +54,7 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring liveliness subscriber on '%s'...\n", keyexpr); + printf("Declaring liveliness subscriber on '%s'...\n", args.keyexpr); z_owned_closure_sample_t callback; z_closure(&callback, data_handler, NULL, NULL); z_owned_subscriber_t sub; @@ -70,16 +63,50 @@ int main(int argc, char **argv) { exit(-1); } - printf("Enter 'q' to quit...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } z_undeclare_subscriber(z_move(sub)); z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_sub_liveliness [OPTIONS]\n\n\ + Options:\n\ + -k (optional, string, default='%s'): The key expression matching liveliness tokens to subscribe to\n", + DEFAULT_KEYEXPR); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + const char* keyexpr = parse_opt(argc, argv, "k", true); + if (!keyexpr) { + keyexpr = DEFAULT_KEYEXPR; + } + parse_zenoh_common_args(argc, argv, config); + const char* arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char** pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); + return (struct args_t){.keyexpr = (char*)keyexpr}; +} diff --git a/examples/z_sub_thr.c b/examples/z_sub_thr.c index 15838b6ec..75367f065 100644 --- a/examples/z_sub_thr.c +++ b/examples/z_sub_thr.c @@ -13,10 +13,13 @@ // #include +#include "parse_args.h" #include "zenoh.h" #define N 1000000 +void parse_args(int argc, char **argv, z_owned_config_t *config); + typedef struct { volatile unsigned long count; volatile unsigned long finished_rounds; @@ -61,17 +64,19 @@ void drop_stats(void *context) { int main(int argc, char **argv) { z_owned_config_t config; - z_config_default(&config); - - if (argc > 1) { - if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[1], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } + parse_args(argc, argv, &config); + +#ifdef SHARED_MEMORY + // A probing procedure for shared memory is performed upon session opening. To operate over shared memory + // (and to not fallback on network mode), shared memory needs to be enabled in the configuration. + if (zc_config_insert_json(z_loan_mut(config), Z_CONFIG_SHARED_MEMORY_KEY, "true") < 0) { + printf( + "Couldn't insert value `true` in configuration at `%s`. This is likely because `%s` expects a " + "JSON-serialized value\n", + Z_CONFIG_SHARED_MEMORY_KEY, Z_CONFIG_SHARED_MEMORY_KEY); + exit(-1); } +#endif z_owned_session_t s; @@ -94,9 +99,9 @@ int main(int argc, char **argv) { exit(-1); } - char c = 0; - while (c != 'q') { - c = fgetc(stdin); + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); } z_undeclare_subscriber(z_move(sub)); @@ -104,3 +109,34 @@ int main(int argc, char **argv) { z_close(z_move(s)); return 0; } + +void print_help() { + printf( + "\ + Usage: z_sub_thr [OPTIONS]\n\n\ + Options:\n"); + printf(COMMON_HELP); + printf( + "\ + -h: print help\n"); +} + +void parse_args(int argc, char **argv, z_owned_config_t *config) { + if (parse_opt(argc, argv, "h", false)) { + print_help(); + exit(1); + } + parse_zenoh_common_args(argc, argv, config); + const char *arg = check_unknown_opts(argc, argv); + if (arg) { + printf("Unknown option %s\n", arg); + exit(-1); + } + char **pos_args = parse_pos_args(argc, argv, 1); + if (!pos_args || pos_args[0]) { + printf("Unexpected positional arguments\n"); + free(pos_args); + exit(-1); + } + free(pos_args); +} diff --git a/src/keyexpr.rs b/src/keyexpr.rs index b94f0ba6a..e9aa62ee1 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -78,7 +78,7 @@ unsafe fn keyexpr_create( Ok(name) => match keyexpr_create_inner(name, should_auto_canonize, should_copy) { Ok(v) => Ok(v), Err(e) => { - tracing::error!("Couldn't construct a keyexpr: {}", e); + tracing::error!("Couldn't construct keyexpr: {}", e); Err(result::Z_EINVAL) } }, diff --git a/src/liveliness.rs b/src/liveliness.rs index 9ee54d581..9bf168ab6 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -101,7 +101,7 @@ pub extern "C" fn zc_liveliness_declare_token( result::Z_OK } Err(e) => { - tracing::error!("Failed to undeclare token: {e}"); + tracing::error!("Failed to undeclare liveliness token: {e}"); this.write(None); result::Z_EGENERIC }