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