diff --git a/examples/parse_args.h b/examples/parse_args.h new file mode 100644 index 000000000..dac3b98db --- /dev/null +++ b/examples/parse_args.h @@ -0,0 +1,213 @@ +// +// 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, + const 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(*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) { + *config = zc_config_from_file(config_file); + } + // -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(*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(*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 5000444bc..9d076033b 100644 --- a/examples/z_delete.c +++ b/examples/z_delete.c @@ -14,23 +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(); - if (argc > 3) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -39,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_delete_options_t options = z_delete_options_default(); - int res = z_delete(z_loan(s), z_keyexpr(keyexpr), &options); + int res = z_delete(z_loan(s), z_keyexpr(args.keyexpr), &options); if (res < 0) { printf("Delete failed...\n"); } @@ -49,3 +45,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 272bef89a..9234f1c2e 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -14,37 +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: - // Do nothing - break; - } - z_keyexpr_t keyexpr = z_keyexpr(expr); +#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 = z_config_default(); + struct args_t args = parse_args(argc, argv, &config); + + z_keyexpr_t keyexpr = z_keyexpr(args.selector); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression", expr); + printf("%s is not a valid key expression", args.selector); exit(-1); } - z_owned_config_t config = z_config_default(); - if (argc > 3) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -53,11 +43,11 @@ int main(int argc, char **argv) { exit(-1); } - printf("Sending Query '%s'...\n", expr); + printf("Sending Query '%s'...\n", args.selector); z_owned_reply_channel_t channel = zc_reply_fifo_new(16); z_get_options_t opts = z_get_options_default(); - if (value != NULL) { - opts.value.payload = z_bytes_from_str(value); + if (args.value != NULL) { + opts.value.payload = z_bytes_from_str(args.value); } z_get(z_loan(s), keyexpr, "", z_move(channel.send), &opts); // here, the send is moved and will be dropped by zenoh when adequate @@ -76,4 +66,47 @@ int main(int argc, char **argv) { z_drop(z_move(channel)); 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 c667cb03a..e6704cdd0 100644 --- a/examples/z_get_liveliness.c +++ b/examples/z_get_liveliness.c @@ -14,29 +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_keyexpr_t keyexpr = z_keyexpr(expr); - if (!z_check(keyexpr)) { - 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(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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_keyexpr_t keyexpr = z_keyexpr(args.keyexpr); + if (!z_check(keyexpr)) { + printf("%s is not a valid key expression\n", args.keyexpr); + exit(-1); } printf("Opening session...\n"); @@ -46,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_reply_channel_t channel = zc_reply_fifo_new(16); zc_liveliness_get(z_loan(s), keyexpr, z_move(channel.send), NULL); z_owned_reply_t reply = z_reply_null(); @@ -65,3 +60,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 d9db2e6d9..728261e90 100644 --- a/examples/z_info.c +++ b/examples/z_info.c @@ -13,26 +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(); - if (argc > 1) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -57,3 +52,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 4191b0496..3b1d27b9a 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -13,31 +13,27 @@ #include #include + +#include "parse_args.h" #include "zenoh.h" +#define DEFAULT_KEYEXPR "group1/zenoh-rs" + +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) { - char *expr = "group1/zenoh-rs"; - if (argc > 1) { - expr = argv[1]; - } + z_owned_config_t config = z_config_default(); + struct args_t args = parse_args(argc, argv, &config); - z_keyexpr_t keyexpr = z_keyexpr(expr); + z_keyexpr_t keyexpr = z_keyexpr(args.keyexpr); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression\n", expr); + printf("%s is not a valid key expression\n", args.keyexpr); exit(-1); } - z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); if (!z_check(s)) { @@ -45,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 = zc_liveliness_declare_token(z_loan(s), keyexpr, NULL); if (!z_check(token)) { 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 c0b02a274..87d7f2f5f 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -14,28 +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]; - } - z_keyexpr_t keyexpr = z_keyexpr(expr); +#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 = z_config_default(); + struct args_t args = parse_args(argc, argv, &config); + + z_keyexpr_t keyexpr = z_keyexpr(args.selector); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression", expr); + printf("%s is not a valid key expression", args.selector); exit(-1); } - z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -44,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.target = Z_QUERY_TARGET_ALL; z_owned_reply_channel_t channel = zc_reply_non_blocking_fifo_new(16); @@ -69,4 +66,42 @@ int main(int argc, char **argv) { z_drop(z_move(channel)); 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 fdc08f71d..c4df86a82 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 @@ -11,7 +12,11 @@ #define PING_TIMEOUT_SEC 1 #define handle_error_en(en, msg) \ - do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) + do { \ + errno = en; \ + perror(msg); \ + exit(EXIT_FAILURE); \ + } while (0) z_condvar_t cond; z_mutex_t mutex; @@ -23,27 +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_PKT_SIZE, DEFAULT_PING_NB, DEFAULT_WARMUP_MS); - return 1; - } + z_owned_config_t config = z_config_default(); + struct args_t args = parse_args(argc, argv, &config); + z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = args.config_path ? zc_config_from_file(args.config_path) : z_config_default(); z_owned_session_t session = z_open(z_move(config)); z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); @@ -90,44 +83,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 8dbb2631e..b9bc73f7a 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_sample_t* sample, void* context) { z_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); #ifdef ZENOH_C // The zc_owned_payload_t API is exclusive to zenoh-c, but allows avoiding some copies. @@ -20,50 +23,51 @@ 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 = args.config_path ? zc_config_from_file(args.config_path) : z_config_default(); + z_owned_config_t config = z_config_default(); + parse_args(argc, argv, &config); + z_owned_session_t session = z_open(z_move(config)); z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); z_owned_publisher_t pub = z_declare_publisher(z_loan(session), pong, NULL); z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)z_move(pub)); z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), ping, z_move(respond), NULL); - while (getchar() != 'q') { + while (1) { + z_sleep_s(1); } z_drop(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); } - return (struct args_t){.help_requested = 0, .config_path = getopt(argc, argv, 'c')}; -} \ No newline at end of file + 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_pub.c b/examples/z_pub.c index ecc95e42d..f372abe8f 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -14,9 +14,20 @@ #include #include +#include "parse_args.h" #include "zenoh.h" -void matching_status_handler(const zcu_matching_status_t *matching_status, void *arg) { +#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); + +void matching_status_handler(const zcu_matching_status_t* matching_status, void* arg) { if (matching_status->matching) { printf("Subscriber matched\n"); } else { @@ -24,25 +35,9 @@ void matching_status_handler(const zcu_matching_status_t *matching_status, void } } -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(); - if (argc > 4) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -51,27 +46,28 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); + z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(args.keyexpr), NULL); if (!z_check(pub)) { printf("Unable to declare Publisher for key expression!\n"); exit(-1); } zcu_owned_matching_listener_t listener; - if (add_matching_listener) { + if (args.add_matching_listener) { zcu_owned_closure_matching_status_t callback = z_closure(matching_status_handler); - listener = zcu_publisher_matching_listener_callback(z_loan(pub), z_move(callback)); + listener = zcu_publisher_matching_listener_callback(z_loan(pub), z_move(callback)); } + 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.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + z_publisher_put(z_loan(pub), (const uint8_t*)buf, strlen(buf), &options); } z_undeclare_publisher(z_move(pub)); @@ -79,3 +75,52 @@ 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 a24133e91..d09fd3d6a 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -14,25 +14,21 @@ #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!" - 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(); - if (argc > 3) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -41,8 +37,8 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); + z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(args.keyexpr), NULL); if (!z_check(pub)) { printf("Unable to declare Publisher for key expression!\n"); exit(-1); @@ -60,6 +56,7 @@ int main(int argc, char **argv) { // add some value z_bytes_map_insert_by_alias(&map, z_bytes_from_str("source"), z_bytes_from_str("C")); + printf("Press CTRL-C to quit...\n"); char buf[256]; char buf_ind[16]; for (int idx = 0; 1; ++idx) { @@ -69,9 +66,9 @@ int main(int argc, char **argv) { sprintf(buf_ind, "%d", idx); z_bytes_map_insert_by_alias(&map, z_bytes_from_str("index"), z_bytes_from_str(buf_ind)); - sprintf(buf, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + sprintf(buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); + z_publisher_put(z_loan(pub), (const uint8_t*)buf, strlen(buf), &options); } z_undeclare_publisher(z_move(pub)); @@ -81,3 +78,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 770bf9d93..0fe50a262 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -14,25 +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(); - if (argc > 3) { - if (zc_config_insert_json(z_loan(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(config), Z_CONFIG_ADD_TIMESTAMP_KEY, "true") < 0) { printf("Unable to configure timestamps!\n"); @@ -47,23 +45,24 @@ int main(int argc, char **argv) { } ze_publication_cache_options_t pub_cache_opts = ze_publication_cache_options_default(); - pub_cache_opts.history = 42; + pub_cache_opts.history = args.history; 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 = - ze_declare_publication_cache(z_loan(s), z_keyexpr(keyexpr), &pub_cache_opts); + ze_declare_publication_cache(z_loan(s), z_keyexpr(args.keyexpr), &pub_cache_opts); if (!z_check(pub_cache)) { 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); - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)buf, strlen(buf), NULL); + sprintf(buf, "[%4d] %s", idx, args.value); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); + z_put(z_loan(s), z_keyexpr(args.keyexpr), (const uint8_t*)buf, strlen(buf), NULL); } z_drop(z_move(pub_cache)); @@ -71,3 +70,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 10970bf62..feddc6fdf 100644 --- a/examples/z_pub_shm.c +++ b/examples/z_pub_shm.c @@ -16,32 +16,28 @@ #include #include +#include "parse_args.h" #include "zenoh.h" #define N 10 +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-pub-shm" +#define DEFAULT_VALUE "Pub from C!" -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-pub-shm"; - 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(); + struct args_t args = parse_args(argc, argv, &config); + // Enable shared memory if (zc_config_insert_json(z_loan(config), "transport/shared_memory/enabled", "true") < 0) { printf("Error enabling Shared Memory"); exit(-1); } - if (argc > 3) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -57,13 +53,14 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring Publisher on '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); + printf("Declaring Publisher on '%s'...\n", args.keyexpr); + z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(args.keyexpr), NULL); if (!z_check(pub)) { printf("Unable to declare Publisher for key expression!\n"); exit(-1); } + printf("Press CTRL-C to quit...\n"); for (int idx = 0; true; ++idx) { zc_owned_shmbuf_t shmbuf = zc_shm_alloc(&manager, 256); if (!z_check(shmbuf)) { @@ -74,13 +71,13 @@ int main(int argc, char **argv) { exit(-1); } } - char *buf = (char *)zc_shmbuf_ptr(&shmbuf); + char* buf = (char*)zc_shmbuf_ptr(&shmbuf); buf[256] = 0; - snprintf(buf, 255, "[%4d] %s", idx, value); + snprintf(buf, 255, "[%4d] %s", idx, args.value); size_t len = strlen(buf); zc_shmbuf_set_length(&shmbuf, len); z_sleep_s(1); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); zc_owned_payload_t payload = zc_shmbuf_into_payload(z_move(shmbuf)); @@ -92,3 +89,46 @@ int main(int argc, char **argv) { z_close(z_move(s)); 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 8686c33eb..0a6562317 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -14,29 +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(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); if (!z_check(s)) { @@ -53,10 +45,50 @@ int main(int argc, char **argv) { exit(-1); } + printf("Press CTRL-C to quit...\n"); while (1) { - z_publisher_put(z_loan(pub), (const uint8_t *)value, len, NULL); + z_publisher_put(z_loan(pub), (const uint8_t*)value, args.size, 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 0af23f7e2..c405d602f 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -12,33 +12,29 @@ // ZettaScale Zenoh Team, // #include + +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind); +#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_sample_t *sample, void *arg) { +void data_handler(const z_sample_t* sample, void* arg) { z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), (int)sample->payload.len, sample->payload.start); z_drop(z_move(keystr)); } -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(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -48,22 +44,19 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback = z_closure(data_handler); - printf("Declaring Subscriber on '%s'...\n", expr); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(expr), z_move(callback), NULL); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); + z_owned_pull_subscriber_t sub = + z_declare_pull_subscriber(z_loan(s), z_keyexpr(args.keyexpr), z_move(callback), NULL); if (!z_check(sub)) { printf("Unable to declare subscriber.\n"); exit(-1); } - printf("Press to pull data...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } else { - z_subscriber_pull(z_loan(sub)); - } + printf("Press CTRL-C to quit...\n"); + for (int idx = 0; 1; ++idx) { + z_sleep_s(1); + printf("[%4d] Pulling...\n", idx); + z_subscriber_pull(z_loan(sub)); } z_undeclare_pull_subscriber(z_move(sub)); @@ -71,7 +64,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"; @@ -80,4 +73,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_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 498d1e958..dd24a9bd5 100644 --- a/examples/z_put.c +++ b/examples/z_put.c @@ -14,29 +14,25 @@ #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(); + struct args_t args = parse_args(argc, argv, &config); z_owned_bytes_map_t attachment = z_bytes_map_new(); z_bytes_map_insert_by_alias(&attachment, z_bytes_from_str("hello"), z_bytes_from_str("there")); - z_owned_config_t config = z_config_default(); - if (argc > 3) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); if (!z_check(s)) { @@ -44,11 +40,11 @@ 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_put_options_t options = z_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); options.attachment = z_bytes_map_as_attachment(&attachment); - int res = z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)value, strlen(value), &options); + int res = z_put(z_loan(s), z_keyexpr(args.keyexpr), (const uint8_t*)args.value, strlen(args.value), &options); if (res < 0) { printf("Put failed...\n"); } @@ -57,3 +53,46 @@ int main(int argc, char **argv) { z_drop(z_move(attachment)); 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 15564be7c..c7e1c1cd8 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -12,33 +12,29 @@ // ZettaScale Zenoh Team, // #include + +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind); +#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); -void data_handler(const z_sample_t *sample, void *arg) { +const char* kind_to_str(z_sample_kind_t kind); + +void data_handler(const z_sample_t* sample, void* arg) { z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), (int)sample->payload.len, sample->payload.start); z_drop(z_move(keystr)); } -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(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -49,21 +45,17 @@ int main(int argc, char **argv) { ze_querying_subscriber_options_t sub_opts = ze_querying_subscriber_options_default(); z_owned_closure_sample_t callback = z_closure(data_handler); - printf("Declaring querying subscriber on '%s'...\n", expr); + printf("Declaring querying subscriber on '%s'...\n", args.keyexpr); ze_owned_querying_subscriber_t sub = - ze_declare_querying_subscriber(z_loan(s), z_keyexpr(expr), z_move(callback), &sub_opts); + ze_declare_querying_subscriber(z_loan(s), z_keyexpr(args.keyexpr), z_move(callback), &sub_opts); if (!z_check(sub)) { 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); } z_drop(z_move(sub)); @@ -72,7 +64,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"; @@ -82,3 +74,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 9d6ec7702..81a19bbd7 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -13,13 +13,22 @@ #include #include + +#include "parse_args.h" #include "zenoh.h" -const char *expr = "demo/example/zenoh-c-queryable"; -const char *value = "Queryable from C!"; -z_keyexpr_t keyexpr; +#define DEFAULT_KEYEXPR "demo/example/zenoh-c-queryable" +#define DEFAULT_VALUE "Queryable from C!" + +char* value = NULL; -void query_handler(const z_query_t *query, void *context) { +struct args_t { + char* keyexpr; // -k + char* value; // -v +}; +struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); + +void query_handler(const z_query_t* query, void* context) { z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); z_bytes_t pred = z_query_parameters(query); z_value_t payload_value = z_query_value(query); @@ -31,24 +40,14 @@ void query_handler(const z_query_t *query, void *context) { } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr((const char *)context), (const unsigned char *)value, strlen(value), &options); + z_query_reply(query, z_keyexpr((const char*)context), (const unsigned char*)value, strlen(value), &options); z_drop(z_move(keystr)); } -int main(int argc, char **argv) { - if (argc > 1) { - expr = argv[1]; - } +int main(int argc, char** argv) { z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -56,30 +55,69 @@ int main(int argc, char **argv) { printf("Unable to open session!\n"); exit(-1); } - keyexpr = z_keyexpr(expr); + z_keyexpr_t keyexpr = z_keyexpr(args.keyexpr); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression", expr); + printf("%s is not a valid key expression", args.keyexpr); exit(-1); } - printf("Declaring Queryable on '%s'...\n", expr); - z_owned_closure_query_t callback = z_closure(query_handler, NULL, expr); + printf("Declaring Queryable on '%s'...\n", args.keyexpr); + z_owned_closure_query_t callback = z_closure(query_handler, NULL, args.keyexpr); z_owned_queryable_t qable = z_declare_queryable(z_loan(s), keyexpr, z_move(callback), NULL); if (!z_check(qable)) { printf("Unable to create queryable.\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_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 672ddd607..d71c0ccbf 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -14,32 +14,28 @@ #include #include #include + +#include "parse_args.h" #include "zenoh.h" -const char *expr = "demo/example/zenoh-c-queryable"; -const char *value = "Queryable from C!"; -z_keyexpr_t keyexpr; +#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); -void query_handler(const z_query_t *query, void *context) { - z_owned_closure_owned_query_t *channel = (z_owned_closure_owned_query_t *)context; +void query_handler(const z_query_t* query, void* context) { + z_owned_closure_owned_query_t* channel = (z_owned_closure_owned_query_t*)context; z_owned_query_t oquery = z_query_clone(query); z_call(*channel, &oquery); } -int main(int argc, char **argv) { - if (argc > 1) { - expr = argv[1]; - } +int main(int argc, char** argv) { z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -47,13 +43,13 @@ int main(int argc, char **argv) { printf("Unable to open session!\n"); exit(-1); } - keyexpr = z_keyexpr(expr); + z_keyexpr_t keyexpr = z_keyexpr(args.keyexpr); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression", expr); + printf("%s is not a valid key expression", args.keyexpr); exit(-1); } - printf("Declaring Queryable on '%s'...\n", expr); + printf("Declaring Queryable on '%s'...\n", args.keyexpr); z_owned_query_channel_t channel = zc_query_fifo_new(16); z_owned_closure_query_t callback = z_closure(query_handler, NULL, &channel.send); z_owned_queryable_t qable = z_declare_queryable(z_loan(s), keyexpr, z_move(callback), NULL); @@ -62,7 +58,7 @@ 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 = z_query_null(); for (z_call(channel.recv, &oquery); z_check(oquery); z_call(channel.recv, &oquery)) { z_query_t query = z_loan(oquery); @@ -77,7 +73,7 @@ int main(int argc, char **argv) { } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(&query, keyexpr, (const unsigned char *)value, strlen(value), &options); + z_query_reply(&query, keyexpr, (const unsigned char*)args.value, strlen(args.value), &options); z_drop(z_move(keystr)); z_drop(z_move(oquery)); } @@ -87,3 +83,46 @@ int main(int argc, char **argv) { z_drop(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 867c1277e..e5f5b30fa 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -12,8 +12,17 @@ // ZettaScale Zenoh Team, // #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_sample_t *sample, void *arg) { @@ -24,21 +33,9 @@ void data_handler(const z_sample_t *sample, void *arg) { } int main(int argc, char **argv) { - char *expr = "demo/example/**"; - if (argc > 1) { - expr = argv[1]; - } - z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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); + // 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. @@ -55,20 +52,16 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback = z_closure(data_handler); - printf("Declaring Subscriber on '%s'...\n", expr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(expr), z_move(callback), NULL); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); + z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(args.keyexpr), z_move(callback), NULL); if (!z_check(sub)) { 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)); @@ -85,4 +78,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 58b0afd81..4b38b9c7b 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -13,16 +13,25 @@ // #include #include + +#include "parse_args.h" #include "zenoh.h" -const char *kind_to_str(z_sample_kind_t kind); +#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); -int8_t attachment_reader(z_bytes_t key, z_bytes_t val, void *ctx) { +int8_t attachment_reader(z_bytes_t key, z_bytes_t val, void* ctx) { printf(" attachment: %.*s: '%.*s'\n", (int)key.len, key.start, (int)val.len, val.start); return 0; } -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_sample_t* sample, void* arg) { z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), (int)sample->payload.len, sample->payload.start); @@ -41,22 +50,9 @@ void data_handler(const z_sample_t *sample, void *arg) { z_drop(z_move(keystr)); } -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(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); @@ -66,20 +62,16 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback = z_closure(data_handler); - printf("Declaring Subscriber on '%s'...\n", expr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(expr), z_move(callback), NULL); + printf("Declaring Subscriber on '%s'...\n", args.keyexpr); + z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(args.keyexpr), z_move(callback), NULL); if (!z_check(sub)) { 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)); @@ -87,7 +79,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"; @@ -97,3 +89,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 36bf64515..9b74fa8e2 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -12,9 +12,18 @@ // ZettaScale Zenoh Team, // #include + +#include "parse_args.h" #include "zenoh.h" -void data_handler(const z_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_sample_t* sample, void* arg) { z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); switch (sample->kind) { case Z_SAMPLE_KIND_PUT: @@ -27,29 +36,16 @@ void data_handler(const z_sample_t *sample, void *arg) { z_drop(z_move(keystr)); } -int main(int argc, char **argv) { - char *expr = "group1/**"; - if (argc > 1) { - expr = argv[1]; - } +int main(int argc, char** argv) { + z_owned_config_t config = z_config_default(); + struct args_t args = parse_args(argc, argv, &config); - z_keyexpr_t keyexpr = z_keyexpr(expr); + z_keyexpr_t keyexpr = z_keyexpr(args.keyexpr); if (!z_check(keyexpr)) { - printf("%s is not a valid key expression\n", expr); + printf("%s is not a valid key expression\n", args.keyexpr); exit(-1); } - z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(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 = z_open(z_move(config)); if (!z_check(s)) { @@ -57,7 +53,7 @@ int main(int argc, char **argv) { exit(-1); } - printf("Declaring liveliness subscriber on '%s'...\n", expr); + printf("Declaring liveliness subscriber on '%s'...\n", args.keyexpr); z_owned_closure_sample_t callback = z_closure(data_handler); z_owned_subscriber_t sub = zc_liveliness_declare_subscriber(z_loan(s), keyexpr, z_move(callback), NULL); if (!z_check(sub)) { @@ -65,16 +61,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 05ee709d3..efec57128 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,15 +64,7 @@ void drop_stats(void *context) { int main(int argc, char **argv) { z_owned_config_t config = z_config_default(); - if (argc > 1) { - if (zc_config_insert_json(z_loan(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); z_owned_session_t s = z_open(z_move(config)); if (!z_check(s)) { @@ -87,9 +82,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)); @@ -97,3 +92,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); +}