]> sigrok.org Git - libsigrok.git/commitdiff
input/csv: rework user accessible options for consistency
authorGerhard Sittig <redacted>
Wed, 16 Oct 2019 18:40:36 +0000 (20:40 +0200)
committerGerhard Sittig <redacted>
Sat, 21 Dec 2019 17:20:04 +0000 (18:20 +0100)
Rename the CSV input module's option keywords. To better reflect their
purpose, and for consistency across the rather complex set of options
and how they interact. Rearrange the list of options (not that the order
matters from the outside, but it's good to have during maintenance).

Update builtin help texts which will show up in applications, as well as
the source code comments which discuss these options in greater detail.
Would be nice to have a "general" help text for input modules which is
not tied to one single option, to provide an overview or use examples.
Arrange the option keys, short and long help texts such that the source
better reflects the applications' screen layout. To better support
future maintenance, again.

Consistently separate multi-work keywords for improved readability.
Prefer underscores over dashes for consistency with common keys in
shared infrastructure in other project sources (device options, MQ
items, etc).

src/input/csv.c

index e3e609917ab5c99cb1e9a77aa5bc648771fa2f1c..4a415181fc50f1c8c7cfaa879b19ea5a4ce89c46 100644 (file)
 /*
  * The CSV input module has the following options:
  *
- * single-column: Specifies the column number which stores the sample data for
- *                single column mode and enables single column mode. Multi
- *                column mode is used if this parameter is omitted.
+ * column_formats: Specifies the data formats and channel counts for the
+ *     input file's text columns. Accepts a comma separated list of tuples
+ *     with: an optional column repeat count ('*' as a wildcard meaning
+ *     "all remaining columns", only applicable to the last field), a format
+ *     specifying character ('x' hexadecimal, 'o' octal, 'b' binary, 'l'
+ *     single-bit logic), and an optional bit count (translating to: logic
+ *     channels communicated in that column). This "column_formats" option
+ *     is most versatile, other forms of specifying the column layout only
+ *     exist for backwards compatibility.
  *
- * numchannels:   Specifies the number of channels to use. In multi column mode
- *                the number of channels are the number of columns and in single
- *                column mode the number of bits (LSB first) beginning at
- *                'first-channel'.
+ * single_column: Specifies the column number which contains the logic data
+ *     for single-column mode. All logic data is taken from several bits
+ *     which all are kept within that one column. Only exists for backwards
+ *     compatibility, see "column_formats" for more flexibility.
  *
- * delimiter:     Specifies the delimiter for columns. Must be at least one
- *                character. Comma is used as default delimiter.
+ * first_column: Specifies the number of the first column with logic data
+ *     in simple multi-column mode. Only exists for backwards compatibility,
+ *     see "column_formats" for more flexibility.
  *
- * format:        Specifies the format of the sample data in single column mode.
- *                Available formats are: 'bin', 'hex' and 'oct'. The binary
- *                format is used by default. This option has no effect in multi
- *                column mode.
+ * logic_channels: Specifies the number of logic channels. Is required in
+ *     simple single-column mode. Is optional in simple multi-column mode
+ *     (and defaults to all remaining columns). Only exists for backwards
+ *     compatibility, see "column_formats" for more flexibility.
  *
- * comment:       Specifies the prefix character(s) for comments. No prefix
- *                characters are used by default which disables removing of
- *                comments.
+ * single_format: Specifies the format of the input text in simple single-
+ *     column mode. Available formats are: 'bin' (default), 'hex' and 'oct'.
+ *     Simple multi-column mode always uses single-bit data per column.
+ *     Only exists for backwards compatibility, see "column_formats" for
+ *     more flexibility.
  *
- * samplerate:    Samplerate which the sample data was captured with. Default
- *                value is 0.
+ * start_line: Specifies at which line to start processing the input file.
+ *     Allows to skip leading lines which neither are header nor data lines.
+ *     By default all of the input file gets processed.
  *
- * first-channel: Column number of the first channel in multi column mode and
- *                position of the bit for the first channel in single column mode.
- *                Default value is 0.
+ * header: Boolean option, controls whether the first processed line is used
+ *     to determine channel names. Off by default. Generic channel names are
+ *     used in the absence of header line content.
  *
- * header:        Determines if the first line should be treated as header
- *                and used for channel names in multi column mode. Empty header
- *                names will be replaced by the channel number. If enabled in
- *                single column mode the first line will be skipped. Usage of
- *                header is disabled by default.
+ * samplerate: Specifies the samplerate of the input data. Defaults to 0.
+ *     User specs take precedence over data which optionally gets derived
+ *     from input data.
  *
- * startline:     Line number to start processing sample data. Must be greater
- *                than 0. The default line number to start processing is 1.
+ * column_separator: Specifies the sequence which separates the text file
+ *     columns. Cannot be empty. Defaults to comma.
+ *
+ * comment_leader: Specifies the sequence which starts comments that run
+ *     up to the end of the current text line. Can be empty to disable
+ *     comment support. Defaults to semicolon.
+ *
+ * Typical examples of using these options:
+ * - ... -I csv:column_formats=*l ...
+ *   All columns are single-bit logic data. Identical to the previous
+ *   multi-column mode (the default when no options were given at all).
+ * - ... -I csv:column_formats=3-,*l ...
+ *   Ignore the first three columns, get single-bit logic data from all
+ *   remaining lines (multi-column mode with first-column above 1).
+ * - ... -I csv:column_formats=3-,4l,x8 ...
+ *   Ignore the first three columns, get single-bit logic data from the
+ *   next four columns, then eight-bit data in hex format from the next
+ *   column. More columns may follow in the input text but won't get
+ *   processed. (Mix of previous multi-column as well as single-column
+ *   modes.)
+ * - ... -I csv:column_formats=4x8,b16,5l ...
+ *   Get eight-bit data in hex format from the first four columns, then
+ *   sixteen-bit data in binary format, then five times single-bit data.
+ * - ... -I csv:single_column=2:single_format=bin:logic_channels=8 ...
+ *   Get eight logic bits in binary format from column 2. (Simple
+ *   single-column mode, corresponds to the "-,b8" format.)
+ * - ... -I csv:first_column=6:logic_channels=4 ...
+ *   Get four single-bit logic channels from columns 6 to 9 respectively.
+ *   (Simple multi-column mode, corresponds to the "5-,4b" format.)
+ * - ... -I csv:start_line=20:header=yes:...
+ *   Skip the first 19 text lines. Use line 20 to derive channel names.
+ *   Data starts at line 21.
  */
 
 /*
@@ -617,18 +655,18 @@ static int init(struct sr_input *in, GHashTable *options)
        in->sdi = g_malloc0(sizeof(*in->sdi));
        in->priv = inc = g_malloc0(sizeof(*inc));
 
-       single_column = g_variant_get_uint32(g_hash_table_lookup(options, "single-column"));
+       single_column = g_variant_get_uint32(g_hash_table_lookup(options, "single_column"));
 
-       logic_channels = g_variant_get_uint32(g_hash_table_lookup(options, "numchannels"));
+       logic_channels = g_variant_get_uint32(g_hash_table_lookup(options, "logic_channels"));
 
        inc->delimiter = g_string_new(g_variant_get_string(
-                       g_hash_table_lookup(options, "delimiter"), NULL));
+                       g_hash_table_lookup(options, "column_separator"), NULL));
        if (!inc->delimiter->len) {
-               sr_err("Column delimiter cannot be empty.");
+               sr_err("Column separator cannot be empty.");
                return SR_ERR_ARG;
        }
 
-       s = g_variant_get_string(g_hash_table_lookup(options, "format"), NULL);
+       s = g_variant_get_string(g_hash_table_lookup(options, "single_format"), NULL);
        if (g_ascii_strncasecmp(s, "bin", 3) == 0) {
                format = FORMAT_BIN;
        } else if (g_ascii_strncasecmp(s, "hex", 3) == 0) {
@@ -636,30 +674,30 @@ static int init(struct sr_input *in, GHashTable *options)
        } else if (g_ascii_strncasecmp(s, "oct", 3) == 0) {
                format = FORMAT_OCT;
        } else {
-               sr_err("Invalid format: '%s'", s);
+               sr_err("Invalid single-column format: '%s'", s);
                return SR_ERR_ARG;
        }
 
        inc->comment = g_string_new(g_variant_get_string(
-                       g_hash_table_lookup(options, "comment"), NULL));
+                       g_hash_table_lookup(options, "comment_leader"), NULL));
        if (g_string_equal(inc->comment, inc->delimiter)) {
                /*
                 * Using the same sequence as comment leader and column
-                * delimiter won't work. The user probably specified ';'
-                * as the column delimiter but did not adjust the comment
+                * separator won't work. The user probably specified ';'
+                * as the column separator but did not adjust the comment
                 * leader. Try DWIM, drop comment strippin support here.
                 */
-               sr_warn("Comment leader and column delimiter conflict, disabling comment support.");
+               sr_warn("Comment leader and column separator conflict, disabling comment support.");
                g_string_truncate(inc->comment, 0);
        }
 
        inc->samplerate = g_variant_get_uint64(g_hash_table_lookup(options, "samplerate"));
 
