diff options
author | Dan Glastonbury <[email protected]> | 2017-05-15 11:15:20 +1000 |
---|---|---|
committer | Dan Glastonbury <[email protected]> | 2017-08-29 19:05:30 +1000 |
commit | 8b17b0e9dafcc710215d98f370deae988f78c2dc (patch) | |
tree | 7621dc3cd01a63a0e002365c446cc5384a8f1860 | |
parent | fcf854bb20351508a8058164e79b6a8e4fd1a37b (diff) | |
download | cubeb-8b17b0e9dafcc710215d98f370deae988f78c2dc.tar.gz cubeb-8b17b0e9dafcc710215d98f370deae988f78c2dc.zip |
cubeb: Intern string support.
A simple database for interned strings. This is to be used to provide
stable device ids in the device enumeration API.
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/cubeb_strings.c | 155 | ||||
-rw-r--r-- | src/cubeb_strings.h | 42 |
3 files changed, 198 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c662964..a3e100a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ add_library(cubeb src/cubeb_resampler.cpp src/cubeb_panner.cpp src/cubeb_log.cpp + src/cubeb_strings.c src/cubeb_utils.c $<TARGET_OBJECTS:speex>) target_include_directories(cubeb PUBLIC include) diff --git a/src/cubeb_strings.c b/src/cubeb_strings.c new file mode 100644 index 0000000..79d7d21 --- /dev/null +++ b/src/cubeb_strings.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2011 Mozilla Foundation + * + * This program is made available under an ISC-style license. See the + * accompanying file LICENSE for details. + */ + +#include "cubeb_strings.h" + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#define CUBEB_STRINGS_INLINE_COUNT 4 + +struct cubeb_strings { + uint32_t size; + uint32_t count; + char ** data; + char * small_store[CUBEB_STRINGS_INLINE_COUNT]; +}; + +int +cubeb_strings_init(cubeb_strings ** strings) +{ + cubeb_strings* strs = NULL; + + if (!strings) { + return CUBEB_ERROR; + } + + strs = calloc(1, sizeof(cubeb_strings)); + assert(strs); + + if (!strs) { + return CUBEB_ERROR; + } + + strs->size = sizeof(strs->small_store) / sizeof(strs->small_store[0]); + strs->count = 0; + strs->data = strs->small_store; + + *strings = strs; + + return CUBEB_OK; +} + +void +cubeb_strings_destroy(cubeb_strings * strings) +{ + char ** sp = NULL; + char ** se = NULL; + + if (!strings) { + return; + } + + sp = strings->data; + se = sp + strings->count; + + for ( ; sp != se; sp++) { + if (*sp) { + free(*sp); + } + } + + if (strings->data != strings->small_store) { + free(strings->data); + } + + free(strings); +} + +/** Look for string in string storage. + @param strings Opaque pointer to interned string storage. + @param s String to look up. + @retval Read-only string or NULL if not found. */ +static char const * +cubeb_strings_lookup(cubeb_strings * strings, char const * s) +{ + char ** sp = NULL; + char ** se = NULL; + + if (!strings || !s) { + return NULL; + } + + sp = strings->data; + se = sp + strings->count; + + for ( ; sp != se; sp++) { + if (*sp && strcmp(*sp, s) == 0) { + return *sp; + } + } + + return NULL; +} + +static char const * +cubeb_strings_push(cubeb_strings * strings, char const * s) +{ + char * is = NULL; + + if (strings->count == strings->size) { + char ** new_data; + uint32_t value_size = sizeof(char const *); + uint32_t new_size = strings->size * 2; + if (!new_size || value_size > (uint32_t)-1 / new_size) { + // overflow + return NULL; + } + + if (strings->small_store == strings->data) { + // First time heap allocation. + new_data = malloc(new_size * value_size); + if (new_data) { + memcpy(new_data, strings->small_store, sizeof(strings->small_store)); + } + } else { + new_data = realloc(strings->data, new_size * value_size); + } + + if (!new_data) { + // out of memory + return NULL; + } + + strings->size = new_size; + strings->data = new_data; + } + + is = strdup(s); + strings->data[strings->count++] = is; + + return is; +} + +char const * +cubeb_strings_intern(cubeb_strings * strings, char const * s) +{ + char const * is = NULL; + + if (!strings || !s) { + return NULL; + } + + is = cubeb_strings_lookup(strings, s); + if (is) { + return is; + } + + return cubeb_strings_push(strings, s); +} + diff --git a/src/cubeb_strings.h b/src/cubeb_strings.h new file mode 100644 index 0000000..f8ad2fe --- /dev/null +++ b/src/cubeb_strings.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2011 Mozilla Foundation + * + * This program is made available under an ISC-style license. See the + * accompanying file LICENSE for details. + */ + +#ifndef CUBEB_STRINGS_H +#define CUBEB_STRINGS_H + +#include "cubeb/cubeb.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** Opaque handle referencing interned string storage. */ +typedef struct cubeb_strings cubeb_strings; + +/** Initialize a interned string structure. + @param strings An out param where an opaque pointer to the + interned string storage will be returned. + @retval CUBEB_OK in case of success. + @retval CUBEB_ERROR in case of error. */ +CUBEB_EXPORT int cubeb_strings_init(cubeb_strings ** strings); + +/** */ +CUBEB_EXPORT void cubeb_strings_destroy(cubeb_strings * strings); + +/** Add string to internal storage. + @param strings Opaque pointer to interned string storage. + @param s String to add to storage. + @retval CUBEB_OK + @retval CUBEB_ERROR + */ +CUBEB_EXPORT char const * cubeb_strings_intern(cubeb_strings * strings, char const * s); + +#if defined(__cplusplus) +} +#endif + +#endif // !CUBEB_STRINGS_H |