X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Fcsv.c;h=984a58c7d9753ae1d11869d829ad2e5507e9d686;hb=3be42bc22f8b36599a448273c12a76d3e0f7a940;hp=cc721baf2427a3e89c3c50d12bf196569dfafe59;hpb=60107497fed4b307a7d64d23e3d8d6137f64c4e4;p=libsigrok.git diff --git a/src/input/csv.c b/src/input/csv.c index cc721baf..984a58c7 100644 --- a/src/input/csv.c +++ b/src/input/csv.c @@ -17,10 +17,11 @@ * along with this program. If not, see . */ +#include #include #include #include -#include "libsigrok.h" +#include #include "libsigrok-internal.h" #define LOG_PREFIX "input/csv" @@ -80,7 +81,7 @@ struct context { uint64_t samplerate; /* Number of channels. */ - gsize num_channels; + unsigned int num_channels; /* Column delimiter character(s). */ GString *delimiter; @@ -95,23 +96,23 @@ struct context { gboolean multi_column_mode; /* Column number of the sample data in single column mode. */ - gsize single_column; + unsigned int single_column; /* * Number of the first column to parse. Equivalent to the number of the * first channel in multi column mode and the single column number in * single column mode. */ - gsize first_column; + unsigned int first_column; /* * Column number of the first channel in multi column mode and position of * the bit for the first channel in single column mode. */ - gsize first_channel; + unsigned int first_channel; /* Line number to start processing. */ - gsize start_line; + size_t start_line; /* * Determines if the first line should be treated as header and used for @@ -123,26 +124,15 @@ struct context { int format; /* Size of the sample buffer. */ - gsize sample_buffer_size; + size_t sample_buffer_size; /* Buffer to store sample data. */ uint8_t *sample_buffer; /* Current line number. */ - gsize line_number; + size_t line_number; }; -static int format_match(GHashTable *metadata) -{ - char *buf; - - buf = g_hash_table_lookup(metadata, GINT_TO_POINTER(SR_INPUT_META_MIMETYPE)); - if (!strcmp(buf, "text/csv")) - return SR_OK; - - return SR_ERR; -} - static void strip_comment(char *buf, const GString *prefix) { char *ptr; @@ -161,7 +151,7 @@ static int parse_binstr(const char *str, struct context *inc) length = strlen(str); if (!length) { - sr_err("Column %zu in line %zu is empty.", inc->single_column, + sr_err("Column %u in line %zu is empty.", inc->single_column, inc->line_number); return SR_ERR; } @@ -175,7 +165,7 @@ static int parse_binstr(const char *str, struct context *inc) if (str[length - i - 1] == '1') { inc->sample_buffer[j / 8] |= (1 << (j % 8)); } else if (str[length - i - 1] != '0') { - sr_err("Invalid value '%s' in column %zu in line %zu.", + sr_err("Invalid value '%s' in column %u in line %zu.", str, inc->single_column, inc->line_number); return SR_ERR; } @@ -193,7 +183,7 @@ static int parse_hexstr(const char *str, struct context *inc) length = strlen(str); if (!length) { - sr_err("Column %zu in line %zu is empty.", inc->single_column, + sr_err("Column %u in line %zu is empty.", inc->single_column, inc->line_number); return SR_ERR; } @@ -208,7 +198,7 @@ static int parse_hexstr(const char *str, struct context *inc) c = str[length - i - 1]; if (!g_ascii_isxdigit(c)) { - sr_err("Invalid value '%s' in column %zu in line %zu.", + sr_err("Invalid value '%s' in column %u in line %zu.", str, inc->single_column, inc->line_number); return SR_ERR; } @@ -237,7 +227,7 @@ static int parse_octstr(const char *str, struct context *inc) length = strlen(str); if (!length) { - sr_err("Column %zu in line %zu is empty.", inc->single_column, + sr_err("Column %u in line %zu is empty.", inc->single_column, inc->line_number); return SR_ERR; } @@ -252,7 +242,7 @@ static int parse_octstr(const char *str, struct context *inc) c = str[length - i - 1]; if (c < '0' || c > '7') { - sr_err("Invalid value '%s' in column %zu in line %zu.", + sr_err("Invalid value '%s' in column %u in line %zu.", str, inc->single_column, inc->line_number); return SR_ERR; } @@ -351,7 +341,7 @@ static int parse_single_column(const char *column, struct context *inc) res = SR_ERR; - switch(inc->format) { + switch (inc->format) { case FORMAT_BIN: res = parse_binstr(column, inc); break; @@ -393,7 +383,7 @@ static int init(struct sr_input *in, GHashTable *options) struct context *inc; const char *s; - in->sdi = sr_dev_inst_new(SR_ST_ACTIVE, NULL, NULL, NULL); + in->sdi = g_malloc0(sizeof(struct sr_dev_inst)); in->priv = inc = g_malloc0(sizeof(struct context)); inc->single_column = g_variant_get_int32(g_hash_table_lookup(options, "single-column")); @@ -437,7 +427,7 @@ static int init(struct sr_input *in, GHashTable *options) inc->start_line = g_variant_get_int32(g_hash_table_lookup(options, "startline")); if (inc->start_line < 1) { - sr_err("Invalid start line %d.", inc->start_line); + sr_err("Invalid start line %zu.", inc->start_line); return SR_ERR_ARG; } @@ -454,9 +444,9 @@ static int init(struct sr_input *in, GHashTable *options) return SR_OK; } -static char *get_line_termination(GString *buf) +static const char *get_line_termination(GString *buf) { - char *term; + const char *term; term = NULL; if (g_strstr_len(buf->str, buf->len, "\r\n")) @@ -472,10 +462,9 @@ static char *get_line_termination(GString *buf) static int initial_parse(const struct sr_input *in, GString *buf) { struct context *inc; - struct sr_channel *ch; GString *channel_name; - gsize num_columns, l, i; - unsigned int line_number; + unsigned int num_columns, i; + size_t line_number, l; int ret; char **lines, **columns; @@ -523,7 +512,7 @@ static int initial_parse(const struct sr_input *in, GString *buf) /* Ensure that the first column is not out of bounds. */ if (!num_columns) { - sr_err("Column %zu in line %zu is out of bounds.", + sr_err("Column %u in line %zu is out of bounds.", inc->first_column, line_number); ret = SR_ERR; goto out; @@ -536,7 +525,7 @@ static int initial_parse(const struct sr_input *in, GString *buf) */ if (!inc->num_channels) { inc->num_channels = num_columns; - sr_dbg("Number of auto-detected channels: %zu.", + sr_dbg("Number of auto-detected channels: %u.", inc->num_channels); } @@ -554,12 +543,11 @@ static int initial_parse(const struct sr_input *in, GString *buf) channel_name = g_string_sized_new(64); for (i = 0; i < inc->num_channels; i++) { - if (inc->header && inc->multi_column_mode && strlen(columns[i])) + if (inc->header && inc->multi_column_mode && columns[i][0] != '\0') g_string_assign(channel_name, columns[i]); else - g_string_printf(channel_name, "%lu", i); - ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name->str); - in->sdi->channels = g_slist_append(in->sdi->channels, ch); + g_string_printf(channel_name, "%u", i); + sr_channel_new(in->sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name->str); } g_string_free(channel_name, TRUE); @@ -583,7 +571,8 @@ static int initial_receive(const struct sr_input *in) struct context *inc; GString *new_buf; int len, ret; - char *termination, *p; + char *p; + const char *termination; inc = in->priv; @@ -632,6 +621,7 @@ static int process_buffer(struct sr_input *in) src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); + g_slist_free(meta.config); sr_config_free(src); } @@ -651,6 +641,7 @@ static int process_buffer(struct sr_input *in) else max_columns = 1; + ret = SR_OK; lines = g_strsplit_set(in->buf->str, "\r\n", 0); for (l = 0; lines[l]; l++) { inc->line_number++; @@ -666,13 +657,20 @@ static int process_buffer(struct sr_input *in) continue; } + /* Skip the header line, its content was used as the channel names. */ + if (inc->header) { + sr_spew("Header line %zu skipped.", inc->line_number); + inc->header = FALSE; + continue; + } + if (!(columns = parse_line(lines[l], inc, max_columns))) { sr_err("Error while parsing line %zu.", inc->line_number); return SR_ERR; } num_columns = g_strv_length(columns); if (!num_columns) { - sr_err("Column %zu in line %zu is out of bounds.", + sr_err("Column %u in line %zu is out of bounds.", inc->first_column, inc->line_number); g_strfreev(columns); return SR_ERR; @@ -740,7 +738,6 @@ static int receive(struct sr_input *in, GString *buf) static int end(struct sr_input *in) { struct context *inc; - struct sr_datafeed_packet packet; int ret; if (in->sdi_ready) @@ -749,11 +746,8 @@ static int end(struct sr_input *in) ret = SR_OK; inc = in->priv; - if (inc->started) { - /* End of stream. */ - packet.type = SR_DF_END; - sr_session_send(in->sdi, &packet); - } + if (inc->started) + std_session_send_df_end(in->sdi, LOG_PREFIX); return ret; } @@ -770,11 +764,8 @@ static void cleanup(struct sr_input *in) if (inc->comment) g_string_free(inc->comment, TRUE); - if (inc->termination) - g_free(inc->termination); - - if (inc->sample_buffer) - g_free(inc->sample_buffer); + g_free(inc->termination); + g_free(inc->sample_buffer); } static struct sr_option options[] = { @@ -790,7 +781,7 @@ static struct sr_option options[] = { ALL_ZERO }; -static struct sr_option *get_options(void) +static const struct sr_option *get_options(void) { if (!options[0].def) { options[0].def = g_variant_ref_sink(g_variant_new_int32(0)); @@ -811,9 +802,8 @@ SR_PRIV struct sr_input_module input_csv = { .id = "csv", .name = "CSV", .desc = "Comma-separated values", - .metadata = { SR_INPUT_META_MIMETYPE }, + .exts = (const char*[]){"csv", NULL}, .options = get_options, - .format_match = format_match, .init = init, .receive = receive, .end = end,