]> sigrok.org Git - libsigrok.git/commitdiff
input/vcd: add channel list checks for file re-read
authorGerhard Sittig <redacted>
Sat, 13 Oct 2018 09:06:16 +0000 (11:06 +0200)
committerUwe Hermann <redacted>
Sat, 13 Oct 2018 13:17:51 +0000 (15:17 +0200)
Keep (part of) previous results around when the VCD input module gets
reset, and check the header of the next import against previous runs to
avoid issues in applications. This addresses the VCD specific part of
bug #1241, and resolves the remaining part of bug #1306.

src/input/vcd.c

index 95092cb2e5bf5363697a933051ad4cb4bf1dc391..e3c2347ac0875ff6f44f99f000077a691ce3a455 100644 (file)
@@ -85,6 +85,7 @@ struct context {
        size_t samples_in_buffer;
        uint8_t *buffer;
        uint8_t *current_levels;
+       GSList *prev_sr_channels;
 };
 
 struct vcd_channel {
@@ -175,6 +176,56 @@ static void remove_empty_parts(gchar **parts)
        *dest = NULL;
 }
 
+/*
+ * Keep track of a previously created channel list, in preparation of
+ * re-reading the input file. Gets called from reset()/cleanup() paths.
+ */
+static void keep_header_for_reread(const struct sr_input *in)
+{
+       struct context *inc;
+
+       inc = in->priv;
+       g_slist_free_full(inc->prev_sr_channels, sr_channel_free_cb);
+       inc->prev_sr_channels = in->sdi->channels;
+       in->sdi->channels = NULL;
+}
+
+/*
+ * Check whether the input file is being re-read, and refuse operation
+ * when essential parameters of the acquisition have changed in ways
+ * that are unexpected to calling applications. Gets called after the
+ * file header got parsed (again).
+ *
+ * Changing the channel list across re-imports of the same file is not
+ * supported, by design and for valid reasons, see bug #1215 for details.
+ * Users are expected to start new sessions when they change these
+ * essential parameters in the acquisition's setup. When we accept the
+ * re-read file, then make sure to keep using the previous channel list,
+ * applications may still reference them.
+ */
+static int check_header_in_reread(const struct sr_input *in)
+{
+       struct context *inc;
+
+       if (!in)
+               return FALSE;
+       inc = in->priv;
+       if (!inc)
+               return FALSE;
+       if (!inc->prev_sr_channels)
+               return TRUE;
+
+       if (sr_channel_lists_differ(inc->prev_sr_channels, in->sdi->channels)) {
+               sr_err("Channel list change not supported for file re-read.");
+               return FALSE;
+       }
+       g_slist_free_full(in->sdi->channels, sr_channel_free_cb);
+       in->sdi->channels = inc->prev_sr_channels;
+       inc->prev_sr_channels = NULL;
+
+       return TRUE;
+}
+
 /*
  * Parse VCD header to get values for context structure.
  * The context structure should be zeroed before calling this.
@@ -265,6 +316,8 @@ static gboolean parse_header(const struct sr_input *in, GString *buf)
        inc->current_levels = g_malloc0(inc->bytes_per_sample);
 
        inc->got_header = status;
+       if (status)
+               status = check_header_in_reread(in);
 
        return status;
 }
@@ -618,8 +671,10 @@ static void cleanup(struct sr_input *in)
        struct context *inc;
 
        inc = in->priv;
+       keep_header_for_reread(in);
        g_slist_free_full(inc->channels, free_channel);
        inc->channels = NULL;
+
        g_free(inc->buffer);
        inc->buffer = NULL;
        g_free(inc->current_levels);