-       first_column = g_variant_get_uint32(g_hash_table_lookup(options, "first-column"));
+       first_column = g_variant_get_uint32(g_hash_table_lookup(options, "first_column"));
 
        inc->use_header = g_variant_get_boolean(g_hash_table_lookup(options, "header"));
 
-       inc->start_line = g_variant_get_uint32(g_hash_table_lookup(options, "startline"));
+       inc->start_line = g_variant_get_uint32(g_hash_table_lookup(options, "start_line"));
        if (inc->start_line < 1) {
                sr_err("Invalid start line %zu.", inc->start_line);
                return SR_ERR_ARG;
@@ -676,10 +714,10 @@ static int init(struct sr_input *in, GHashTable *options)
         * of input data was seen. To support automatic determination of
         * e.g. channel counts from column counts.
         */
-       s = g_variant_get_string(g_hash_table_lookup(options, "column-formats"), NULL);
+       s = g_variant_get_string(g_hash_table_lookup(options, "column_formats"), NULL);
        if (s && *s) {
                inc->column_formats = g_strdup(s);
-               sr_dbg("User specified column-formats: %s.", s);
+               sr_dbg("User specified column_formats: %s.", s);
        } else if (single_column && logic_channels) {
                format_char = col_format_char[format];
                if (single_column == 1) {
@@ -690,7 +728,7 @@ static int init(struct sr_input *in, GHashTable *options)
                                single_column - 1,
                                format_char, logic_channels);
                }
-               sr_dbg("Backwards compat single-column, col %zu, fmt %s, bits %zu -> %s.",
+               sr_dbg("Backwards compat single_column, col %zu, fmt %s, bits %zu -> %s.",
                        single_column, col_format_text[format], logic_channels,
                        inc->column_formats);
        } else if (!single_column) {
@@ -705,7 +743,7 @@ static int init(struct sr_input *in, GHashTable *options)
                        first_column, logic_channels,
                        inc->column_formats);
        } else {
-               sr_warn("Unknown or unsupported format spec, assuming trivial multi-column.");
+               sr_warn("Unknown or unsupported columns layout spec, assuming simple multi-column mode.");
                inc->column_formats = g_strdup("*l");
        }
 
