Hi,

2015-08-20 17:55 keltezéssel, Marc-André Lureau írta:
[snip]
+static void
+sum_strlen(gpointer data, gpointer user_data)
+{
+    const char *str = data;
+    size_t *sum_len = user_data;
+
+    if (str) { /* skip NULLs */
+        *sum_len += strlen(str) + 1;
+    }
+}
+
+static void
+append_str(gpointer data, gpointer user_data)
+{
+    const char *str = data;
+    char *concat_str = user_data;
+
+    if (str) {
+        strcat(concat_str, str);
+        strcat(concat_str, ".");
+    }
+}
+
+/* lookup a name, using a fully qualified version */
  static GQueue *
-lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp)
+lookup_distinct(const OptsVisitor *ov, const char *name, char **out_key,
+                Error **errp)
  {
-    GQueue *list;
+    GQueue *list = NULL;
+    char *key;
+    size_t sum_len = strlen(name);
+
+    g_queue_foreach(ov->nested_names, sum_strlen, &sum_len);
+    key = g_malloc(sum_len+1);
+    key[0] = 0;
+    g_queue_foreach(ov->nested_names, append_str, key);
+    strcat(key, name);

Instead of using a GQueue, I think you could use a GArray, and use
g_strjoin() here.

Unfortunately g_strjoinv won't skip NULL pointers in the array (as it expects a NULL terminated array), but we will get structs with NULL name (the top level struct will be such one). And one can't simply say if (name) { g_array_append_val(...); } in opts_start_struct because we need to know somehow in opts_end_struct if we need to pop or not.

One way is to use NULL pointers because in that case we must pop, but g_strjoinv won't work. An alternate is to only push non-NULL elements into the array and have another bool array where we store if we need to pop or not. Not sure which one is cleaner.

Or maybe if it's guaranteed that only the top-level struct will have a NULL name, we can hack around by only pushing non-NULL elements and ignore empty array when popping.

Zoltan

Reply via email to