]> sigrok.org Git - libsigrok.git/blob - src/input/csv.c
88c49c43f19456df83dac61a85e118fc18c2233c
[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 static int make_column_details_single(struct context *inc,
276         size_t col_nr, size_t bit_count, enum single_col_format format)
277 {
278         struct column_details *details;
279
280         /*
281          * Need at least as many columns to also include the one with
282          * the single-column input data.
283          */
284         inc->column_want_count = col_nr;
285
286         /*
287          * Allocate the columns' processing details. Columns are counted
288          * from 1 (user's perspective), array items from 0 (programmer's
289          * perspective).
290          */
291         inc->column_details = g_malloc0_n(col_nr, sizeof(inc->column_details[0]));
292         details = &inc->column_details[col_nr - 1];
293         details->col_nr = col_nr;
294
295         /*
296          * In single-column mode this single column will hold all bits
297          * of all logic channels, in the user specified number format.
298          */
299         details->text_format = format;
300         details->channel_offset = 0;
301         details->channel_count = bit_count;
302
303         return SR_OK;
304 }
305
306 static int make_column_details_multi(struct context *inc,
307         size_t first_col, size_t last_col)
308 {
309         struct column_details *details;
310         size_t col_nr;
311
312         /*
313          * Need at least as many columns to also include the one with
314          * the last channel's data.
315          */
316         inc->column_want_count = last_col;
317
318         /*
319          * Allocate the columns' processing details. Columns are counted
320          * from 1, array items from 0.
321          * In multi-column mode each column will hold a single bit for
322          * the respective channel.
323          */
324         inc->column_details = g_malloc0_n(last_col, sizeof(inc->column_details[0]));
325         for (col_nr = first_col; col_nr <= last_col; col_nr++) {
326                 details = &inc->column_details[col_nr - 1];
327                 details->col_nr = col_nr;
328                 details->text_format = FORMAT_BIN;
329                 details->channel_offset = col_nr - first_col;
330                 details->channel_count = 1;
331         }
332
333
334         return SR_OK;
335 }
336
337 static const struct column_details *lookup_column_details(struct context *inc, size_t nr)
338 {
339         if (!inc || !inc->column_details)
340                 return NULL;
341         if (!nr || nr > inc->column_want_count)
342                 return NULL;
343         return &inc->column_details[nr - 1];
344 }
345
346 /*
347  * Primitive operations for text input: Strip comments off text lines.
348  * Split text lines into columns. Process input text for individual
349  * columns.
350  */
351
352 static void strip_comment(char *buf, const GString *prefix)
353 {
354         char *ptr;
355
356         if (!prefix->len)
357                 return;
358
359         if ((ptr = strstr(buf, prefix->str))) {
360                 *ptr = '\0';
361                 g_strstrip(buf);
362         }
363 }
364
365 /**
366  * @brief Splits a text line into a set of columns.
367  *
368  * @param[in] buf       The input text line to split.
369  * @param[in] inc       The input module's context.
370  *
371  * @returns An array of strings, representing the columns' text.
372  *
373  * This routine splits a text line on previously determined separators.
374  */
375 static char **split_line(char *buf, struct context *inc)
376 {
377         return g_strsplit(buf, inc->delimiter->str, 0);
378 }
379
380 /**
381  * @brief Parse a multi-bit field into several logic channels.
382  *
383  * @param[in] column    The input text, a run of bin/hex/oct digits.
384  * @param[in] inc       The input module's context.
385  * @param[in] details   The column processing details.
386  *
387  * @retval SR_OK        Success.
388  * @retval SR_ERR       Invalid input data (empty, or format error).
389  *
390  * This routine modifies the logic levels in the current sample set,
391  * based on the text input and a user provided format spec.
392  */
393 static int parse_logic(const char *column, struct context *inc,
394         const struct column_details *details)
395 {
396         size_t length, ch_rem, ch_idx, ch_inc;
397         const char *rdptr;
398         char c;
399         gboolean valid;
400         const char *type_text;
401         uint8_t bits;
402
403         /*
404          * Prepare to read the digits from the text end towards the start.
405          * A digit corresponds to a variable number of channels (depending
406          * on the value's radix). Prepare the mapping of text digits to
407          * (a number of) logic channels.
408          */
409         length = strlen(column);
410         if (!length) {
411                 sr_err("Column %zu in line %zu is empty.", details->col_nr,
412                         inc->line_number);
413                 return SR_ERR;
414         }
415         rdptr = &column[length];
416         ch_idx = details->channel_offset;
417         ch_rem = details->channel_count;
418
419         /*
420          * Get another digit and derive up to four logic channels' state from
421          * it. Make sure to not process more bits than the column has channels
422          * associated with it.
423          */
424         while (rdptr > column && ch_rem) {
425                 /* Check for valid digits according to the input radix. */
426                 c = *(--rdptr);
427                 switch (details->text_format) {
428                 case FORMAT_BIN:
429                         valid = g_ascii_isxdigit(c) && c < '2';
430                         ch_inc = 1;
431                         break;
432                 case FORMAT_OCT:
433                         valid = g_ascii_isxdigit(c) && c < '8';
434                         ch_inc = 3;
435                         break;
436                 case FORMAT_HEX:
437                         valid = g_ascii_isxdigit(c);
438                         ch_inc = 4;
439                         break;
440                 default:
441                         valid = FALSE;
442                         break;
443                 }
444                 if (!valid) {
445                         type_text = col_format_text[details->text_format];
446                         sr_err("Invalid text '%s' in %s type column %zu in line %zu.",
447                                 column, type_text, details->col_nr, inc->line_number);
448                         return SR_ERR;
449                 }
450                 /* Use the digit's bits for logic channels' data. */
451                 bits = g_ascii_xdigit_value(c);
452                 switch (details->text_format) {
453                 case FORMAT_HEX:
454                         if (ch_rem >= 4) {
455                                 ch_rem--;
456                                 set_logic_level(inc, ch_idx + 3, bits & (1 << 3));
457                         }
458                         /* FALLTHROUGH */
459                 case FORMAT_OCT:
460                         if (ch_rem >= 3) {
461                                 ch_rem--;
462                                 set_logic_level(inc, ch_idx + 2, bits & (1 << 2));
463                         }
464                         if (ch_rem >= 2) {
465                                 ch_rem--;
466                                 set_logic_level(inc, ch_idx + 1, bits & (1 << 1));
467                         }
468                         /* FALLTHROUGH */
469                 case FORMAT_BIN:
470                         ch_rem--;
471                         set_logic_level(inc, ch_idx + 0, bits & (1 << 0));
472                         break;
473                 case FORMAT_NONE:
474                         /* ShouldNotHappen(TM), but silences compiler warning. */
475                         return SR_ERR;
476                 }
477                 ch_idx += ch_inc;
478         }
479         /*
480          * TODO Determine whether the availability of extra input data
481          * for unhandled logic channels is worth warning here. In this
482          * implementation users are in control, and can have the more
483          * significant bits ignored (which can be considered a feature
484          * and not really a limitation).
485          */
486
487         return SR_OK;
488 }
489
490 /**
491  * @brief Parse routine which ignores the input text.
492  *
493  * This routine exists to unify dispatch code paths, mapping input file
494  * columns' data types to their respective parse routines.
495  */
496 static int parse_ignore(const char *column, struct context *inc,
497         const struct column_details *details)
498 {
499         (void)column;
500         (void)inc;
501         (void)details;
502         return SR_OK;
503 }
504
505 typedef int (*col_parse_cb)(const char *column, struct context *inc,
506         const struct column_details *details);
507
508 static const col_parse_cb col_parse_funcs[] = {
509         [FORMAT_NONE] = parse_ignore,
510         [FORMAT_BIN] = parse_logic,
511         [FORMAT_OCT] = parse_logic,
512         [FORMAT_HEX] = parse_logic,
513 };
514
515 static int init(struct sr_input *in, GHashTable *options)
516 {
517         struct context *inc;
518         size_t single_column;
519         const char *s;
520         enum single_col_format format;
521         int ret;
522
523         in->sdi = g_malloc0(sizeof(*in->sdi));
524         in->priv = inc = g_malloc0(sizeof(*inc));
525
526         single_column = g_variant_get_uint32(g_hash_table_lookup(options, "single-column"));
527         inc->multi_column_mode = single_column == 0;
528
529         inc->logic_channels = g_variant_get_uint32(g_hash_table_lookup(options, "numchannels"));
530
531         inc->delimiter = g_string_new(g_variant_get_string(
532                         g_hash_table_lookup(options, "delimiter"), NULL));
533         if (!inc->delimiter->len) {
534                 sr_err("Column delimiter cannot be empty.");
535                 return SR_ERR_ARG;
536         }
537
538         s = g_variant_get_string(g_hash_table_lookup(options, "format"), NULL);
539         if (g_ascii_strncasecmp(s, "bin", 3) == 0) {
540                 format = FORMAT_BIN;
541         } else if (g_ascii_strncasecmp(s, "hex", 3) == 0) {
542                 format = FORMAT_HEX;
543         } else if (g_ascii_strncasecmp(s, "oct", 3) == 0) {
544                 format = FORMAT_OCT;
545         } else {
546                 sr_err("Invalid format: '%s'", s);
547                 return SR_ERR_ARG;
548         }
549
550         inc->comment = g_string_new(g_variant_get_string(
551                         g_hash_table_lookup(options, "comment"), NULL));
552         if (g_string_equal(inc->comment, inc->delimiter)) {
553                 /*
554                  * Using the same sequence as comment leader and column
555                  * delimiter won't work. The user probably specified ';'
556                  * as the column delimiter but did not adjust the comment
557                  * leader. Try DWIM, drop comment strippin support here.
558                  */
559                 sr_warn("Comment leader and column delimiter conflict, disabling comment support.");
560                 g_string_truncate(inc->comment, 0);
561         }
562
563         inc->samplerate = g_variant_get_uint64(g_hash_table_lookup(options, "samplerate"));
564
565         inc->first_column = g_variant_get_uint32(g_hash_table_lookup(options, "first-column"));
566
567         inc->use_header = g_variant_get_boolean(g_hash_table_lookup(options, "header"));
568
569         inc->start_line = g_variant_get_uint32(g_hash_table_lookup(options, "startline"));
570         if (inc->start_line < 1) {
571                 sr_err("Invalid start line %zu.", inc->start_line);
572                 return SR_ERR_ARG;
573         }
574
575         /*
576          * Derive the set of columns to inspect and their respective
577          * formats from simple input specs. Remain close to the previous
578          * set of option keywords and their meaning. Exclusively support
579          * a single column with multiple bits in it, or an adjacent set
580          * of colums with one bit each. The latter may not know the total
581          * column count here (when the user omitted the spec), and will
582          * derive it from the first text line of the input file.
583          */
584         if (single_column && inc->logic_channels) {
585                 sr_dbg("DIAG Got single column (%zu) and channels (%zu).",
586                         single_column, inc->logic_channels);
587                 sr_dbg("DIAG -> column %zu, %zu bits in %s format.",
588                         single_column, inc->logic_channels,
589                         col_format_text[format]);
590                 ret = make_column_details_single(inc,
591                         single_column, inc->logic_channels, format);
592                 if (ret != SR_OK)
593                         return ret;
594         } else if (inc->multi_column_mode) {
595                 sr_dbg("DIAG Got multi-column, first column %zu, count %zu.",
596                         inc->first_column, inc->logic_channels);
597                 if (inc->logic_channels) {
598                         sr_dbg("DIAG -> columns %zu-%zu, 1 bit each.",
599                                 inc->first_column,
600                                 inc->first_column + inc->logic_channels - 1);
601                         ret = make_column_details_multi(inc, inc->first_column,
602                                 inc->first_column + inc->logic_channels - 1);
603                         if (ret != SR_OK)
604                                 return ret;
605                 } else {
606                         sr_dbg("DIAG -> incomplete spec, have to update later.");
607                 }
608         } else {
609                 sr_err("Unknown or unsupported combination of option values.");
610                 return SR_ERR_ARG;
611         }
612
613         return SR_OK;
614 }
615
616 /*
617  * Check the channel list for consistency across file re-import. See
618  * the VCD input module for more details and motivation.
619  */
620
621 static void keep_header_for_reread(const struct sr_input *in)
622 {
623         struct context *inc;
624
625         inc = in->priv;
626         g_slist_free_full(inc->prev_sr_channels, sr_channel_free_cb);
627         inc->prev_sr_channels = in->sdi->channels;
628         in->sdi->channels = NULL;
629 }
630
631 static int check_header_in_reread(const struct sr_input *in)
632 {
633         struct context *inc;
634
635         if (!in)
636                 return FALSE;
637         inc = in->priv;
638         if (!inc)
639                 return FALSE;
640         if (!inc->prev_sr_channels)
641                 return TRUE;
642
643         if (sr_channel_lists_differ(inc->prev_sr_channels, in->sdi->channels)) {
644                 sr_err("Channel list change not supported for file re-read.");
645                 return FALSE;
646         }
647         g_slist_free_full(in->sdi->channels, sr_channel_free_cb);
648         in->sdi->channels = inc->prev_sr_channels;
649         inc->prev_sr_channels = NULL;
650
651         return TRUE;
652 }
653
654 static const char *delim_set = "\r\n";
655
656 static const char *get_line_termination(GString *buf)
657 {
658         const char *term;
659
660         term = NULL;
661         if (g_strstr_len(buf->str, buf->len, "\r\n"))
662                 term = "\r\n";
663         else if (memchr(buf->str, '\n', buf->len))
664                 term = "\n";
665         else if (memchr(buf->str, '\r', buf->len))
666                 term = "\r";
667
668         return term;
669 }
670
671 static int initial_parse(const struct sr_input *in, GString *buf)
672 {
673         struct context *inc;
674         GString *channel_name;
675         size_t num_columns, ch_idx, ch_name_idx, col_idx, col_nr;
676         size_t line_number, line_idx;
677         int ret;
678         char **lines, *line, **columns, *column;
679         const char *col_caption;
680         gboolean got_caption;
681         const struct column_details *detail;
682
683         ret = SR_OK;
684         inc = in->priv;
685         columns = NULL;
686
687         line_number = 0;
688         if (inc->termination)
689                 lines = g_strsplit(buf->str, inc->termination, 0);
690         else
691                 lines = g_strsplit_set(buf->str, delim_set, 0);
692         for (line_idx = 0; (line = lines[line_idx]); line_idx++) {
693                 line_number++;
694                 if (inc->start_line > line_number) {
695                         sr_spew("Line %zu skipped (before start).", line_number);
696                         continue;
697                 }
698                 if (line[0] == '\0') {
699                         sr_spew("Blank line %zu skipped.", line_number);
700                         continue;
701                 }
702                 strip_comment(line, inc->comment);
703                 if (line[0] == '\0') {
704                         sr_spew("Comment-only line %zu skipped.", line_number);
705                         continue;
706                 }
707
708                 /* Reached first proper line. */
709                 break;
710         }
711         if (!line) {
712                 /* Not enough data for a proper line yet. */
713                 ret = SR_ERR_NA;
714                 goto out;
715         }
716
717         /* See how many columns the current line has. */
718         columns = split_line(line, inc);
719         if (!columns) {
720                 sr_err("Error while parsing line %zu.", line_number);
721                 ret = SR_ERR;
722                 goto out;
723         }
724         num_columns = g_strv_length(columns);
725         if (!num_columns) {
726                 sr_err("Error while parsing line %zu.", line_number);
727                 ret = SR_ERR;
728                 goto out;
729         }
730         sr_dbg("DIAG Got %zu columns in text line: %s.", num_columns, line);
731
732         /* Optionally update incomplete multi-column specs. */
733         if (inc->multi_column_mode && !inc->logic_channels) {
734                 inc->logic_channels = num_columns - inc->first_column + 1;
735                 sr_dbg("DIAG -> multi-column update: columns %zu-%zu, 1 bit each.",
736                         inc->first_column,
737                         inc->first_column + inc->logic_channels - 1);
738                 ret = make_column_details_multi(inc, inc->first_column,
739                         inc->first_column + inc->logic_channels - 1);
740                 if (ret != SR_OK)
741                         goto out;
742         }
743
744         /*
745          * Assume all lines have equal length (column count). Bail out
746          * early on suspicious or insufficient input data (check input
747          * which became available here against previous user specs or
748          * auto-determined properties, regardless of layout variant).
749          */
750         if (num_columns < inc->column_want_count) {
751                 sr_err("Insufficient input text width for desired data amount, got %zu but want %zu columns.",
752                         num_columns, inc->column_want_count);
753                 ret = SR_ERR;
754                 goto out;
755         }
756
757         /*
758          * Determine channel names. Optionally use text from a header
759          * line (when requested by the user, and only works in multi
760          * column mode). In the absence of header text, or in single
761          * column mode, channels are assigned rather generic names.
762          *
763          * Manipulation of the column's caption is acceptable here, the
764          * header line will never get processed another time.
765          */
766         channel_name = g_string_sized_new(64);
767         for (col_idx = 0; col_idx < inc->column_want_count; col_idx++) {
768
769                 col_nr = col_idx + 1;
770                 detail = lookup_column_details(inc, col_nr);
771                 if (detail->text_format == FORMAT_NONE)
772                         continue;
773                 column = columns[col_idx];
774                 col_caption = sr_scpi_unquote_string(column);
775                 got_caption = inc->use_header && *col_caption;
776                 sr_dbg("DIAG col %zu, ch count %zu, text %s.",
777                         col_nr, detail->channel_count, col_caption);
778                 for (ch_idx = 0; ch_idx < detail->channel_count; ch_idx++) {
779                         ch_name_idx = detail->channel_offset + ch_idx;
780                         if (got_caption && detail->channel_count == 1)
781                                 g_string_assign(channel_name, col_caption);
782                         else if (got_caption)
783                                 g_string_printf(channel_name, "%s[%zu]",
784                                         col_caption, ch_idx);
785                         else
786                                 g_string_printf(channel_name, "%zu", ch_name_idx);
787                         sr_dbg("DIAG ch idx %zu, name %s.", ch_name_idx, channel_name->str);
788                         sr_channel_new(in->sdi, ch_name_idx, SR_CHANNEL_LOGIC, TRUE,
789                                 channel_name->str);
790                 }
791         }
792         g_string_free(channel_name, TRUE);
793         if (!check_header_in_reread(in)) {
794                 ret = SR_ERR_DATA;
795                 goto out;
796         }
797
798         /*
799          * Calculate the minimum buffer size to store the set of samples
800          * of all channels (unit size). Determine a larger buffer size
801          * for datafeed submission that is a multiple of the unit size.
802          * Allocate the larger buffer, the "sample buffer" will point
803          * to a location within that large buffer later.
804          */
805         inc->sample_unit_size = (inc->logic_channels + 7) / 8;
806         inc->datafeed_buf_size = CHUNK_SIZE;
807         inc->datafeed_buf_size *= inc->sample_unit_size;
808         inc->datafeed_buffer = g_malloc(inc->datafeed_buf_size);
809         inc->datafeed_buf_fill = 0;
810
811 out:
812         if (columns)
813                 g_strfreev(columns);
814         g_strfreev(lines);
815
816         return ret;
817 }
818
819 /*
820  * Gets called from initial_receive(), which runs until the end-of-line
821  * encoding of the input stream could get determined. Assumes that this
822  * routine receives enough buffered initial input data to either see the
823  * BOM when there is one, or that no BOM will follow when a text line
824  * termination sequence was seen. Silently drops the UTF-8 BOM sequence
825  * from the input buffer if one was seen. Does not care to protect
826  * against multiple execution or dropping the BOM multiple times --
827  * there should be at most one in the input stream.
828  */
829 static void initial_bom_check(const struct sr_input *in)
830 {
831         static const char *utf8_bom = "\xef\xbb\xbf";
832
833         if (in->buf->len < strlen(utf8_bom))
834                 return;
835         if (strncmp(in->buf->str, utf8_bom, strlen(utf8_bom)) != 0)
836                 return;
837         g_string_erase(in->buf, 0, strlen(utf8_bom));
838 }
839
840 static int initial_receive(const struct sr_input *in)
841 {
842         struct context *inc;
843         GString *new_buf;
844         int len, ret;
845         char *p;
846         const char *termination;
847
848         initial_bom_check(in);
849
850         inc = in->priv;
851
852         termination = get_line_termination(in->buf);
853         if (!termination)
854                 /* Don't have a full line yet. */
855                 return SR_ERR_NA;
856
857         p = g_strrstr_len(in->buf->str, in->buf->len, termination);
858         if (!p)
859                 /* Don't have a full line yet. */
860                 return SR_ERR_NA;
861         len = p - in->buf->str - 1;
862         new_buf = g_string_new_len(in->buf->str, len);
863         g_string_append_c(new_buf, '\0');
864
865         inc->termination = g_strdup(termination);
866
867         if (in->buf->str[0] != '\0')
868                 ret = initial_parse(in, new_buf);
869         else
870                 ret = SR_OK;
871
872         g_string_free(new_buf, TRUE);
873
874         return ret;
875 }
876
877 static int process_buffer(struct sr_input *in, gboolean is_eof)
878 {
879         struct context *inc;
880         gsize num_columns;
881         size_t line_idx, col_idx, col_nr;
882         const struct column_details *details;
883         col_parse_cb parse_func;
884         int ret;
885         char *p, **lines, *line, **columns, *column;
886
887         inc = in->priv;
888         if (!inc->started) {
889                 std_session_send_df_header(in->sdi);
890                 inc->started = TRUE;
891         }
892
893         /*
894          * Consider empty input non-fatal. Keep accumulating input until
895          * at least one full text line has become available. Grab the
896          * maximum amount of accumulated data that consists of full text
897          * lines, and process what has been received so far, leaving not
898          * yet complete lines for the next invocation.
899          *
900          * Enforce that all previously buffered data gets processed in
901          * the "EOF" condition. Do not insist in the presence of the
902          * termination sequence for the last line (may often be missing
903          * on Windows). A present termination sequence will just result
904          * in the "execution of an empty line", and does not harm.
905          */
906         if (!in->buf->len)
907                 return SR_OK;
908         if (is_eof) {
909                 p = in->buf->str + in->buf->len;
910         } else {
911                 p = g_strrstr_len(in->buf->str, in->buf->len, inc->termination);
912                 if (!p)
913                         return SR_ERR;
914                 *p = '\0';
915                 p += strlen(inc->termination);
916         }
917         g_strstrip(in->buf->str);
918
919         ret = SR_OK;
920         lines = g_strsplit(in->buf->str, inc->termination, 0);
921         for (line_idx = 0; (line = lines[line_idx]); line_idx++) {
922                 inc->line_number++;
923                 if (inc->line_number < inc->start_line) {
924                         sr_spew("Line %zu skipped (before start).", inc->line_number);
925                         continue;
926                 }
927                 if (line[0] == '\0') {
928                         sr_spew("Blank line %zu skipped.", inc->line_number);
929                         continue;
930                 }
931
932                 /* Remove trailing comment. */
933                 strip_comment(line, inc->comment);
934                 if (line[0] == '\0') {
935                         sr_spew("Comment-only line %zu skipped.", inc->line_number);
936                         continue;
937                 }
938
939                 /* Skip the header line, its content was used as the channel names. */
940                 if (inc->use_header && !inc->header_seen) {
941                         sr_spew("Header line %zu skipped.", inc->line_number);
942                         inc->header_seen = TRUE;
943                         continue;
944                 }
945
946                 /* Split the line into columns, check for minimum length. */
947                 columns = split_line(line, inc);
948                 if (!columns) {
949                         sr_err("Error while parsing line %zu.", inc->line_number);
950                         g_strfreev(lines);
951                         return SR_ERR;
952                 }
953                 num_columns = g_strv_length(columns);
954                 if (num_columns < inc->column_want_count) {
955                         sr_err("Insufficient column count %zu in line %zu.",
956                                 num_columns, inc->line_number);
957                         g_strfreev(columns);
958                         g_strfreev(lines);
959                         return SR_ERR;
960                 }
961
962                 /* Have the columns of the current text line processed. */
963                 clear_logic_samples(inc);
964                 for (col_idx = 0; col_idx < inc->column_want_count; col_idx++) {
965                         column = columns[col_idx];
966                         col_nr = col_idx + 1;
967                         details = lookup_column_details(inc, col_nr);
968                         if (!details || !details->text_format)
969                                 continue;
970                         parse_func = col_parse_funcs[details->text_format];
971                         if (!parse_func)
972                                 continue;
973                         ret = parse_func(column, inc, details);
974                         if (ret != SR_OK) {
975                                 g_strfreev(columns);
976                                 g_strfreev(lines);
977                                 return SR_ERR;
978                         }
979                 }
980
981                 /* Send sample data to the session bus (buffered). */
982                 ret = queue_logic_samples(in);
983                 if (ret != SR_OK) {
984                         sr_err("Sending samples failed.");
985                         g_strfreev(columns);
986                         g_strfreev(lines);
987                         return SR_ERR;
988                 }
989
990                 g_strfreev(columns);
991         }
992         g_strfreev(lines);
993         g_string_erase(in->buf, 0, p - in->buf->str);
994
995         return ret;
996 }
997
998 static int receive(struct sr_input *in, GString *buf)
999 {
1000         struct context *inc;
1001         int ret;
1002
1003         g_string_append_len(in->buf, buf->str, buf->len);
1004
1005         inc = in->priv;
1006         if (!inc->termination) {
1007                 ret = initial_receive(in);
1008                 if (ret == SR_ERR_NA)
1009                         /* Not enough data yet. */
1010                         return SR_OK;
1011                 else if (ret != SR_OK)
1012                         return SR_ERR;
1013
1014                 /* sdi is ready, notify frontend. */
1015                 in->sdi_ready = TRUE;
1016                 return SR_OK;
1017         }
1018
1019         ret = process_buffer(in, FALSE);
1020
1021         return ret;
1022 }
1023
1024 static int end(struct sr_input *in)
1025 {
1026         struct context *inc;
1027         int ret;
1028
1029         if (in->sdi_ready)
1030                 ret = process_buffer(in, TRUE);
1031         else
1032                 ret = SR_OK;
1033         if (ret != SR_OK)
1034                 return ret;
1035
1036         ret = flush_logic_samples(in);
1037         if (ret != SR_OK)
1038                 return ret;
1039
1040         inc = in->priv;
1041         if (inc->started)
1042                 std_session_send_df_end(in->sdi);
1043
1044         return ret;
1045 }
1046
1047 static void cleanup(struct sr_input *in)
1048 {
1049         struct context *inc;
1050
1051         keep_header_for_reread(in);
1052
1053         inc = in->priv;
1054
1055         g_free(inc->termination);
1056         inc->termination = NULL;
1057         g_free(inc->datafeed_buffer);
1058         inc->datafeed_buffer = NULL;
1059 }
1060
1061 static int reset(struct sr_input *in)
1062 {
1063         struct context *inc = in->priv;
1064
1065         cleanup(in);
1066         inc->started = FALSE;
1067         g_string_truncate(in->buf, 0);
1068
1069         return SR_OK;
1070 }
1071
1072 enum option_index {
1073         OPT_SINGLE_COL,
1074         OPT_NUM_LOGIC,
1075         OPT_DELIM,
1076         OPT_FORMAT,
1077         OPT_COMMENT,
1078         OPT_RATE,
1079         OPT_FIRST_COL,
1080         OPT_HEADER,
1081         OPT_START,
1082         OPT_MAX,
1083 };
1084
1085 static struct sr_option options[] = {
1086         [OPT_SINGLE_COL] = { "single-column", "Single column", "Enable single-column mode, using the specified column (>= 1); 0: multi-col. mode", NULL, NULL },
1087         [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 },
1088         [OPT_DELIM] = { "delimiter", "Column delimiter", "The column delimiter (>= 1 characters)", NULL, NULL },
1089         [OPT_FORMAT] = { "format", "Data format (single-col. mode)", "The numeric format of the data (single-col. mode): bin, hex, oct", NULL, NULL },
1090         [OPT_COMMENT] = { "comment", "Comment character(s)", "The comment prefix character(s)", NULL, NULL },
1091         [OPT_RATE] = { "samplerate", "Samplerate (Hz)", "The sample rate (used during capture) in Hz", NULL, NULL },
1092         [OPT_FIRST_COL] = { "first-column", "First column", "The column number of the first channel (multi-col. mode)", NULL, NULL },
1093         [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 },
1094         [OPT_START] = { "startline", "Start line", "The line number at which to start processing samples (>= 1)", NULL, NULL },
1095         [OPT_MAX] = ALL_ZERO,
1096 };
1097
1098 static const struct sr_option *get_options(void)
1099 {
1100         GSList *l;
1101
1102         if (!options[0].def) {
1103                 options[OPT_SINGLE_COL].def = g_variant_ref_sink(g_variant_new_uint32(0));
1104                 options[OPT_NUM_LOGIC].def = g_variant_ref_sink(g_variant_new_uint32(0));
1105                 options[OPT_DELIM].def = g_variant_ref_sink(g_variant_new_string(","));
1106                 options[OPT_FORMAT].def = g_variant_ref_sink(g_variant_new_string("bin"));
1107                 l = NULL;
1108                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("bin")));
1109                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("hex")));
1110                 l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("oct")));
1111                 options[OPT_FORMAT].values = l;
1112                 options[OPT_COMMENT].def = g_variant_ref_sink(g_variant_new_string(";"));
1113                 options[OPT_RATE].def = g_variant_ref_sink(g_variant_new_uint64(0));
1114                 options[OPT_FIRST_COL].def = g_variant_ref_sink(g_variant_new_uint32(1));
1115                 options[OPT_HEADER].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
1116                 options[OPT_START].def = g_variant_ref_sink(g_variant_new_uint32(1));
1117         }
1118
1119         return options;
1120 }
1121
1122 SR_PRIV struct sr_input_module input_csv = {
1123         .id = "csv",
1124         .name = "CSV",
1125         .desc = "Comma-separated values",
1126         .exts = (const char*[]){"csv", NULL},
1127         .options = get_options,
1128         .init = init,
1129         .receive = receive,
1130         .end = end,
1131         .cleanup = cleanup,
1132         .reset = reset,
1133 };