]> sigrok.org Git - libsigrok.git/commitdiff
output: Move option checks to the wrapper.
authorBert Vermeulen <redacted>
Sat, 2 Aug 2014 23:16:03 +0000 (01:16 +0200)
committerBert Vermeulen <redacted>
Sat, 2 Aug 2014 23:16:03 +0000 (01:16 +0200)
Output modules are now guaranteed:
  - Every option is always given, with the default value if not supplied
    by the user, and is the right GVariantType.
  - No invalid options are ever passed.

src/output/ascii.c
src/output/bits.c
src/output/hex.c
src/output/output.c
src/output/wav.c

index 45abb656447433a01e6ecc65d08ceeccb5971280..562d02551b4aff4a7ea5ac965fb380e243c77cd9 100644 (file)
@@ -30,7 +30,7 @@
 
 struct context {
        unsigned int num_enabled_channels;
-       int samples_per_line;
+       int spl;
        int bit_cnt;
        int spl_cnt;
        int trigger;
@@ -49,37 +49,15 @@ static int init(struct sr_output *o, GHashTable *options)
        struct context *ctx;
        struct sr_channel *ch;
        GSList *l;
-       GHashTableIter iter;
-       gpointer key, value;
        unsigned int i, j;
-       uint32_t spl;
 
        if (!o || !o->sdi)
                return SR_ERR_ARG;
 
-       spl = DEFAULT_SAMPLES_PER_LINE;
-       if (options) {
-               g_hash_table_iter_init(&iter, options);
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       if (!strcmp(key, "width")) {
-                               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
-                                       sr_err("Invalid type for 'width' option.");
-                                       return SR_ERR_ARG;
-                               }
-                               if (!(spl = g_variant_get_uint32(value))) {
-                                       sr_err("Invalid width.");
-                                       return SR_ERR_ARG;
-                               }
-                       } else {
-                               sr_err("Unknown option '%s'.", key);
-                       }
-               }
-       }
-
        ctx = g_malloc0(sizeof(struct context));
        o->priv = ctx;
        ctx->trigger = -1;
-       ctx->samples_per_line = spl;
+       ctx->spl = g_variant_get_uint32(g_hash_table_lookup(options, "width"));
 
        for (l = o->sdi->channels; l; l = l->next) {
                ch = l->data;
@@ -199,7 +177,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                }
                                g_string_append_c(ctx->lines[j], c);
 
-                               if (ctx->spl_cnt == ctx->samples_per_line) {
+                               if (ctx->spl_cnt == ctx->spl) {
                                        /* Flush line buffers. */
                                        g_string_append_len(*out, ctx->lines[j]->str, ctx->lines[j]->len);
                                        g_string_append_c(*out, '\n');
@@ -211,7 +189,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                        g_string_printf(ctx->lines[j], "%s:", ctx->channel_names[j]);
                                }
                        }
-                       if (ctx->spl_cnt == ctx->samples_per_line)
+                       if (ctx->spl_cnt == ctx->spl)
                                /* Line buffers were already flushed. */
                                ctx->spl_cnt = 0;
                        memcpy(ctx->prev_sample, logic->data + i, logic->unitsize);
index 22212fd5cd205c088884ce396be49882ada6c4f2..728ff2ffb3140c608f85e11492ed28a5f736eb6d 100644 (file)
@@ -29,7 +29,7 @@
 
 struct context {
        unsigned int num_enabled_channels;
-       int samples_per_line;
+       int spl;
        int spl_cnt;
        int trigger;
        uint64_t samplerate;
@@ -44,37 +44,15 @@ static int init(struct sr_output *o, GHashTable *options)
        struct context *ctx;
        struct sr_channel *ch;
        GSList *l;
-       GHashTableIter iter;
-       gpointer key, value;
        unsigned int i, j;
-       uint32_t spl;
 
        if (!o || !o->sdi)
                return SR_ERR_ARG;
 
-       spl = DEFAULT_SAMPLES_PER_LINE;
-       if (options) {
-               g_hash_table_iter_init(&iter, options);
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       if (!strcmp(key, "width")) {
-                               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
-                                       sr_err("Invalid type for 'width' option.");
-                                       return SR_ERR_ARG;
-                               }
-                               if (!(spl = g_variant_get_uint32(value))) {
-                                       sr_err("Invalid width.");
-                                       return SR_ERR_ARG;
-                               }
-                       } else {
-                               sr_err("Unknown option '%s'.", key);
-                       }
-               }
-       }
-
        ctx = g_malloc0(sizeof(struct context));
        o->priv = ctx;
        ctx->trigger = -1;