@@ -1171,28 +1209,68 @@ static int reset(struct sr_input *in)
 enum option_index {
        OPT_COL_FMTS,
        OPT_SINGLE_COL,
+       OPT_FIRST_COL,
        OPT_NUM_LOGIC,
-       OPT_DELIM,
        OPT_FORMAT,
-       OPT_COMMENT,
-       OPT_RATE,
-       OPT_FIRST_COL,
-       OPT_HEADER,
        OPT_START,
+       OPT_HEADER,
+       OPT_RATE,
+       OPT_DELIM,
+       OPT_COMMENT,
        OPT_MAX,
 };
 
 static struct sr_option options[] = {
-       [OPT_COL_FMTS] = { "column-formats", "Column format specs", "Specifies text columns data types: comma separated list of [<cols>]<fmt>[<bits>]", NULL, NULL },
-       [OPT_SINGLE_COL] = { "single-column", "Single column", "Enable single-column mode, using the specified column (>= 1); 0: multi-col. mode", NULL, NULL },
-       [OPT_NUM_LOGIC] = { "numchannels", "Number of logic channels", "The number of (logic) channels (single-col. mode: number of bits beginning at 'first channel', LSB-first)", NULL, NULL },
-       [OPT_DELIM] = { "delimiter", "Column delimiter", "The column delimiter (>= 1 characters)", NULL, NULL },
-       [OPT_FORMAT] = { "format", "Data format (single-col. mode)", "The numeric format of the data (single-col. mode): bin, hex, oct", NULL, NULL },
-       [OPT_COMMENT] = { "comment", "Comment character(s)", "The comment prefix character(s)", NULL, NULL },
-       [OPT_RATE] = { "samplerate", "Samplerate (Hz)", "The sample rate (used during capture) in Hz", NULL, NULL },
-       [OPT_FIRST_COL] = { "first-column", "First column", "The column number of the first channel (multi-col. mode)", NULL, NULL },
-       [OPT_HEADER] = { "header", "Interpret first line as header (multi-col. mode)", "Treat the first line as header with channel names (multi-col. mode)", NULL, NULL },
-       [OPT_START] = { "startline", "Start line", "The line number at which to start processing samples (>= 1)", NULL, NULL },
+       [OPT_COL_FMTS] = {
+               "column_formats", "Column format specs",
+               "Specifies text columns data types: comma separated list of [<cols>]<fmt>[<bits>], with -/x/o/b/l format specifiers.",
+               NULL, NULL,
+       },
+       [OPT_SINGLE_COL] = {
+               "single_column", "Single column",
+               "Enable single-column mode, exclusively use text from the specified column (number starting at 1).",
+               NULL, NULL,
+       },
+       [OPT_FIRST_COL] = {
+               "first_column", "First column",
+               "Number of the first column with logic data in simple multi-column mode (number starting at 1, default 1).",
+               NULL, NULL,
+       },
+       [OPT_NUM_LOGIC] = {
+               "logic_channels", "Number of logic channels",
+               "Logic channel count, required in simple single-column mode, defaults to \"all remaining columns\" in simple multi-column mode. Obsoleted by 'column_formats'.",
+               NULL, NULL,
+       },
+       [OPT_FORMAT] = {
+               "single_format", "Data format for simple single-column mode.",
+               "The number format of single-column mode input data: bin, hex, oct.",
+               NULL, NULL,
+       },
+       [OPT_START] = {
+               "start_line", "Start line",
+               "The line number at which to start processing input text (default: 1).",
+               NULL, NULL,
+       },
+       [OPT_HEADER] = {
+               "header", "Get channel names from first line.",
+               "Use the first processed line's column captions (when available) as channel names.",
+               NULL, NULL,
+       },
+       [OPT_RATE] = {
+               "samplerate", "Samplerate (Hz)",
+               "The input data's sample rate in Hz.",
+               NULL, NULL,
+       },
+       [OPT_DELIM] = {
+               "column_separator", "Column separator",
+               "The sequence which separates text columns. Non-empty text, comma by default.",
+               NULL, NULL,
+       },
+       [OPT_COMMENT] = {
+               "comment_leader", "Comment leader character",
+               "The text which starts comments at the end of text lines.",
+               NULL, NULL,
+       },
        [OPT_MAX] = ALL_ZERO,
 };
 
