X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Fcsv.c;h=0e68e39156f884eb20d2dd14bbead33c1f724b84;hb=329733d92c5004f0fe308eff26b9537fded2cdf3;hp=2db908547f39be6d5a6b898c2fe715951d8263c2;hpb=4f979115a4206bc1ff72c0319a340cbcad0f4b06;p=libsigrok.git diff --git a/src/input/csv.c b/src/input/csv.c index 2db90854..0e68e391 100644 --- a/src/input/csv.c +++ b/src/input/csv.c @@ -393,7 +393,7 @@ static int init(struct sr_input *in, GHashTable *options) struct context *inc; const char *s; - in->sdi = sr_dev_inst_new(0, 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")); @@ -429,11 +429,7 @@ static int init(struct sr_input *in, GHashTable *options) g_string_truncate(inc->comment, 0); } - s = g_variant_get_string(g_hash_table_lookup(options, "samplerate"), NULL); - if (sr_parse_sizestring(s, &inc->samplerate) != SR_OK) { - sr_err("Invalid samplerate '%s'.", s); - return SR_ERR_ARG; - } + inc->samplerate = g_variant_get_uint64(g_hash_table_lookup(options, "samplerate")); inc->first_channel = g_variant_get_int32(g_hash_table_lookup(options, "first-channel")); @@ -458,9 +454,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")) @@ -476,7 +472,6 @@ 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; @@ -510,7 +505,7 @@ static int initial_parse(const struct sr_input *in, GString *buf) } if (!lines[l]) { /* Not enough data for a proper line yet. */ - ret = SR_OK_CONTINUE; + ret = SR_ERR_NA; goto out; } @@ -561,9 +556,8 @@ static int initial_parse(const struct sr_input *in, GString *buf) if (inc->header && inc->multi_column_mode && strlen(columns[i])) 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, "%zu", i); + sr_channel_new(in->sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name->str); } g_string_free(channel_name, TRUE); @@ -587,17 +581,18 @@ 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; if (!(termination = get_line_termination(in->buf))) /* Don't have a full line yet. */ - return SR_OK_CONTINUE; + return SR_ERR_NA; if (!(p = g_strrstr_len(in->buf->str, in->buf->len, termination))) /* Don't have a full line yet. */ - return SR_OK_CONTINUE; + return SR_ERR_NA; len = p - in->buf->str - 1; new_buf = g_string_new_len(in->buf->str, len); g_string_append_c(new_buf, '\0'); @@ -614,7 +609,7 @@ static int initial_receive(const struct sr_input *in) return ret; } -static int receive(const struct sr_input *in, GString *buf) +static int process_buffer(struct sr_input *in) { struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; @@ -625,18 +620,8 @@ static int receive(const struct sr_input *in, GString *buf) int max_columns, ret, l; char *p, **lines, **columns; - g_string_append_len(in->buf, buf->str, buf->len); - inc = in->priv; - if (!inc->termination) { - ret = initial_receive(in); - if (ret == SR_OK_CONTINUE) - /* Not enough data yet. */ - return SR_OK_CONTINUE; - else if (ret != SR_OK) - return SR_ERR; - - inc->started = TRUE; + if (!inc->started) { std_session_send_df_header(in->sdi, LOG_PREFIX); if (inc->samplerate) { @@ -648,6 +633,8 @@ static int receive(const struct sr_input *in, GString *buf) sr_session_send(in->sdi, &packet); sr_config_free(src); } + + inc->started = TRUE; } if (!(p = g_strrstr_len(in->buf->str, in->buf->len, inc->termination))) @@ -663,6 +650,7 @@ static int receive(const struct sr_input *in, GString *buf) 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++; @@ -678,6 +666,13 @@ static int receive(const struct sr_input *in, GString *buf) 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; @@ -721,24 +716,61 @@ static int receive(const struct sr_input *in, GString *buf) g_strfreev(lines); g_string_erase(in->buf, 0, p - in->buf->str + 1); - return SR_OK; + return ret; } -static int cleanup(struct sr_input *in) +static int receive(struct sr_input *in, GString *buf) { struct context *inc; - struct sr_datafeed_packet packet; + int ret; + + g_string_append_len(in->buf, buf->str, buf->len); inc = in->priv; - if (!inc) + if (!inc->termination) { + if ((ret = initial_receive(in)) == SR_ERR_NA) + /* Not enough data yet. */ + return SR_OK; + else if (ret != SR_OK) + return SR_ERR; + + /* sdi is ready, notify frontend. */ + in->sdi_ready = TRUE; return SR_OK; + } + + ret = process_buffer(in); + + return ret; +} + +static int end(struct sr_input *in) +{ + struct context *inc; + struct sr_datafeed_packet packet; + int ret; + + if (in->sdi_ready) + ret = process_buffer(in); + else + ret = SR_OK; + inc = in->priv; if (inc->started) { /* End of stream. */ packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); } + return ret; +} + +static void cleanup(struct sr_input *in) +{ + struct context *inc; + + inc = in->priv; + if (inc->delimiter) g_string_free(inc->delimiter, TRUE); @@ -750,11 +782,6 @@ static int cleanup(struct sr_input *in) if (inc->sample_buffer) g_free(inc->sample_buffer); - - g_free(inc); - in->priv = NULL; - - return SR_OK; } static struct sr_option options[] = { @@ -778,7 +805,7 @@ static struct sr_option *get_options(void) options[2].def = g_variant_ref_sink(g_variant_new_string(",")); options[3].def = g_variant_ref_sink(g_variant_new_string("bin")); options[4].def = g_variant_ref_sink(g_variant_new_string(";")); - options[5].def = g_variant_ref_sink(g_variant_new_string("0")); + options[5].def = g_variant_ref_sink(g_variant_new_uint64(0)); options[6].def = g_variant_ref_sink(g_variant_new_int32(0)); options[7].def = g_variant_ref_sink(g_variant_new_boolean(FALSE)); options[8].def = g_variant_ref_sink(g_variant_new_int32(1)); @@ -791,10 +818,12 @@ SR_PRIV struct sr_input_module input_csv = { .id = "csv", .name = "CSV", .desc = "Comma-separated values", + .exts = (const char*[]){"csv", NULL}, .metadata = { SR_INPUT_META_MIMETYPE }, .options = get_options, .format_match = format_match, .init = init, .receive = receive, + .end = end, .cleanup = cleanup, };