-       ctx->samples_per_line = spl;
+       ctx->spl = g_variant_get_uint32(g_hash_table_lookup(options, "width"));
 
        for (l = o->sdi->channels; l; l = l->next) {
                ch = l->data;
@@ -184,7 +162,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                c = (*p & (1 << (idx % 8))) ? '1' : '0';
                                g_string_append_c(ctx->lines[j], c);
 
-                               if (ctx->spl_cnt == ctx->samples_per_line) {
+                               if (ctx->spl_cnt == ctx->spl) {
                                        /* Flush line buffers. */
                                        g_string_append_len(*out, ctx->lines[j]->str, ctx->lines[j]->len);
                                        g_string_append_c(*out, '\n');
@@ -199,7 +177,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                        g_string_append_c(ctx->lines[j], ' ');
                                }
                        }
-                       if (ctx->spl_cnt == ctx->samples_per_line)
+                       if (ctx->spl_cnt == ctx->spl)
                                /* Line buffers were already flushed. */
                                ctx->spl_cnt = 0;
                }
index ab4ce2d37cbc3a485652010f6e9cf53d28c6fc4c..1d4196381d3a706440eb1b52c468c6c20d6e4703 100644 (file)
@@ -29,7 +29,7 @@
 
 struct context {
        unsigned int num_enabled_channels;
-       int samples_per_line;
+       int spl;
        int bit_cnt;
        int spl_cnt;
        int trigger;
@@ -47,38 +47,15 @@ static int init(struct sr_output *o, GHashTable *options)
        struct context *ctx;
        struct sr_channel *ch;
        GSList *l;
-       GHashTableIter iter;
-       gpointer key, value;
        unsigned int i, j;
-       uint32_t spl;
 
        if (!o || !o->sdi)
                return SR_ERR_ARG;
 
-       spl = DEFAULT_SAMPLES_PER_LINE;
-       if (options) {
-               g_hash_table_iter_init(&iter, options);
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       if (!strcmp(key, "width")) {
-                               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
-                                       sr_err("Invalid type for 'width' option.");
-                                       return SR_ERR_ARG;
-                               }
-                               if (!(spl = g_variant_get_uint32(value))) {
-                                       sr_err("Invalid width.");
-                                       return SR_ERR_ARG;
-                               }
-                       } else {
-                               sr_err("Unknown option '%s'.", key);
-                               return SR_ERR_ARG;
-                       }
-               }
-       }
-
        ctx = g_malloc0(sizeof(struct context));
        o->priv = ctx;
        ctx->trigger = -1;
-       ctx->samples_per_line = spl;
+       ctx->spl = g_variant_get_uint32(g_hash_table_lookup(options, "width"));
 
        for (l = o->sdi->channels; l; l = l->next) {
                ch = l->data;
@@ -198,7 +175,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                        ctx->sample_buf[j] = 0;
                                }
 
-                               if (ctx->spl_cnt == ctx->samples_per_line) {
+                               if (ctx->spl_cnt == ctx->spl) {
                                        /* Flush line buffers. */
                                        g_string_append_len(*out, ctx->lines[j]->str, ctx->lines[j]->len);
                                        g_string_append_c(*out, '\n');
@@ -210,7 +187,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                                        g_string_printf(ctx->lines[j], "%s:", ctx->channel_names[j]);
                                }
                        }