@@ -1203,19 +1281,19 @@ static const struct sr_option *get_options(void)
        if (!options[0].def) {
                options[OPT_COL_FMTS].def = g_variant_ref_sink(g_variant_new_string(""));
                options[OPT_SINGLE_COL].def = g_variant_ref_sink(g_variant_new_uint32(0));
+               options[OPT_FIRST_COL].def = g_variant_ref_sink(g_variant_new_uint32(1));
                options[OPT_NUM_LOGIC].def = g_variant_ref_sink(g_variant_new_uint32(0));
-               options[OPT_DELIM].def = g_variant_ref_sink(g_variant_new_string(","));
                options[OPT_FORMAT].def = g_variant_ref_sink(g_variant_new_string("bin"));
                l = NULL;
                l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("bin")));
                l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("hex")));
                l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("oct")));
                options[OPT_FORMAT].values = l;
-               options[OPT_COMMENT].def = g_variant_ref_sink(g_variant_new_string(";"));
-               options[OPT_RATE].def = g_variant_ref_sink(g_variant_new_uint64(0));
-               options[OPT_FIRST_COL].def = g_variant_ref_sink(g_variant_new_uint32(1));
-               options[OPT_HEADER].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
                options[OPT_START].def = g_variant_ref_sink(g_variant_new_uint32(1));
+               options[OPT_HEADER].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
+               options[OPT_RATE].def = g_variant_ref_sink(g_variant_new_uint64(0));
+               options[OPT_DELIM].def = g_variant_ref_sink(g_variant_new_string(","));
+               options[OPT_COMMENT].def = g_variant_ref_sink(g_variant_new_string(";"));
        }
 
        return options;