From: Simon Marchi Date: Tue, 23 Apr 2019 14:14:08 +0000 (-0400) Subject: cli: Support arrays in parameters X-Git-Tag: v2.0.0-pre5~65 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=7b6a21439c0ec822f2fce4fe61b7f1d1f2059273 cli: Support arrays in parameters This patch adds support for arrays in the parameters one can pass to components on the Babeltrace command line. For example: --params="value=[1,2,\"Hello\"]" When we are starting to parse a value and the token is a '[', we start parsing it as an array. We accept comma-separated values until we reach the matching ']'. The code should be pretty self-explanatory/commented. Signed-off-by: Simon Marchi --- diff --git a/cli/babeltrace-cfg-cli-args.c b/cli/babeltrace-cfg-cli-args.c index b71b70f5..927a85d9 100644 --- a/cli/babeltrace-cfg-cli-args.c +++ b/cli/babeltrace-cfg-cli-args.c @@ -220,6 +220,77 @@ bt_value *ini_parse_neg_number(struct ini_parsing_state *state) return value; } +static bt_value *ini_parse_value(struct ini_parsing_state *state); + +/* + * Parse the current and following tokens as an array. Arrays are formatted as + * an opening `[`, a list of comma-separated values and a closing `]`. For + * convenience we support an optional trailing comma, after the last value. + * + * The current token of the parser must be the opening square bracket of the + * array. + */ +static +bt_value *ini_parse_array(struct ini_parsing_state *state) +{ + /* The [ character must have already been ingested. */ + BT_ASSERT(g_scanner_cur_token(state->scanner) == G_TOKEN_CHAR); + BT_ASSERT(g_scanner_cur_value(state->scanner).v_char == '['); + + bt_value *array_value; + GTokenType token_type; + + array_value = bt_value_array_create (); + token_type = g_scanner_get_next_token(state->scanner); + + /* While the current token is not a ]... */ + while (!(token_type == G_TOKEN_CHAR && g_scanner_cur_value(state->scanner).v_char == ']')) { + /* Parse the item... */ + bt_value *item_value; + bt_value_status status; + + item_value = ini_parse_value(state); + if (!item_value) { + goto error; + } + + /* ... and add it to the result array. */ + status = bt_value_array_append_element(array_value, item_value); + BT_VALUE_PUT_REF_AND_RESET(item_value); + + if (status != BT_VALUE_STATUS_OK) { + goto error; + } + + /* + * Ingest the token following the value, it should be either a + * comma or closing square brace. + */ + token_type = g_scanner_get_next_token(state->scanner); + + if (token_type == G_TOKEN_CHAR && g_scanner_cur_value(state->scanner).v_char == ',') { + /* + * Ingest the token following the comma. If it happens + * to be a closing square bracket, we'll exit the loop + * and we are done (we allow trailing commas). + * Otherwise, we are ready for the next ini_parse_value call. + */ + token_type = g_scanner_get_next_token(state->scanner); + } else if (token_type != G_TOKEN_CHAR || g_scanner_cur_value(state->scanner).v_char != ']') { + ini_append_error_expecting(state, state->scanner, ", or ]"); + goto error; + } + } + + goto end; + +error: + BT_VALUE_PUT_REF_AND_RESET(array_value); + +end: + return array_value; +} + /* * Parse the current token (and the following ones if needed) as a value, return * it as a bt_value. @@ -235,6 +306,9 @@ bt_value *ini_parse_value(struct ini_parsing_state *state) if (state->scanner->value.v_char == '-') { /* Negative number */ value = ini_parse_neg_number(state); + } else if (state->scanner->value.v_char == '[') { + /* Array */ + value = ini_parse_array(state); } else { ini_append_error_expecting(state, state->scanner, "value"); } @@ -1769,6 +1843,8 @@ void print_expected_params_format(FILE *fp) fprintf(fp, "* Unquoted string with no special characters, and not matching any of\n"); fprintf(fp, " the null and boolean value symbols above.\n"); fprintf(fp, "* Double-quoted string (accepts escape characters).\n"); + fprintf(fp, "* Array, formatted as an opening `[`, a list of comma-separated values\n"); + fprintf(fp, " (as described by the current list) and a closing `]`.\n"); fprintf(fp, "\n"); fprintf(fp, "You can put whitespaces allowed around individual `=` and `,` symbols.\n"); fprintf(fp, "\n"); @@ -1776,7 +1852,8 @@ void print_expected_params_format(FILE *fp) fprintf(fp, "\n"); fprintf(fp, " many=null, fresh=yes, condition=false, squirrel=-782329,\n"); fprintf(fp, " observe=3.14, simple=beef, needs-quotes=\"some string\",\n"); - fprintf(fp, " escape.chars-are:allowed=\"this is a \\\" double quote\"\n"); + fprintf(fp, " escape.chars-are:allowed=\"this is a \\\" double quote\",\n"); + fprintf(fp, " things=[1, \"2\", 3]\n"); fprintf(fp, "\n"); fprintf(fp, "IMPORTANT: Make sure to single-quote the whole argument when you run\n"); fprintf(fp, "babeltrace from a shell.\n"); diff --git a/doc/man/common-cmd-params-format.txt b/doc/man/common-cmd-params-format.txt index c3ee8d4f..efceab47 100644 --- a/doc/man/common-cmd-params-format.txt +++ b/doc/man/common-cmd-params-format.txt @@ -31,6 +31,9 @@ list of `NAME=VALUE` assignments: * Double-quoted string (accepts escape characters). +* Array, formatted as an opening `[`, a list of comma-separated values + (as described by the current list) and a closing `]`. + You may put whitespaces around the individual `=` (assignment) and `,` (separator) characters. -- @@ -41,7 +44,8 @@ Example: babeltrace ... --params='many=null, fresh=yes, condition=false, squirrel=-782329, observe=3.14, simple=beef, needs-quotes="some string", - escape.chars-are:allowed="a \" quote"' + escape.chars-are:allowed="a \" quote", + things=[1, "2", 3]' ---- IMPORTANT: Like in the example above, make sure to single-quote the