From 5066c94d4aa1c12e6e7133c431c4911ca17a758c Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Wed, 27 May 2015 13:21:01 +0200
Subject: [PATCH] Renaming registry where result is only depending on final
 name

---
 lib/c/2014/Makefile                           |   5 +
 lib/c/2014/labcomm2014_renaming.h             |  17 ++
 lib/c/2014/labcomm2014_renaming_registry.c    | 184 ++++++++++++++++++
 .../test/test_labcomm_renaming_registry.c     |  44 +++++
 4 files changed, 250 insertions(+)
 create mode 100644 lib/c/2014/labcomm2014_renaming_registry.c
 create mode 100644 lib/c/2014/test/test_labcomm_renaming_registry.c

diff --git a/lib/c/2014/Makefile b/lib/c/2014/Makefile
index 741f5e3..b18a9e4 100644
--- a/lib/c/2014/Makefile
+++ b/lib/c/2014/Makefile
@@ -24,6 +24,7 @@ OBJS=labcomm$(VERSION).o \
      labcomm$(VERSION)_fd_writer.o \
      labcomm$(VERSION)_pthread_scheduler.o \
      labcomm$(VERSION)_renaming.o \
+     labcomm$(VERSION)_renaming_registry.o \
      labcomm$(VERSION)_renaming_encoder.o \
      labcomm$(VERSION)_renaming_decoder.o
 
@@ -50,6 +51,7 @@ TESTS=test_labcomm_basic_type_encoding \
       test_labcomm \
       test_labcomm_pthread_scheduler \
       test_labcomm_copy \
+      test_labcomm_renaming_registry \
       test_labcomm_renaming_encoder \
       test_labcomm_renaming_decoder
 #FIXME: test_labcomm_errors
@@ -175,6 +177,9 @@ $(TEST_DIR)/gen/test_labcomm_copy: \
 	$(TEST_DIR)/gen/test_sample.o \
 	$(TEST_DIR)/gen/more_types.o
 
+$(TEST_DIR)/gen/test_labcomm_renaming_registry: \
+	$(TEST_DIR)/gen/generated_encoding.o
+
 $(TEST_DIR)/gen/test_labcomm_renaming_encoder: \
 	$(TEST_DIR)/gen/generated_encoding.o
 
