Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/cubeb/src/cubeb_strings.c
4246 views
1
/*
2
* Copyright © 2011 Mozilla Foundation
3
*
4
* This program is made available under an ISC-style license. See the
5
* accompanying file LICENSE for details.
6
*/
7
8
#include "cubeb_strings.h"
9
10
#include <assert.h>
11
#include <stdlib.h>
12
#include <string.h>
13
14
#define CUBEB_STRINGS_INLINE_COUNT 4
15
16
struct cubeb_strings {
17
uint32_t size;
18
uint32_t count;
19
char ** data;
20
char * small_store[CUBEB_STRINGS_INLINE_COUNT];
21
};
22
23
int
24
cubeb_strings_init(cubeb_strings ** strings)
25
{
26
cubeb_strings * strs = NULL;
27
28
if (!strings) {
29
return CUBEB_ERROR;
30
}
31
32
strs = calloc(1, sizeof(cubeb_strings));
33
assert(strs);
34
35
if (!strs) {
36
return CUBEB_ERROR;
37
}
38
39
strs->size = sizeof(strs->small_store) / sizeof(strs->small_store[0]);
40
strs->count = 0;
41
strs->data = strs->small_store;
42
43
*strings = strs;
44
45
return CUBEB_OK;
46
}
47
48
void
49
cubeb_strings_destroy(cubeb_strings * strings)
50
{
51
char ** sp = NULL;
52
char ** se = NULL;
53
54
if (!strings) {
55
return;
56
}
57
58
sp = strings->data;
59
se = sp + strings->count;
60
61
for (; sp != se; sp++) {
62
if (*sp) {
63
free(*sp);
64
}
65
}
66
67
if (strings->data != strings->small_store) {
68
free(strings->data);
69
}
70
71
free(strings);
72
}
73
74
/** Look for string in string storage.
75
@param strings Opaque pointer to interned string storage.
76
@param s String to look up.
77
@retval Read-only string or NULL if not found. */
78
static char const *
79
cubeb_strings_lookup(cubeb_strings * strings, char const * s)
80
{
81
char ** sp = NULL;
82
char ** se = NULL;
83
84
if (!strings || !s) {
85
return NULL;
86
}
87
88
sp = strings->data;
89
se = sp + strings->count;
90
91
for (; sp != se; sp++) {
92
if (*sp && strcmp(*sp, s) == 0) {
93
return *sp;
94
}
95
}
96
97
return NULL;
98
}
99
100
static char const *
101
cubeb_strings_push(cubeb_strings * strings, char const * s)
102
{
103
char * is = NULL;
104
105
if (strings->count == strings->size) {
106
char ** new_data;
107
uint32_t value_size = sizeof(char const *);
108
uint32_t new_size = strings->size * 2;
109
if (!new_size || value_size > (uint32_t)-1 / new_size) {
110
// overflow
111
return NULL;
112
}
113
114
if (strings->small_store == strings->data) {
115
// First time heap allocation.
116
new_data = malloc(new_size * value_size);
117
if (new_data) {
118
memcpy(new_data, strings->small_store, sizeof(strings->small_store));
119
}
120
} else {
121
new_data = realloc(strings->data, new_size * value_size);
122
}
123
124
if (!new_data) {
125
// out of memory
126
return NULL;
127
}
128
129
strings->size = new_size;
130
strings->data = new_data;
131
}
132
133
is = strdup(s);
134
strings->data[strings->count++] = is;
135
136
return is;
137
}
138
139
char const *
140
cubeb_strings_intern(cubeb_strings * strings, char const * s)
141
{
142
char const * is = NULL;
143
144
if (!strings || !s) {
145
return NULL;
146
}
147
148
is = cubeb_strings_lookup(strings, s);
149
if (is) {
150
return is;
151
}
152
153
return cubeb_strings_push(strings, s);
154
}
155
156