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