diff --git a/lib/c/2014/labcomm2014_renaming.h b/lib/c/2014/labcomm2014_renaming.h
index 903010e..296e9e1 100644
--- a/lib/c/2014/labcomm2014_renaming.h
+++ b/lib/c/2014/labcomm2014_renaming.h
@@ -31,4 +31,21 @@ char *labcomm2014_renaming_prefix(struct labcomm2014_memory *m,
 char *labcomm2014_renaming_suffix(struct labcomm2014_memory *m,
                                   char *name, void *context);
 
+struct labcomm2014_renaming_registry;
+struct labcomm2014_renaming_registry *labcomm2014_renaming_registry_new(
+  struct labcomm2014_error_handler *error,
+  struct labcomm2014_memory *memory,
+  struct labcomm2014_scheduler *scheduler);
+
+/* semi private */
+
+struct labcomm2014_renaming_rename *labcomm2014_renaming_rename_new(
+  struct labcomm2014_renaming_registry *r,
+  const struct labcomm2014_signature *signature,
+  char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
+  void *context);
+
+const struct labcomm2014_signature *labcomm2014_renaming_rename_signature(
+  struct labcomm2014_renaming_rename *rename);
+
 #endif
diff --git a/lib/c/2014/labcomm2014_renaming_registry.c b/lib/c/2014/labcomm2014_renaming_registry.c
new file mode 100644
index 0000000..cbf82f5
--- /dev/null
+++ b/lib/c/2014/labcomm2014_renaming_registry.c
@@ -0,0 +1,184 @@
+/*
+  labcomm2014_renaming_registry.c -- renaming registry
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm2014.h"
+#include "labcomm2014_private.h"
+
+struct alias {
+  int usecount;
+  struct alias *next;
+  char *name;
+};
+
+struct registry {
+  struct registry *base; /* NULL if this is the base type */
+  const struct labcomm2014_signature *signature;
+  struct labcomm2014_renaming_rename *rename;
+};
+
+struct labcomm2014_renaming_rename {
+  struct labcomm2014_renaming_rename *next;
+  int use_count;
+  struct registry *base;
+  struct labcomm2014_signature signature;
+  struct labcomm2014_signature_data s_treedata[2];
+};
+
+struct labcomm2014_renaming_registry {
+  struct labcomm2014_error_handler *error;
+  struct labcomm2014_memory *memory;
+  struct labcomm2014_scheduler *scheduler;
+  LABCOMM_SIGNATURE_ARRAY_DEF(registry, struct registry *);
+};
+
+struct labcomm2014_renaming_registry *labcomm2014_renaming_registry_new(
+  struct labcomm2014_error_handler *error,
+  struct labcomm2014_memory *memory,
+  struct labcomm2014_scheduler *scheduler)
+{
+  struct labcomm2014_renaming_registry *result;
+  result = labcomm2014_memory_alloc(memory, 0, sizeof(*result));
+  if (! result) {
+    return NULL;
+  } else {
+    result->error = error;
+    result->memory = memory;
+    result->scheduler = scheduler;
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->registry, struct registry *);
+    return result;
+  }
+}
+
+static struct registry *registry_new(
+  struct labcomm2014_renaming_registry *r,
+  const struct labcomm2014_signature *signature,
+  struct registry *base)
+{
+  /* Called with registry locked */
+  struct registry *result = NULL;
+  struct registry **registry;
+  int index;
+
+  index = labcomm2014_get_local_index(signature);
+  if (index <= 0) {
+    labcomm2014_error_warning(r->error,
+                              LABCOMM2014_ERROR_MEMORY,
+                              "Signature has no index: %s\n",
+                              signature->name);
+    goto out;
+  }
+  registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
+                                          struct registry *, index);
+  if (registry == NULL) { goto out; }
+  if (*registry != NULL) {
+    result = *registry;
+  } else {
+    /* Add previosly unknown sample to registry */
+    registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
+                                          struct registry *, index);
+    if (registry == NULL) { goto out; }
+    result = labcomm2014_memory_alloc(r->memory, 0, sizeof(*result));
+    if (result == NULL) { goto out; }
+    result->base = base;
+    result->signature = signature;
+    result->rename = NULL;
+    *registry = result;
+  }
+out:
+  return result;
+}
+
+struct labcomm2014_renaming_rename *labcomm2014_renaming_rename_new(
+  struct labcomm2014_renaming_registry *r,
+  const struct labcomm2014_signature *signature,
+  char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
+  void *context)
+{
+  struct labcomm2014_renaming_rename *result = NULL;
+
+  labcomm2014_scheduler_data_lock(r->scheduler);
+  {
+    char *new_name = NULL;
+    static struct registry *base, *renamed;
+    struct labcomm2014_renaming_rename **l;
+
+    base = registry_new(r, signature, NULL);
+    if (base == NULL) { goto out; }
+    if (base->base) {
+      base = base->base;
+    }
+
+    /* Find if renamed entry already exists */
+    new_name = rename(r->memory, signature->name, context);
+    if (new_name == NULL) { goto out; }
+    for (l = &base->rename ; *l ; l = &(*l)->next) {
+      if (strcmp((*l)->signature.name, new_name) == 0) { break; }
+    }
+    if ((*l) == NULL) {
+      /* Create a new rename entry */
+      struct labcomm2014_renaming_rename *entry = NULL;
+
+      entry = labcomm2014_memory_alloc(r->memory, 0, sizeof(*entry));
+      if (entry == NULL) { goto out; }
+      entry->next = NULL;
+      entry->use_count = 0;
+      entry->base = base;
+      entry->signature.name = new_name;
+      entry->signature.encoded_size = signature->encoded_size;
+      entry->signature.size = signature->size;
+      entry->signature.signature = signature->signature;
+      entry->signature.index = 0;
+#ifndef LABCOMM_NO_TYPEDECL
+      struct labcomm2014_signature_data s_treedata[2] = {
+        LABCOMM_SIGDEF_SIGNATURE(*signature),
+        LABCOMM_SIGDEF_END
+      };
+      entry->s_treedata[0] = s_treedata[0];
+      entry->s_treedata[1] = s_treedata[1];
+      entry->signature.tdsize = sizeof(result->s_treedata);
+      entry->signature.treedata = entry->s_treedata;
+#endif
+      labcomm2014_set_local_index(&entry->signature);
+      renamed = registry_new(r, &entry->signature, base);
+      if (renamed == NULL) {
+        /* Failed to create registry entry */
+        labcomm2014_memory_free(r->memory, 0, entry);
+        goto out;
+      } else {
+        (*l) = entry;
+      }
+    }
+    result = *l;
+    if (result) {
+      result->use_count++;
+    }
+  out:
+    ;
+  }
+  labcomm2014_scheduler_data_unlock(r->scheduler);
+  return result;
+}
+
+const struct labcomm2014_signature *labcomm2014_renaming_rename_signature(
+  struct labcomm2014_renaming_rename *rename)
+{
+  return &rename->signature;
+}
diff --git a/lib/c/2014/test/test_labcomm_renaming_registry.c b/lib/c/2014/test/test_labcomm_renaming_registry.c
new file mode 100644
index 0000000..ded8f6d
--- /dev/null
+++ b/lib/c/2014/test/test_labcomm_renaming_registry.c
@@ -0,0 +1,44 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <err.h>
+
+#include "labcomm2014.h"
+#include "labcomm2014_private.h"
+#include "labcomm2014_default_error_handler.h"
+#include "labcomm2014_default_memory.h"
+#include "labcomm2014_default_scheduler.h"
+#include "labcomm2014_renaming.h"
+#include "test/gen/generated_encoding.h"
+
+int main(int argc, char **argv)
+{
+  struct labcomm2014_renaming_registry *registry;
+  struct labcomm2014_renaming_rename *r1, *r2, *r3, *r4;
+
+  registry = labcomm2014_renaming_registry_new(
+    labcomm2014_default_error_handler,
+    labcomm2014_default_memory,
+    labcomm2014_default_scheduler);
+  r1 = labcomm2014_renaming_rename_new(
+    registry,
+    labcomm2014_signature_generated_encoding_R,
+    labcomm2014_renaming_prefix, "p:");
+  r2 = labcomm2014_renaming_rename_new(
+    registry,
+    labcomm2014_renaming_rename_signature(r1),
+    labcomm2014_renaming_suffix, ":s");
+  r3 = labcomm2014_renaming_rename_new(
+    registry,
+    labcomm2014_signature_generated_encoding_R,
+    labcomm2014_renaming_suffix, ":s");
+  r4 = labcomm2014_renaming_rename_new(
+    registry,
+    labcomm2014_renaming_rename_signature(r3),
+    labcomm2014_renaming_prefix, "p:");
+  assert(r2 == r4);
+}
-- 
GitLab