-                       if (ctx->spl_cnt == ctx->samples_per_line)
+                       if (ctx->spl_cnt == ctx->spl)
                                /* Line buffers were already flushed. */
                                ctx->spl_cnt = 0;
                }
index e0bb2f1d7b1a1a3361fdd850fdfdcd2f359f46cf..e84183913cef7723a887b9593a260268ed70e83c 100644 (file)
@@ -212,15 +212,59 @@ SR_API const struct sr_output *sr_output_new(const struct sr_output_module *o,
                GHashTable *options, const struct sr_dev_inst *sdi)
 {
        struct sr_output *op;
+       struct sr_option *mod_opts;
+       const GVariantType *gvt;
+       GHashTable *new_opts;
+       GHashTableIter iter;
+       gpointer key, value;
+       int i;
 
        op = g_malloc(sizeof(struct sr_output));
        op->module = o;
        op->sdi = sdi;
 
-       if (op->module->init && op->module->init(op, options) != SR_OK) {
+       if (options) {
+               new_opts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+                               (GDestroyNotify)g_variant_unref);
+               mod_opts = o->options();
+               for (i = 0; mod_opts[i].id; i++) {
+                       if (g_hash_table_lookup_extended(options, mod_opts[i].id,
+                                       &key, &value)) {
+                               /* Option not given: insert the default value. */
+                               gvt = g_variant_get_type(mod_opts[i].def);
+                               if (!g_variant_is_of_type(value, gvt)) {
+                                       sr_err("Invalid type for '%s' option.", key);
+                                       g_free(op);
+                                       return NULL;
+                               }
+                               g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
+                                               g_variant_ref(value));
+                       } else {
+                               /* Pass option along. */
+                               g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
+                                               g_variant_ref(mod_opts[i].def));
+                       }
+               }
+
+               /* Make sure no invalid options were given. */
+               g_hash_table_iter_init(&iter, options);
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       if (!g_hash_table_lookup(new_opts, key)) {
+                               sr_err("Output module '%s' has no option '%s'", o->id, key);
+                               g_hash_table_destroy(new_opts);
+                               g_free(op);
+                               return NULL;
+                       }
+               }
+       } else
+               new_opts = NULL;
+
+       if (op->module->init && op->module->init(op, new_opts) != SR_OK) {
+               g_hash_table_destroy(new_opts);
                g_free(op);
                op = NULL;
        }
+       g_hash_table_destroy(new_opts);
 
        return op;
 }
index 9bf9843d18cd9333fbf01e26698a68c8f1b8da7d..add2d99996672304a029191b036280db98b4705d 100644 (file)
@@ -91,28 +91,10 @@ static int init(struct sr_output *o, GHashTable *options)
        struct out_context *outc;
        struct sr_channel *ch;
        GSList *l;
-       GHashTableIter iter;
-       gpointer key, value;
 
        outc = g_malloc0(sizeof(struct out_context));
        o->priv = outc;
-
-       outc->scale = 0.0;
-       if (options) {
-               g_hash_table_iter_init(&iter, options);
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       if (!strcmp(key, "scale")) {
-                               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)) {
-                                       sr_err("Invalid type for 'scale' option.");
-                                       return SR_ERR_ARG;
-                               }
-                               outc->scale = g_variant_get_double(value);
-                       } else {
-                               sr_err("Unknown option '%s'.", key);
-                               return SR_ERR_ARG;
-                       }
-               }
-       }
+       outc->scale = g_variant_get_double(g_hash_table_lookup(options, "scale"));
 
        for (l = o->sdi->channels; l; l = l->next) {
                ch = l->data;
@@ -359,7 +341,7 @@ static struct sr_option options[] = {
 static struct sr_option *get_options(void)
 {
        if (!options[0].def) {
-               options[0].def = g_variant_new_double(0);
+               options[0].def = g_variant_new_double(0.0);
                g_variant_ref_sink(options[0].def);
        }