diff options
Diffstat (limited to 'src/symap.c')
-rw-r--r-- | src/symap.c | 143 |
1 files changed, 79 insertions, 64 deletions
diff --git a/src/symap.c b/src/symap.c index 4a1a989..07002f2 100644 --- a/src/symap.c +++ b/src/symap.c @@ -1,18 +1,5 @@ -/* - Copyright 2011-2022 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "symap.h" @@ -38,47 +25,45 @@ */ struct SymapImpl { - /// Unsorted array of strings, so symbols[i] is the symbol for ID i - char** symbols; - - /// Array of IDs, sorted by corresponding string in `symbols` - uint32_t* index; - - /// Number of symbols (number of items in `symbols` and `index`) - uint32_t size; + char** symbols; ///< String array where symbols[i] is the symbol for ID i + uint32_t* index; ///< ID array sorted by corresponding string in `symbols` + uint32_t size; ///< Number of symbols (length of both symbols and index) + uint32_t pad; ///< Unused padding }; Symap* symap_new(void) { - Symap* map = (Symap*)malloc(sizeof(Symap)); - map->symbols = NULL; - map->index = NULL; - map->size = 0; + Symap* const map = (Symap*)calloc(1, sizeof(Symap)); + + if (map) { + map->symbols = NULL; + map->index = NULL; + map->size = 0U; + } + return map; } void -symap_free(Symap* map) +symap_free(Symap* const map) { - if (!map) { - return; - } + if (map) { + for (uint32_t i = 0U; i < map->size; ++i) { + free(map->symbols[i]); + } - for (uint32_t i = 0; i < map->size; ++i) { - free(map->symbols[i]); + free(map->symbols); + free(map->index); + free(map); } - - free(map->symbols); - free(map->index); - free(map); } static char* -symap_strdup(const char* str) +symap_strdup(const char* const str) { const size_t len = strlen(str); - char* copy = (char*)malloc(len + 1); + char* const copy = (char*)malloc(len + 1); memcpy(copy, str, len + 1); return copy; } @@ -88,9 +73,10 @@ symap_strdup(const char* str) or the index where a new entry for `sym` should be inserted. */ static uint32_t -symap_search(const Symap* map, const char* sym, bool* exact) +symap_search(const Symap* const map, const char* const sym, bool* const exact) { *exact = false; + if (map->size == 0) { return 0; // Empty map, insert at 0 } @@ -128,12 +114,11 @@ symap_search(const Symap* map, const char* sym, bool* exact) } uint32_t -symap_try_map(Symap* map, const char* sym) +symap_try_map(const Symap* const map, const char* const sym) { bool exact = false; const uint32_t index = symap_search(map, sym, &exact); if (exact) { - assert(!strcmp(map->symbols[map->index[index]], sym)); return map->index[index]; } @@ -141,8 +126,9 @@ symap_try_map(Symap* map, const char* sym) } uint32_t -symap_map(Symap* map, const char* sym) +symap_map(Symap* const map, const char* sym) { + // Search for existing symbol bool exact = false; const uint32_t index = symap_search(map, sym, &exact); if (exact) { @@ -150,15 +136,31 @@ symap_map(Symap* map, const char* sym) return map->index[index]; } - const uint32_t id = ++map->size; - char* const str = symap_strdup(sym); + // Claim a new highest ID + const uint32_t id = map->size + 1; + + // Grow symbol array + char** new_symbols = (char**)realloc(map->symbols, id * sizeof(sym)); + if (!new_symbols) { + return 0; + } + + map->symbols = new_symbols; + + // Grow index array + uint32_t* new_index = (uint32_t*)realloc(map->index, id * sizeof(index)); + if (!new_index) { + return 0; + } + + map->index = new_index; // Append new symbol to symbols array - map->symbols = (char**)realloc(map->symbols, map->size * sizeof(str)); - map->symbols[id - 1] = str; + map->size = id; + map->symbols[id - 1] = symap_strdup(sym); // Insert new index element into sorted index - map->index = (uint32_t*)realloc(map->index, map->size * sizeof(uint32_t)); + map->index = new_index; if (index < map->size - 1) { memmove(map->index + index + 1, map->index + index, @@ -171,7 +173,7 @@ symap_map(Symap* map, const char* sym) } const char* -symap_unmap(Symap* map, uint32_t id) +symap_unmap(const Symap* const map, const uint32_t id) { if (id == 0) { return NULL; @@ -184,12 +186,12 @@ symap_unmap(Symap* map, uint32_t id) return NULL; } -#ifdef STANDALONE +#ifdef SYMAP_STANDALONE # include <stdio.h> static void -symap_dump(Symap* map) +symap_dump(Symap* const map) { fprintf(stderr, "{\n"); for (uint32_t i = 0; i < map->size; ++i) { @@ -199,35 +201,48 @@ symap_dump(Symap* map) fprintf(stderr, "}\n"); } -int -main() +static int +symap_test(Symap* const map) { # define N_SYMS 5 - char* syms[N_SYMS] = {"hello", "bonjour", "goodbye", "aloha", "salut"}; - Symap* map = symap_new(); + static const char* const syms[N_SYMS] = { + "hello", "bonjour", "goodbye", "aloha", "salut"}; + for (int i = 0; i < N_SYMS; ++i) { if (symap_try_map(map, syms[i])) { - fprintf(stderr, "error: Symbol already mapped\n"); - return 1; + return fprintf(stderr, "error: Symbol already mapped\n"); } const uint32_t id = symap_map(map, syms[i]); - if (strcmp(map->symbols[id - 1], syms[i])) { - fprintf(stderr, "error: Corrupt symbol table\n"); - return 1; + if (!id) { + return fprintf(stderr, "error: Failed to insert ID\n"); + } + + if (!!strcmp(map->symbols[id - 1], syms[i])) { + return fprintf(stderr, "error: Corrupt symbol table\n"); } if (symap_map(map, syms[i]) != id) { - fprintf(stderr, "error: Remapped symbol to a different ID\n"); - return 1; + return fprintf(stderr, "error: Remapped symbol to a different ID\n"); } symap_dump(map); } - symap_free(map); return 0; + +# undef N_SYMS +} + +int +main(void) +{ + Symap* const map = symap_new(); + const int st = symap_test(map); + + symap_free(map); + return st; } -#endif // STANDALONE +#endif // SYMAP_STANDALONE |