]> sigrok.org Git - libsigrok.git/blob - src/input/csv.c
2f6c20d32382dfc131564615aa285e827c401441
[libsigrok.git] / src / input / csv.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 Marc Schink <sigrok-dev@marcschink.de>
5  * Copyright (C) 2019 Gerhard Sittig <gerhard.sittig@gmx.net>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "config.h"
22
23 #include <glib.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <libsigrok/libsigrok.h>
28 #include "libsigrok-internal.h"
29 #include "scpi.h"       /* String un-quote for channel name from header line. */
30
31 #define LOG_PREFIX "input/csv"
32
33 #define CHUNK_SIZE      (4 * 1024 * 1024)
34
35 /*
36  * The CSV input module has the following options:
37  *
38  * single-column: Specifies the column number which stores the sample data for
39  *                single column mode and enables single column mode. Multi
40  *                column mode is used if this parameter is omitted.
41  *
42  * numchannels:   Specifies the number of channels to use. In multi column mode
43  *                the number of channels are the number of columns and in single
44  *                column mode the number of bits (LSB first) beginning at
45  *                'first-channel'.
46  *
47  * delimiter:     Specifies the delimiter for columns. Must be at least one
48  *                character. Comma is used as default delimiter.
49  *
50  * format:        Specifies the format of the sample data in single column mode.
51  *                Available formats are: 'bin', 'hex' and 'oct'. The binary
52  *                format is used by default. This option has no effect in multi
53  *                column mode.
54  *
55  * comment:       Specifies the prefix character(s) for comments. No prefix
56  *                characters are used by default which disables removing of
57  *                comments.
58  *
59  * samplerate:    Samplerate which the sample data was captured with. Default
60  *                value is 0.
61  *
62  * first-channel: Column number of the first channel in multi column mode and
63  *                position of the bit for the first channel in single column mode.
64  *                Default value is 0.
65  *
66  * header:        Determines if the first line should be treated as header
67  *                and used for channel names in multi column mode. Empty header
68  *                names will be replaced by the channel number. If enabled in
69  *                single column mode the first line will be skipped. Usage of
70  *                header is disabled by default.
71  *
72  * startline:     Line number to start processing sample data. Must be greater
73  *                than 0. The default line number to start processing is 1.
74  */
75
76 /*
77  * TODO
78  *
79  * - Determine how the text line handling can get improved, regarding
80  *   all of robustness and flexibility and correctness.
81  *   - The current implementation splits on "any run of CR and LF". Which
82  *     translates to: Line numbers are wrong in the presence of empty
83  *     lines in the input stream. See below for an (expensive) fix.
84  *   - Dropping support for CR style end-of-line markers could improve
85  *     the situation a lot. Code could search for and split on LF, and
86  *     trim optional trailing CR. This would result in proper support
87  *     for CRLF (Windows) as well as LF (Unix), and allow for correct
88  *     line number counts.
89  *   - When support for CR-only line termination cannot get dropped,
90  *     then the current implementation is inappropriate. Currently the
91  *     input stream is scanned for the first occurance of either of the
92  *     supported termination styles (which is good). For the remaining
93  *     session a consistent encoding of the text lines is assumed (which
94  *     is acceptable).
95  *   - When line numbers need to be correct and reliable, _and_ the full
96  *     set of previously supported line termination sequences are required,
97  *     and potentially more are to get added for improved compatibility
98  *     with more platforms or generators, then the current approach of
99  *     splitting on runs of termination characters needs to get replaced,
100  *     by the more expensive approach to scan for and count the initially
101  *     determined termination sequence.
102  *
103  * - Add support for analog input data? (optional)
104  *   - Needs a syntax first for user specs which channels (columns) are
105  *     logic and which are analog. May need heuristics(?) to guess from
106  *     input data in the absence of user provided specs.
107  */
108
109 /* Single column formats. */
110 enum single_col_format {
111         FORMAT_NONE,    /* Ignore this column. */
112         FORMAT_BIN,     /* Bin digits for a set of bits (or just one bit). */
113         FORMAT_HEX,     /* Hex digits for a set of bits. */
114         FORMAT_OCT,     /* Oct digits for a set of bits. */
115 };
116
117 static const char *col_format_text[] = {
118         [FORMAT_NONE] = "unknown",
119         [FORMAT_BIN] = "binary",
120         [FORMAT_HEX] = "hexadecimal",
121         [FORMAT_OCT] = "octal",
122 };
123
124 struct column_details {
125         size_t col_nr;
126         enum single_col_format text_format;
127         size_t channel_offset;
128         size_t channel_count;
129 };
130
131 struct context {
132         gboolean started;
133
134         /* Current selected samplerate. */
135         uint64_t samplerate;
136         gboolean samplerate_sent;
137
138         /* Number of logic channels. */
139         size_t logic_channels;
140
141         /* Column delimiter (actually separator), comment leader, EOL sequence. */
142         GString *delimiter;
143         GString *comment;
144         char *termination;
145
146         /*
147          * Determines if sample data is stored in multiple columns,
148          * which column to start at, and how many columns to expect.
149          */
150         gboolean multi_column_mode;
151         size_t first_column;
152         size_t column_want_count;
153         /* Parameters how to process the columns. */
154         struct column_details *column_details;
155
156         /* Line number to start processing. */
157         size_t start_line;
158
159         /*
160          * Determines if the first line should be treated as header and used for
161          * channel names in multi column mode.
162          */
163         gboolean use_header;
164         gboolean header_seen;
165
166         size_t sample_unit_size;        /**!< Byte count for a single sample. */
167         uint8_t *sample_buffer;         /**!< Buffer for a single sample. */
168
169         uint8_t *datafeed_buffer;       /**!< Queue for datafeed submission. */
170         size_t datafeed_buf_size;
171         size_t datafeed_buf_fill;
172
173         /* Current line number. */
174         size_t line_number;
175
176         /* List of previously created sigrok channels. */
177         GSList *prev_sr_channels;
178 };
179
180 /*
181  * Primitive operations to handle sample sets:
182  * - Keep a buffer for datafeed submission, capable of holding many
183  *   samples (reduces call overhead, improves throughput).
184  * - Have a "current sample set" pointer reference one position in that
185  *   large samples buffer.
186  * - Clear the current sample set before text line inspection, then set
187  *   the bits which are found active in the current line of text input.
188  *   Phrase the API such that call sites can be kept simple. Advance to
189  *   the next sample set between lines, flush the larger buffer as needed
190  *   (when it is full, or upon EOF).
191  */
192
193 static void clear_logic_samples(struct context *inc)
194 {
195         inc->sample_buffer = &inc->datafeed_buffer[inc->datafeed_buf_fill];
196         memset(inc->sample_buffer, 0, inc->sample_unit_size);
197 }
198
199 static void set_logic_level(struct context *inc, size_t ch_idx, int on)
200 {
201         size_t byte_idx, bit_idx;
202         uint8_t bit_mask;
203
204         if (ch_idx >= inc->logic_channels)
205                 return;
206         if (!on)
207                 return;
208
209         byte_idx = ch_idx / 8;
210         bit_idx = ch_idx % 8;
211         bit_mask = 1 << bit_idx;
212         inc->sample_buffer[byte_idx] |= bit_mask;
213 }
214
215 static int flush_logic_samples(const struct sr_input *in)
216 {
217         struct context *inc;
218         struct sr_datafeed_packet packet;
219         struct sr_datafeed_meta meta;
220         struct sr_config *src;
221         uint64_t samplerate;
222         struct sr_datafeed_logic logic;
223         int rc;
224
225         inc = in->priv;
226         if (!inc->datafeed_buf_fill)
227                 return SR_OK;
228
229         if (inc->samplerate && !inc->samplerate_sent) {
230                 packet.type = SR_DF_META;
231                 packet.payload = &meta;
232                 samplerate = inc->samplerate;
233                 src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(samplerate));
234                 meta.config = g_slist_append(NULL, src);
235                 sr_session_send(in->sdi, &packet);
236                 g_slist_free(meta.config);
237                 sr_config_free(src);
238                 inc->samplerate_sent = TRUE;
239         }
240
241         memset(&packet, 0, sizeof(packet));
242         memset(&logic, 0, sizeof(logic));
243         packet.type = SR_DF_LOGIC;
244         packet.payload = &logic;
245         logic.unitsize = inc->sample_unit_size;
246         logic.length = inc->datafeed_buf_fill;
247         logic.data = inc->datafeed_buffer;
248
249         rc = sr_session_send(in->sdi, &packet);
250         if (rc != SR_OK)
251                 return rc;
252
253         inc->datafeed_buf_fill = 0;
254         return SR_OK;
255 }
256
257 static int queue_logic_samples(const struct sr_input *in)
258 {
259         struct context *inc;
260         int rc;
261
262         inc = in->priv;
263         if (!inc->logic_channels)
264                 return SR_OK;
265
266         inc->datafeed_buf_fill += inc->sample_unit_size;
267         if (inc->datafeed_buf_fill == inc->datafeed_buf_size) {
268                 rc = flush_logic_samples(in);
269                 if (rc != SR_OK)
270                         return rc;
271         }
272         return SR_OK;
273 }
274
275 /* Helpers for "column processing". */
276
277 static int split_column_format(const char *spec,
278         size_t *column_count, enum single_col_format *format, size_t *bit_count)
279 {
280         size_t count;
281         char *endp, format_char;
282         enum single_col_format format_code;
283
284         if (!spec || !*spec)
285                 return SR_ERR_ARG;
286
287         /* Get the (optional, decimal, default 1) column count. */
288         endp = NULL;
289         count = strtoul(spec, &endp, 10);
290         if (!endp)
291                 return SR_ERR_ARG;
292         if (endp == spec)
293                 count = 1;
294         if (column_count)
295                 *column_count = count;
296         spec = endp;
297
298         /* Get the (mandatory, single letter) type spec (-/xob/l). */
299         format_char = *spec++;
300         switch (format_char) {
301         case '-':       /* Might conflict with number-parsing. */
302         case '/':
303                 format_char = '-';
304                 format_code = FORMAT_NONE;
305                 break;
306         case 'x':
307                 format_code = FORMAT_HEX;
308                 break;
309         case 'o':
310                 format_code = FORMAT_OCT;
311                 break;
312         case 'b':
313         case 'l':
314                 format_code = FORMAT_BIN;
315                 break;
316         default:        /* includes NUL */
317                 return SR_ERR_ARG;
318         }
319         if (format)
320                 *format = format_code;
321
322         /* Get the (optional, decimal, default 1) bit count. */
323         endp = NULL;
324         count = strtoul(spec, &endp, 10);
325         if (!endp)
326                 return SR_ERR_ARG;
327         if (endp == spec)
328                 count = 1;
329         if (format_char == '-')
330                 count = 0;
331         if (format_char == 'l')
332                 count = 1;
333         if (bit_count)
334                 *bit_count = count;
335         spec = endp;
336
337         /* Input spec must have been exhausted. */
338         if (*spec)
339                 return SR_ERR_ARG;
340
341         return SR_OK;
342 }
343
344 static int make_column_details_from_format(struct context *inc,
345         const char *column_format)
346 {
347         char **formats, *format;
348         size_t format_count, column_count, bit_count;
349         size_t format_idx, c, b, column_idx, channel_idx;
350         enum single_col_format f;
351         struct column_details *detail;
352         int ret;
353
354         /*
355          * Default to "all single-bit logic in each column" (which is
356          * the former multi-column mode).
357          */
358         if (!column_format || !*column_format) {
359                 sr_dbg("Missing columns format, assuming multi-column mode.");
360                 column_format = "0l";
361         }
362
363         /* Split the input spec, count involved columns and bits. */
364         formats = g_strsplit(column_format, ",", 0);
365         if (!formats) {
366                 sr_err("Cannot parse columns format %s (comma split).", column_format);
367                 return SR_ERR_ARG;
368         }
369         format_count = g_strv_length(formats);
370         if (!format_count) {
371                 sr_err("Cannot parse columns format %s (field count).", column_format);
372                 g_strfreev(formats);
373                 return SR_ERR_ARG;
374         }
375         column_count = bit_count = 0;
376         for (format_idx = 0; format_idx < format_count; format_idx++) {
377                 format = formats[format_idx];
378                 ret = split_column_format(format, &c, &f, &b);
379                 sr_dbg("fmt %s -> %zu cols, %s fmt, %zu bits, rc %d", format, c, col_format_text[f], b, ret);
380                 if (ret != SR_OK) {
381                         sr_err("Cannot parse columns format %s (field split, %s).", column_format, format);
382                         g_strfreev(formats);
383                         return SR_ERR_ARG;
384                 }
385                 column_count += c;
386                 bit_count += c * b;
387         }
388         sr_dbg("Column format %s -> %zu columns, %zu logic channels.",
389                 column_format, column_count, bit_count);
390
391         /* Allocate and fill in "column processing" details. */
392         inc->column_want_count = column_count;
393         inc->column_details = g_malloc0_n(column_count, sizeof(inc->column_details[0]));
394         column_idx = channel_idx = 0;
395         for (format_idx = 0; format_idx < format_count; format_idx++) {
396                 format = formats[format_idx];
397                 (void)split_column_format(format, &c, &f, &b);
398                 while (c-- > 0) {
399                         detail = &inc->column_details[column_idx++];
400                         detail->col_nr = column_idx;
401                         detail->text_format = f;
402                         if (detail->text_format) {
403                                 detail->channel_offset = channel_idx;
404                                 detail->channel_count = b;
405                                 channel_idx += b;
406                         }
407                         sr_dbg("detail -> col %zu, fmt %s, ch off/cnt %zu/%zu",
408                                 detail->col_nr, col_format_text[detail->text_format],
409                                 detail->channel_offset, detail->channel_count);
410                 }
411         }
412         inc->logic_channels = channel_idx;
413         g_strfreev(formats);
414
415         return SR_OK;
416 }
417
418 static int make_column_details_single(struct context *inc,
419         size_t col_nr, size_t bit_count, enum single_col_format format)
420 {
421         struct column_details *details;
422
423         /*
424          * Need at least as many columns to also include the one with
425          * the single-column input data.
426          */
427         inc->column_want_count = col_nr;
428
429         /*
430          * Allocate the columns' processing details. Columns are counted
431          * from 1 (user's perspective), array items from 0 (programmer's
432          * perspective).
433          */
434         inc->column_details = g_malloc0_n(col_nr, sizeof(inc->column_details[0]));
435         details = &inc->column_details[col_nr - 1];
436         details->col_nr = col_nr;
437
438         /*
439          * In single-column mode this single column will hold all bits
440          * of all logic channels, in the user specified number format.
441          */
442         details->text_format = format;
443         details->channel_offset = 0;
444         details->channel_count = bit_count;
445
446         return SR_OK;
447 }
448
449 static int make_column_details_multi(struct context *inc,
450         size_t first_col, size_t last_col)
451 {
452         struct column_details *details;
453         size_t col_nr;
454
455         /*
456          * Need at least as many columns to also include the one with
457          * the last channel's data.
458          */
459         inc->column_want_count = last_col;
460
461         /*
462          * Allocate the columns' processing details. Columns are counted
463          * from 1, array items from 0.
464          * In multi-column mode each column will hold a single bit for
465          * the respective channel.
466          */
467         inc->column_details = g_malloc0_n(last_col, sizeof(inc->column_details[0]));
468         for (col_nr = first_col; col_nr <= last_col; col_nr++) {
469                 details = &inc->column_details[col_nr - 1];
470                 details->col_nr = col_nr;
471                 details->text_format = FORMAT_BIN;
472                 details->channel_offset = col_nr - first_col;
473                 details->channel_count = 1;
474         }
475
476
477         return SR_OK;
478 }
479
480 static const struct column_details *lookup_column_details(struct context *inc, size_t nr)
481 {
482         if (!inc || !inc->column_details)
483                 return NULL;
484         if (!nr || nr > inc->column_want_count)
485                 return NULL;
486         return &inc->column_details[nr - 1];
487 }
488
489 /*
490  * Primitive operations for text input: Strip comments off text lines.
491  * Split text lines into columns. Process input text for individual
492  * columns.
493  */
494
495 static void strip_comment(char *buf, const GString *prefix)
496 {
497         char *ptr;
498
499         if (!prefix->len)
500                 return;
501
502         if ((ptr = strstr(buf, prefix->str))) {
503                 *ptr = '\0';
504                 g_strstrip(buf);
505         }
506 }
507
508 /**
509  * @brief Splits a text line into a set of columns.
510  *
511  * @param[in] buf       The input text line to split.
512  * @param[in] inc       The input module's context.
513  *
514  * @returns An array of strings, representing the columns' text.
515  *
516  * This routine splits a text line on previously determined separators.
517  */
518 static char **split_line(char *buf, struct context *inc)
519 {
520         return g_strsplit(buf, inc->delimiter->str, 0);
521 }
522
523 /**
524  * @brief Parse a multi-bit field into several logic channels.
525  *
526  * @param[in] column    The input text, a run of bin/hex/oct digits.
527  * @param[in] inc       The input module's context.
528  * @param[in] details   The column processing details.
529  *
530  * @retval SR_OK        Success.
531  * @retval SR_ERR       Invalid input data (empty, or format error).
532  *
533  * This routine modifies the logic levels in the current sample set,
534  * based on the text input and a user provided format spec.
535  */
536 static int parse_logic(const char *column, struct context *inc,
537         const struct column_details *details)
538 {
539         size_t length, ch_rem, ch_idx, ch_inc;
540         const char *rdptr;
541         char c;
542         gboolean valid;
543         const char *type_text;
544         uint8_t bits;
545
546         /*
547          * Prepare to read the digits from the text end towards the start.
548          * A digit corresponds to a variable number of channels (depending
549          * on the value's radix). Prepare the mapping of text digits to
550          * (a number of) logic channels.
551          */
552         length = strlen(column);
553         if (!length) {
554                 sr_err("Column %zu in line %zu is empty.", details->col_nr,
555                         inc->line_number);
556                 return SR_ERR;
557         }
558         rdptr = &column[length];
559         ch_idx = details->channel_offset;
560         ch_rem = details->channel_count;
561
562         /*
563          * Get another digit and derive up to four logic channels' state from
564          * it. Make sure to not process more bits than the column has channels
565          * associated with it.
566          */
567         while (rdptr > column && ch_rem) {
568                 /* Check for valid digits according to the input radix. */
569                 c = *(--rdptr);
570                 switch (details->text_format) {
571                 case FORMAT_BIN:
572                         valid = g_ascii_isxdigit(c) && c < '2';
573                         ch_inc = 1;
574                         break;
575                 case FORMAT_OCT:
576                         valid = g_ascii_isxdigit(c) && c < '8';
577                         ch_inc = 3;
578                         break;
579                 case FORMAT_HEX:
580                         valid = g_ascii_isxdigit(c);
581                         ch_inc = 4;
582                         break;
583                 default:
584                         valid = FALSE;
585                         break;
586                 }
587                 if (!valid) {
588                         type_text = col_format_text[details->text_format];
589                         sr_err("Invalid text '%s' in %s type column %zu in line %zu.",
590                                 column, type_text, details->col_nr, inc->line_number);
591                         return SR_ERR;
592                 }
593                 /* Use the digit's bits for logic channels' data. */
594                 bits = g_ascii_xdigit_value(c);
595                 switch (details->text_format) {
596                 case FORMAT_HEX:
597                         if (ch_rem >= 4) {
598                                 ch_rem--;
599                                 set_logic_level(inc, ch_idx + 3, bits & (1 << 3));
600                         }
601                         /* FALLTHROUGH */
602                 case FORMAT_OCT:
603                         if (ch_rem >= 3) {
604                                 ch_rem--;
605                                 set_logic_level(inc, ch_idx + 2, bits & (1 << 2));
606                         }
607                         if (ch_rem >= 2) {
608                                 ch_rem--;
609                                 set_logic_level(inc, ch_idx + 1, bits & (1 << 1));
610                         }
611                         /* FALLTHROUGH */
612                 case FORMAT_BIN:
613                         ch_rem--;
614                         set_logic_level(inc, ch_idx + 0, bits & (1 << 0));
615                         break;
616                 case FORMAT_NONE:
617                         /* ShouldNotHappen(TM), but silences compiler warning. */
618                         return SR_ERR;
619                 }
620                 ch_idx += ch_inc;
621         }
622         /*
623          * TODO Determine whether the availability of extra input data
624          * for unhandled logic channels is worth warning here. In this
625          * implementation users are in control, and can have the more
626          * significant bits ignored (which can be considered a feature
627          * and not really a limitation).
628          */
629
630         return SR_OK;
631 }
632
633 /**
634  * @brief Parse routine which ignores the input text.
635  *
636  * This routine exists to unify dispatch code paths, mapping input file
637  * columns' data types to their respective parse routines.
638  */
639 static int parse_ignore(const char *column, struct context *inc,
640         const struct column_details *details)
641 {
642         (void)column;
643         (void)inc;
644         (void)details;
645         return SR_OK;
646 }
647
648 typedef int (*col_parse_cb)(const char *column, struct context *inc,
649         const struct column_details *details);
650
651 static const col_parse_cb col_parse_funcs[] = {
652         [FORMAT_NONE] = parse_ignore,
653         [FORMAT_BIN] = parse_logic,
654         [FORMAT_OCT] = parse_logic,
655         [FORMAT_HEX] = parse_logic,
656 };
657
658 static int init(struct sr_input *in, GHashTable *options)
659 {
660         struct context *inc;
661         size_t single_column;
662         const char *s;
663         enum single_col_format format;
664         int ret;
665
666         in->sdi = g_malloc0(sizeof(*in->sdi));
667         in->priv = inc = g_malloc0(sizeof(*inc));
668
669         single_column = g_variant_get_uint32(g_hash_table_lookup(options, "single-column"));
670         inc->multi_column_mode = single_column == 0;
671
672         inc->logic_channels = g_variant_get_uint32(g_hash_table_lookup(options, "numchannels"));
673
674         inc->delimiter = g_string_new(g_variant_get_string(
675                         g_hash_table_lookup(options, "delimiter"), NULL));
676         if (!inc->delimiter->len) {
677                 sr_err("Column delimiter cannot be empty.");
678                 return SR_ERR_ARG;
679         }
680
681         s = g_variant_get_string(g_hash_table_lookup(options, "format"), NULL);
682         if (g_ascii_strncasecmp(s, "bin", 3) == 0) {
683                 format = FORMAT_BIN;
684         } else if (g_ascii_strncasecmp(s, "hex", 3) == 0) {
685                 format = FORMAT_HEX;
686         } else if (g_ascii_strncasecmp(s, "oct", 3) == 0) {
687                 format = FORMAT_OCT;
688         } else {
689                 sr_err("Invalid format: '%s'", s);
690                 return SR_ERR_ARG;
691         }
692
693         inc->comment = g_string_new(g_variant_get_string(
694                         g_hash_table_lookup(options, "comment"), NULL));
695         if (g_string_equal(inc->comment, inc->delimiter)) {
696                 /*
697                  * Using the same sequence as comment leader and column
698                  * delimiter won't work. The user probably specified ';'
699                  * as the column delimiter but did not adjust the comment
700                  * leader. Try DWIM, drop comment strippin support here.
701                  */
702                 sr_warn("Comment leader and column delimiter conflict, disabling comment support.");
703                 g_string_truncate(inc->comment, 0);
704         }
705
706         inc->samplerate = g_variant_get_uint64(g_hash_table_lookup(options, "samplerate"));
707
708         inc->first_column = g_variant_get_uint32(g_hash_table_lookup(options, "first-column"));
709
710         inc->use_header = g_variant_get_boolean(g_hash_table_lookup(options, "header"));
711
712         inc->start_line = g_variant_get_uint32(g_hash_table_lookup(options, "startline"));
713         if (inc->start_line < 1) {
714                 sr_err("Invalid start line %zu.", inc->start_line);
715                 return SR_ERR_ARG;
716         }
717
718         /*
719          * Derive the set of columns to inspect and their respective
720          * formats from simple input specs. Remain close to the previous
721          * set of option keywords and their meaning. Exclusively support
722          * a single column with multiple bits in it, or an adjacent set
723          * of colums with one bit each. The latter may not know the total
724          * column count here (when the user omitted the spec), and will
725          * derive it from the first text line of the input file.
726          */
727         s = g_variant_get_string(g_hash_table_lookup(options, "column-formats"), NULL);
728         if (s && *s) {
729                 ret = make_column_details_from_format(inc, s);
730                 if (ret != SR_OK)
731                         return ret;
732         } else if (single_column && inc->logic_channels) {
733                 sr_dbg("DIAG Got single column (%zu) and channels (%zu).",
734                         single_column, inc->logic_channels);
735                 sr_dbg("DIAG -> column %zu, %zu bits in %s format.",
736                         single_column, inc->logic_channels,
737                         col_format_text[format]);
738                 ret = make_column_details_single(inc,
739                         single_column, inc->logic_channels, format);
740                 if (ret != SR_OK)
741                         return ret;
742         } else if (inc->multi_column_mode) {
743                 sr_dbg("DIAG Got multi-column, first column %zu, count %zu.",
744                         inc->first_column, inc->logic_channels);
745                 if (inc->logic_channels) {
746                         sr_dbg("DIAG -> columns %zu-%zu, 1 bit each.",
747                                 inc->first_column,
748                                 inc->first_column + inc->logic_channels - 1);
749                         ret = make_column_details_multi(inc, inc->first_column,
750                                 inc->first_column + inc->logic_channels - 1);
751                         if (ret != SR_OK)
752                                 return ret;
753                 } else {
754                         sr_dbg("DIAG -> incomplete spec, have to update later.");
755                 }
756         } else {
757                 sr_err("Unknown or unsupported combination of option values.");
758                 return SR_ERR_ARG;
759         }
760
761         return SR_OK;
762 }
763
764 /*
765  * Check the channel list for consistency across file re-import. See
766  * the VCD input module for more details and motivation.
767  */
768
769 static void keep_header_for_reread(const struct sr_input *in)
770 {
771         struct context *inc;
772
773         inc = in->priv;
774         g_slist_free_full(inc->prev_sr_channels, sr_channel_free_cb);
775         inc->prev_sr_channels = in->sdi->channels;
776         in->sdi->channels = NULL;
777 }
778
779 static int check_header_in_reread(const struct sr_input *in)
780 {
781         struct context *inc;
782
783         if (!in)
784                 return FALSE;
785         inc = in->priv;
786         if (!inc)
787                 return FALSE;
788         if (!inc->prev_sr_channels)
789                 return TRUE;
790
791         if (sr_channel_lists_differ(inc->prev_sr_channels, in->sdi->channels)) {
792                 sr_err("Channel list change not supported for file re-read.");
793                 return FALSE;
794         }
795         g_slist_free_full(in->sdi->channels, sr_channel_free_cb);
796         in->sdi->channels = inc->prev_sr_channels;
797         inc->prev_sr_channels = NULL;
798
799         return TRUE;
800 }
801
802 static const char *delim_set = "\r\n";
803
804 static const char *get_line_termination(GString *buf)
805 {
806         const char *term;
807
808         term = NULL;
809         if (g_strstr_len(buf->str, buf->len, "\r\n"))
810                 term = "\r\n";
811         else if (memchr(buf->str, '\n', buf->len))
812                 term = "\n";
813         else if (memchr(buf->str, '\r', buf->len))
814                 term = "\r";
815
816         return term;
817 }
818
819 static int initial_parse(const struct sr_input *in, GString *buf)
820 {
821         struct context *inc;
822         GString *channel_name;
823         size_t num_columns, ch_idx, ch_name_idx, col_idx, col_nr;
824         size_t line_number, line_idx;
825         int ret;
826         char **lines, *line, **columns, *column;
827         const char *col_caption;
828         gboolean got_caption;
829         const struct column_details *detail;
830
831         ret = SR_OK;
832         inc = in->priv;
833         columns = NULL;
834
835         line_number = 0;
836         if (inc->termination)
837                 lines = g_strsplit(buf->str, inc->termination, 0);
838         else
839                 lines = g_strsplit_set(buf->str, delim_set, 0);
840         for (line_idx = 0; (line = lines[line_idx]); line_idx++) {
841                 line_number++;
842                 if (inc->start_line > line_number) {
843                         sr_spew("Line %zu skipped (before start).", line_number);
844                         continue;
845                 }
846                 if (line[0] == '\0') {
847                         sr_spew("Blank line %zu skipped.", line_number);
848                         continue;
849                 }
850                 strip_comment(line, inc->comment);
851                 if (line[0] == '\0') {
852                         sr_spew("Comment-only line %zu skipped.", line_number);
853                         continue;
854                 }
855
856                 /* Reached first proper line. */
857                 break;
858         }
859         if (!line) {
860                 /* Not enough data for a proper line yet. */
861                 ret = SR_ERR_NA;
862                 goto out;
863         }
864
865         /* See how many columns the current line has. */
866         columns = split_line(line, inc);
867         if (!columns) {
868                 sr_err("Error while parsing line %zu.", line_number);
869                 ret = SR_ERR;
870                 goto out;
871         }
872         num_columns = g_strv_length(columns);
873         if (!num_columns) {
874                 sr_err("Error while parsing line %zu.", line_number);
875                 ret = SR_ERR;
876                 goto out;
877         }
878         sr_dbg("DIAG Got %zu columns in text line: %s.", num_columns, line);
879
880         /* Optionally update incomplete multi-column specs. */
881         if (inc->multi_column_mode && !inc->logic_channels) {
882                 inc->logic_channels = num_columns - inc->first_column + 1;
883                 sr_dbg("DIAG -> multi-column update: columns %zu-%zu, 1 bit each.",
884                         inc->first_column,
885                         inc->first_column + inc->logic_channels - 1);
886                 ret = make_column_details_multi(inc, inc->first_column,
887                         inc->first_column + inc->logic_channels - 1);
888                 if (ret != SR_OK)
889                         goto out;
890         }
891
892         /*
893          * Assume all lines have equal length (column count). Bail out
894          * early on suspicious or insufficient input data (check input
895          * which became available here against previous user specs or
896          * auto-determined properties, regardless of layout variant).
897          */
898         if (num_columns < inc->column_want_count) {
899                 sr_err("Insufficient input text width for desired data amount, got %zu but want %zu columns.",
900                         num_columns, inc->column_want_count);
901                 ret = SR_ERR;
902                 goto out;
903         }
904
905         /*
906          * Determine channel names. Optionally use text from a header
907          * line (when requested by the user, and only works in multi
908          * column mode). In the absence of header text, or in single
909          * column mode, channels are assigned rather generic names.
910          *
911          * Manipulation of the column's caption is acceptable here, the
912          * header line will never get processed another time.
913          */
914         channel_name = g_string_sized_new(64);
915         for (col_idx = 0; col_idx < inc->column_want_count; col_idx++) {
916
917                 col_nr = col_idx + 1;
918                 detail = lookup_column_details(inc, col_nr);
919                 if (detail->text_format == FORMAT_NONE)
920                         continue;
921                 column = columns[col_idx];
922                 col_caption = sr_scpi_unquote_string(column);
923                 got_caption = inc->use_header && *col_caption;
924                 sr_dbg("DIAG col %zu, ch count %zu, text %s.",
925                         col_nr, detail->channel_count, col_caption);
926                 for (ch_idx = 0; ch_idx < detail->channel_count; ch_idx++) {
927                         ch_name_idx = detail->channel_offset + ch_idx;
928                         if (got_caption && detail->channel_count == 1)
929                                 g_string_assign(channel_name, col_caption);
930                         else if (got_caption)
931                                 g_string_printf(channel_name, "%s[%zu]",
932                                         col_caption, ch_idx);
933                         else
934                                 g_string_printf(channel_name, "%zu", ch_name_idx);
935                         sr_dbg("DIAG ch idx %zu, name %s.", ch_name_idx, channel_name->str);
936                         sr_channel_new(in->sdi, ch_name_idx, SR_CHANNEL_LOGIC, TRUE,
937                                 channel_name->str);
938                 }
939         }
940         g_string_free(channel_name, TRUE);
941         if (!check_header_in_reread(in)) {
942                 ret = SR_ERR_DATA;
943                 goto out;
944         }
945
946         /*
947          * Calculate the minimum buffer size to store the set of samples
948          * of all channels (unit size). Determine a larger buffer size
949          * for datafeed submission that is a multiple of the unit size.
950          * Allocate the larger buffer, the "sample buffer" will point
951          * to a location within that large buffer later.
952          */
953         inc->sample_unit_size = (inc->logic_channels + 7) / 8;
954         inc->datafeed_buf_size = CHUNK_SIZE;
955         inc->datafeed_buf_size *= inc->sample_unit_size;
956         inc->datafeed_buffer = g_malloc(inc->datafeed_buf_size);
957         inc->datafeed_buf_fill = 0;
958
959 out:
960         if (columns)
961                 g_strfreev(columns);
962         g_strfreev(lines);
963
964         return ret;
965 }
966
967 /*
968  * Gets called from initial_receive(), which runs until the end-of-line
969  * encoding of the input stream could get determined. Assumes that this
970  * routine receives enough buffered initial input data to either see the
971  * BOM when there is one, or that no BOM will follow when a text line
972  * termination sequence was seen. Silently drops the UTF-8 BOM sequence
973  * from the input buffer if one was seen. Does not care to protect
974  * against multiple execution or dropping the BOM multiple times --
975  * there should be at most one in the input stream.
976  */
977 static void initial_bom_check(const struct sr_input *in)
978 {
979         static const char *utf8_bom = "\xef\xbb\xbf";
980
981         if (in->buf->len < strlen(utf8_bom))
982                 return;
983         if (strncmp(in->buf->str, utf8_bom, strlen(utf8_bom)) != 0)
984                 return;
985         g_string_erase(in->buf, 0, strlen(utf8_bom));
986 }
987
988 static int initial_receive(const struct sr_input *in)
989 {
990         struct context *inc;
991         GString *new_buf;
992         int len, ret;
993         char *p;
994         const char *termination;
995
996         initial_bom_check(in);
997
998         inc = in->priv;
999
1000         termination = get_line_termination(in->buf);
1001         if (!termination)
1002                 /* Don't have a full line yet. */
1003                 return SR_ERR_NA;
1004
1005         p = g_strrstr_len(in->buf->str, in->buf->len, termination);
1006         if (!p)
1007                 /* Don't have a full line yet. */
1008                 return SR_ERR_NA;
1009         len = p - in->buf->str - 1;
1010         new_buf = g_string_new_len(in->buf->str, len);
1011         g_string_append_c(new_buf, '\0');
1012
1013         inc->termination = g_strdup(termination);
1014
1015         if (in->buf->str[0] != '\0')
1016                 ret = initial_parse(in, new_buf);
1017         else
1018                 ret = SR_OK;
1019
1020         g_string_free(new_buf, TRUE);
1021
1022         return ret;
1023 }
1024
1025 static int process_buffer(struct sr_input *in, gboolean is_eof)
1026 {
1027         struct context *inc;
1028         gsize num_columns;
1029         size_t line_idx, col_idx, col_nr;
1030         const struct column_details *details;
1031         col_parse_cb parse_func;
1032         int ret;
1033         char *p, **lines, *line, **columns, *column;
1034
1035         inc = in->priv;
1036         if (!inc->started) {
1037                 std_session_send_df_header(in->sdi);
1038                 inc->started = TRUE;
1039         }
1040
1041         /*
1042          * Consider empty input non-fatal. Keep accumulating input until
1043          * at least one full text line has become available. Grab the
1044          * maximum amount of accumulated data that consists of full text
1045          * lines, and process what has been received so far, leaving not
1046          * yet complete lines for the next invocation.
1047          *
1048          * Enforce that all previously buffered data gets processed in
1049          * the "EOF" condition. Do not insist in the presence of the
1050          * termination sequence for the last line (may often be missing
1051          * on Windows). A present termination sequence will just result
1052          * in the "execution of an empty line", and does not harm.
1053          */
1054         if (!in->buf->len)
1055                 return SR_OK;
1056         if (is_eof) {
1057                 p = in->buf->str + in->buf->len;
1058         } else {
1059                 p = g_strrstr_len(in->buf->str, in->buf->len, inc->termination);
1060                 if (!p)
1061                         return SR_ERR;
1062                 *p = '\0';
1063                 p += strlen(inc->termination);
1064         }
1065         g_strstrip(in->buf->str);
1066
1067         ret = SR_OK;
1068         lines = g_strsplit(in->buf->str, inc->termination, 0);
1069         for (line_idx = 0; (line = lines[line_idx]); line_idx++) {
1070                 inc->line_number++;
1071                 if (inc->line_number < inc->start_line) {
1072                         sr_spew("Line %zu skipped (before start).", inc->line_number);
1073                         continue;
1074                 }
1075                 if (line[0] == '\0') {
1076                         sr_spew("Blank line %zu skipped.", inc->line_number);
1077                         continue;
1078                 }
1079
1080                 /* Remove trailing comment. */
1081                 strip_comment(line, inc->comment);
1082                 if (line[0] == '\0') {
1083                         sr_spew("Comment-only line %zu skipped.", inc->line_number);
1084                         continue;
1085                 }
1086
1087                 /* Skip the header line, its content was used as the channel names. */
1088                 if (inc->use_header && !inc->header_seen) {
1089                         sr_spew("Header line %zu skipped.", inc->line_number);
1090                         inc->header_seen = TRUE;
1091                         continue;
1092                 }
1093
1094                 /* Split the line into columns, check for minimum length. */
1095                 columns = split_line(line, inc);
1096                 if (!columns) {
1097                         sr_err("Error while parsing line %zu.", inc->line_number);
1098                         g_strfreev(lines);
1099                         return SR_ERR;
1100                 }
1101                 num_columns = g_strv_length(columns);
1102                 if (num_columns < inc->column_want_count) {
1103                         sr_err("Insufficient column count %zu in line %zu.",
1104                                 num_columns, inc->line_number);
1105                         g_strfreev(columns);
1106                         g_strfreev(lines);
1107                         return SR_ERR;
1108                 }
1109
1110                 /* Have the columns of the current text line processed. */
1111                 clear_logic_samples(inc);
1112                 for (col_idx = 0; col_idx < inc->column_want_count; col_idx++) {
1113                         column = columns[col_idx];
1114                         col_nr = col_idx + 1;
1115                         details = lookup_column_details(inc, col_nr);
1116                         if (!details || !details->text_format)
1117                                 continue;
1118                         parse_func = col_parse_funcs[details->text_format];
1119                         if (!parse_func)
1120                                 continue;
1121                         ret = parse_func(column, inc, details);
1122                         if (ret != SR_OK) {
1123                                 g_strfreev(columns);
1124                                 g_strfreev(lines);
1125                                 return SR_ERR;
1126                         }
1127                 }
1128
1129                 /* Send sample data to the session bus (buffered). */
1130                 ret = queue_logic_samples(in);
1131                 if (ret != SR_OK) {
1132                         sr_err("Sending samples failed.");
1133                         g_strfreev(columns);
1134                         g_strfreev(lines);
1135                         return SR_ERR;
1136                 }
1137
1138                 g_strfreev(columns);
1139         }
1140         g_strfreev(lines);
1141         g_string_erase(in->buf, 0, p - in->buf->str);
1142
1143         return ret;
1144 }
1145
1146 static int receive(struct sr_input *in, GString *buf)
1147 {
1148         struct context *inc;
1149         int ret;
1150
1151         g_string_append_len(in->buf, buf->str, buf->len);
1152
1153         inc = in->priv;
1154         if (!inc->termination) {
1155                 ret = initial_receive(in);
1156                 if (ret == SR_ERR_NA)
1157                         /* Not enough data yet. */
1158                         return SR_OK;
1159                 else if (ret != SR_OK)
1160                         return SR_ERR;
1161
1162                 /* sdi is ready, notify frontend. */
1163                 in->sdi_ready = TRUE;
1164                 return SR_OK;
1165         }
1166
1167         ret = process_buffer(in, FALSE);
1168
1169         return ret;
1170 }
1171
1172 static int end(struct sr_input *in)
1173 {
1174         struct context *inc;
1175         int ret;
1176
1177         if (in->sdi_ready)
1178                 ret = process_buffer(in, TRUE);
1179         else
1180                 ret = SR_OK;
1181         if (ret != SR_OK)
1182                 return ret;
1183
1184         ret = flush_logic_samples(in);
1185         if (ret != SR_OK)
1186                 return ret;
1187
1188         inc = in->priv;
1189         if (inc->started)
1190                 std_session_send_df_end(in->sdi);
1191
1192         return ret;
1193 }
1194
1195 static void cleanup(struct sr_input *in)
1196 {
1197         struct context *inc;
1198
1199         keep_header_for_reread(in);
1200
1201         inc = in->priv;
1202
1203         g_free(inc->termination);
1204         inc->termination = NULL;
1205         g_free(inc->datafeed_buffer);
1206         inc->datafeed_buffer = NULL;
1207 }
1208
1209 static int reset(struct sr_input *in)
1210 {
1211         struct context *inc = in->priv;
1212
1213         cleanup(in);
1214         inc->started = FALSE;
1215         g_string_truncate(in->buf, 0);
1216
1217         return SR_OK;
1218 }
1219
1220 enum option_index {
1221         OPT_COL_FMTS,
1222         OPT_SINGLE_COL,
1223         OPT_NUM_LOGIC,
1224         OPT_DELIM,
1225         OPT_FORMAT,
1226         OPT_COMMENT,
1227         OPT_RATE,
1228         OPT_FIRST_COL,
1229         OPT_HEADER,
1230         OPT_START,
1231         OPT_MAX,
1232 };
1233
1234 static struct sr_option options[] = {
1235         [OPT_COL_FMTS] = { "column-formats", "Column format specs", "Specifies text columns data types: comma separated list of [<cols>]<fmt>[<bits>]", NULL, NULL },
1236         [OPT_SINGLE_COL] = { "single-column", "Single column", "Enable single-column mode, using the specified column (>= 1); 0: multi-col. mode", NULL, NULL },
1237         [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 },
1238         [OPT_DELIM] = { "delimiter", "Column delimiter", "The column delimiter (>= 1 characters)", NULL, NULL },
1239         [OPT_FORMAT] = { "format", "Data format (single-col. mode)", "The numeric format of the data (single-col. mode): bin, hex, oct", NULL, NULL },
1240         [OPT_COMMENT] = { "comment", "Comment character(s)", "The comment prefix character(s)", NULL, NULL },
1241         [OPT_RATE] = { "samplerate", "Samplerate (Hz)", "The sample rate (used during capture) in Hz", NULL, NULL },
1242         [OPT_FIRST_COL] = { "first-column", "First column", "The column number of the first channel (multi-col. mode)", NULL, NULL },
1243         [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 },
1244         [OPT_START] = { "startline", "Start line", "The line number at which to start processing samples (>= 1)", NULL, NULL },
1245         [OPT_MAX] = ALL_ZERO,
1246 };
1247
1248 static const struct sr_option *get_options(void)
1249 {
1250         GSList *l;
1251
1252         if (!options[0].def) {
1253                 options[OPT_COL_FMTS].def = g_variant_ref_sink(g_variant_new_string("0l"));
1254                 options[OPT_SINGLE_COL].def = g_variant_ref_sink(g_variant_new_uint32(0));
1255                 options[OPT_NUM_LOGIC].def = g_variant_ref_sink(g_variant_new_uint32(0));
1256                 options[OPT_DELIM].def = g_variant_ref_sink(g_variant_new_string(","));
1257                 options[OPT_FORMAT].def = g_variant_ref_sink(g_variant_new_string("bin"));
1258                 l = NULL;
1259                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("bin")));
1260                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("hex")));
1261                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("oct")));
1262                 options[OPT_FORMAT].values = l;
1263                 options[OPT_COMMENT].def = g_variant_ref_sink(g_variant_new_string(";"));
1264                 options[OPT_RATE].def = g_variant_ref_sink(g_variant_new_uint64(0));
1265                 options[OPT_FIRST_COL].def = g_variant_ref_sink(g_variant_new_uint32(1));
1266                 options[OPT_HEADER].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
1267                 options[OPT_START].def = g_variant_ref_sink(g_variant_new_uint32(1));
1268         }
1269
1270         return options;
1271 }
1272
1273 SR_PRIV struct sr_input_module input_csv = {
1274         .id = "csv",
1275         .name = "CSV",
1276         .desc = "Comma-separated values",
1277         .exts = (const char*[]){"csv", NULL},
1278         .options = get_options,
1279         .init = init,
1280         .receive = receive,
1281         .end = end,
1282         .cleanup = cleanup,
1283         .reset = reset,
1284 };