Glib::VariantBase ConfigKey::parse_string(string value) const { GVariant *variant; uint64_t p, q; switch (data_type()->id()) { case SR_T_UINT64: check(sr_parse_sizestring(value.c_str(), &p)); variant = g_variant_new_uint64(p); break; case SR_T_STRING: variant = g_variant_new_string(value.c_str()); break; case SR_T_BOOL: variant = g_variant_new_boolean(sr_parse_boolstring(value.c_str())); break; case SR_T_FLOAT: variant = g_variant_new_double(stod(value)); break; case SR_T_RATIONAL_PERIOD: check(sr_parse_period(value.c_str(), &p, &q)); variant = g_variant_new("(tt)", p, q); break; case SR_T_RATIONAL_VOLT: check(sr_parse_voltage(value.c_str(), &p, &q)); variant = g_variant_new("(tt)", p, q); break; case SR_T_INT32: variant = g_variant_new_int32(stoi(value)); break; default: throw Error(SR_ERR_BUG); } return Glib::VariantBase(variant, false); }
int opt_to_gvar(char *key, char *value, struct sr_config *src) { const struct sr_config_info *srci; double tmp_double, dlow, dhigh; uint64_t tmp_u64, p, q, low, high; GVariant *rational[2], *range[2]; gboolean tmp_bool; int ret; if (!(srci = sr_config_info_name_get(key))) { g_critical("Unknown device option '%s'.", (char *) key); return -1; } src->key = srci->key; if ((value == NULL) && (srci->datatype != SR_T_BOOL)) { g_critical("Option '%s' needs a value.", (char *)key); return -1; } ret = 0; switch (srci->datatype) { case SR_T_UINT64: ret = sr_parse_sizestring(value, &tmp_u64); if (ret != 0) break; src->data = g_variant_new_uint64(tmp_u64); break; case SR_T_INT32: ret = sr_parse_sizestring(value, &tmp_u64); if (ret != 0) break; src->data = g_variant_new_int32(tmp_u64); break; case SR_T_STRING: src->data = g_variant_new_string(value); break; case SR_T_BOOL: if (!value) tmp_bool = TRUE; else tmp_bool = sr_parse_boolstring(value); src->data = g_variant_new_boolean(tmp_bool); break; case SR_T_FLOAT: tmp_double = strtof(value, NULL); src->data = g_variant_new_double(tmp_double); break; case SR_T_RATIONAL_PERIOD: if ((ret = sr_parse_period(value, &p, &q)) != SR_OK) break; rational[0] = g_variant_new_uint64(p); rational[1] = g_variant_new_uint64(q); src->data = g_variant_new_tuple(rational, 2); break; case SR_T_RATIONAL_VOLT: if ((ret = sr_parse_voltage(value, &p, &q)) != SR_OK) break; rational[0] = g_variant_new_uint64(p); rational[1] = g_variant_new_uint64(q); src->data = g_variant_new_tuple(rational, 2); break; case SR_T_UINT64_RANGE: if (sscanf(value, "%"PRIu64"-%"PRIu64, &low, &high) != 2) { ret = -1; break; } else { range[0] = g_variant_new_uint64(low); range[1] = g_variant_new_uint64(high); src->data = g_variant_new_tuple(range, 2); } break; case SR_T_DOUBLE_RANGE: if (sscanf(value, "%lf-%lf", &dlow, &dhigh) != 2) { ret = -1; break; } else { range[0] = g_variant_new_double(dlow); range[1] = g_variant_new_double(dhigh); src->data = g_variant_new_tuple(range, 2); } break; default: ret = -1; } return ret; }
static int init(struct sr_input *in, const char *filename) { int res; struct context *ctx; const char *param; GIOStatus status; gsize i, term_pos; char probe_name[SR_MAX_PROBENAME_LEN + 1]; struct sr_probe *probe; char **columns; gsize num_columns; char *ptr; if (!(ctx = g_try_malloc0(sizeof(struct context)))) { sr_err("Context malloc failed."); return SR_ERR_MALLOC; } /* Create a virtual device. */ in->sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, NULL, NULL, NULL); in->internal = ctx; /* Set default samplerate. */ ctx->samplerate = 0; /* * Enable auto-detection of the number of probes in multi column mode * and enforce the specification of the number of probes in single * column mode. */ ctx->num_probes = 0; /* Set default delimiter. */ if (!(ctx->delimiter = g_string_new(","))) { sr_err("Delimiter malloc failed."); free_context(ctx); return SR_ERR_MALLOC; } /* * Set default comment prefix. Note that an empty comment prefix * disables removing of comments. */ if (!(ctx->comment = g_string_new(""))) { sr_err("Comment malloc failed."); free_context(ctx); return SR_ERR_MALLOC; } /* Enable multi column mode by default. */ ctx->multi_column_mode = TRUE; /* Use first column as default single column number. */ ctx->single_column = 0; /* * In multi column mode start parsing sample data at the first column * and in single column mode at the first bit. */ ctx->first_probe = 0; /* Start at the beginning of the file. */ ctx->start_line = 1; /* Disable the usage of the first line as header by default. */ ctx->header = FALSE; /* Set default format for single column mode. */ ctx->format = FORMAT_BIN; if (!(ctx->buffer = g_string_new(""))) { sr_err("Line buffer malloc failed."); free_context(ctx); return SR_ERR_MALLOC; } if (in->param) { if ((param = g_hash_table_lookup(in->param, "samplerate"))) { res = sr_parse_sizestring(param, &ctx->samplerate); if (res != SR_OK) { sr_err("Invalid samplerate: %s.", param); free_context(ctx); return SR_ERR_ARG; } } if ((param = g_hash_table_lookup(in->param, "numprobes"))) ctx->num_probes = g_ascii_strtoull(param, NULL, 10); if ((param = g_hash_table_lookup(in->param, "delimiter"))) { if (!strlen(param)) { sr_err("Delimiter must be at least one character."); free_context(ctx); return SR_ERR_ARG; } if (!g_ascii_strcasecmp(param, "\\t")) g_string_assign(ctx->delimiter, "\t"); else g_string_assign(ctx->delimiter, param); } if ((param = g_hash_table_lookup(in->param, "comment"))) g_string_assign(ctx->comment, param); if ((param = g_hash_table_lookup(in->param, "single-column"))) { ctx->single_column = g_ascii_strtoull(param, &ptr, 10); ctx->multi_column_mode = FALSE; if (param == ptr) { sr_err("Invalid single-colum number: %s.", param); free_context(ctx); return SR_ERR_ARG; } } if ((param = g_hash_table_lookup(in->param, "first-probe"))) ctx->first_probe = g_ascii_strtoull(param, NULL, 10); if ((param = g_hash_table_lookup(in->param, "startline"))) { ctx->start_line = g_ascii_strtoull(param, NULL, 10); if (ctx->start_line < 1) { sr_err("Invalid start line: %s.", param); free_context(ctx); return SR_ERR_ARG; } } if ((param = g_hash_table_lookup(in->param, "header"))) ctx->header = sr_parse_boolstring(param); if ((param = g_hash_table_lookup(in->param, "format"))) { if (!g_ascii_strncasecmp(param, "bin", 3)) { ctx->format = FORMAT_BIN; } else if (!g_ascii_strncasecmp(param, "hex", 3)) { ctx->format = FORMAT_HEX; } else if (!g_ascii_strncasecmp(param, "oct", 3)) { ctx->format = FORMAT_OCT; } else { sr_err("Invalid format: %s.", param); free_context(ctx); return SR_ERR; } } } if (ctx->multi_column_mode) ctx->first_column = ctx->first_probe; else ctx->first_column = ctx->single_column; if (!ctx->multi_column_mode && !ctx->num_probes) { sr_err("Number of probes needs to be specified in single column mode."); free_context(ctx); return SR_ERR; } if (!(ctx->channel = g_io_channel_new_file(filename, "r", NULL))) { sr_err("Input file '%s' could not be opened.", filename); free_context(ctx); return SR_ERR; } while (TRUE) { ctx->line_number++; status = g_io_channel_read_line_string(ctx->channel, ctx->buffer, &term_pos, NULL); if (status == G_IO_STATUS_EOF) { sr_err("Input file is empty."); free_context(ctx); return SR_ERR; } if (status != G_IO_STATUS_NORMAL) { sr_err("Error while reading line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } if (ctx->start_line > ctx->line_number) { sr_spew("Line %zu skipped.", ctx->line_number); continue; } /* Remove line termination character(s). */ g_string_truncate(ctx->buffer, term_pos); if (!ctx->buffer->len) { sr_spew("Blank line %zu skipped.", ctx->line_number); continue; } /* Remove trailing comment. */ strip_comment(ctx->buffer, ctx->comment); if (ctx->buffer->len) break; sr_spew("Comment-only line %zu skipped.", ctx->line_number); } /* * In order to determine the number of columns parse the current line * without limiting the number of columns. */ if (!(columns = parse_line(ctx, -1))) { sr_err("Error while parsing line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } num_columns = g_strv_length(columns); /* Ensure that the first column is not out of bounds. */ if (!num_columns) { sr_err("Column %zu in line %zu is out of bounds.", ctx->first_column, ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } if (ctx->multi_column_mode) { /* * Detect the number of probes in multi column mode * automatically if not specified. */ if (!ctx->num_probes) { ctx->num_probes = num_columns; sr_info("Number of auto-detected probes: %zu.", ctx->num_probes); } /* * Ensure that the number of probes does not exceed the number * of columns in multi column mode. */ if (num_columns < ctx->num_probes) { sr_err("Not enough columns for desired number of probes in line %zu.", ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } } for (i = 0; i < ctx->num_probes; i++) { if (ctx->header && ctx->multi_column_mode && strlen(columns[i])) snprintf(probe_name, sizeof(probe_name), "%s", columns[i]); else snprintf(probe_name, sizeof(probe_name), "%zu", i); probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, probe_name); if (!probe) { sr_err("Probe creation failed."); free_context(ctx); g_strfreev(columns); return SR_ERR; } in->sdi->probes = g_slist_append(in->sdi->probes, probe); } g_strfreev(columns); /* * Calculate the minimum buffer size to store the sample data of the * probes. */ ctx->sample_buffer_size = (ctx->num_probes + 7) >> 3; if (!(ctx->sample_buffer = g_try_malloc(ctx->sample_buffer_size))) { sr_err("Sample buffer malloc failed."); free_context(ctx); return SR_ERR_MALLOC; } return SR_OK; }
static int set_dev_options(struct sr_dev *dev, GHashTable *args) { GHashTableIter iter; gpointer key, value; int ret, i; float tmp_float; uint64_t tmp_u64; struct sr_rational tmp_rat; gboolean tmp_bool; gboolean found; g_hash_table_iter_init(&iter, args); while (g_hash_table_iter_next(&iter, &key, &value)) { found = FALSE; for (i = 0; sr_hwcap_options[i].hwcap; i++) { if (strcmp(sr_hwcap_options[i].shortname, key)) continue; if ((value == NULL) && (sr_hwcap_options[i].type != SR_T_BOOL)) { g_critical("Option '%s' needs a value.", (char *)key); return SR_ERR; } found = TRUE; switch (sr_hwcap_options[i].type) { case SR_T_UINT64: ret = sr_parse_sizestring(value, &tmp_u64); if (ret != SR_OK) break; ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, &tmp_u64); break; case SR_T_CHAR: ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, value); break; case SR_T_BOOL: if (!value) tmp_bool = TRUE; else tmp_bool = sr_parse_boolstring(value); ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, GINT_TO_POINTER(tmp_bool)); break; case SR_T_FLOAT: tmp_float = strtof(value, NULL); ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, &tmp_float); break; case SR_T_RATIONAL_PERIOD: if ((ret = sr_parse_period(value, &tmp_rat)) != SR_OK) break; ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, &tmp_rat); break; case SR_T_RATIONAL_VOLT: if ((ret = sr_parse_voltage(value, &tmp_rat)) != SR_OK) break; ret = dev->driver->dev_config_set(dev->driver_index, sr_hwcap_options[i].hwcap, &tmp_rat); break; default: ret = SR_ERR; } if (ret != SR_OK) { g_critical("Failed to set device option '%s'.", (char *)key); return ret; } else break; } if (!found) { g_critical("Unknown device option '%s'.", (char *) key); return SR_ERR; } } return SR_OK; }