/src/samba/third_party/heimdal/lib/base/string.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010 Kungliga Tekniska Högskolan |
3 | | * (Royal Institute of Technology, Stockholm, Sweden). |
4 | | * All rights reserved. |
5 | | * |
6 | | * Portions Copyright (c) 2010 Apple Inc. All rights reserved. |
7 | | * |
8 | | * Redistribution and use in source and binary forms, with or without |
9 | | * modification, are permitted provided that the following conditions |
10 | | * are met: |
11 | | * |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, this list of conditions and the following disclaimer. |
14 | | * |
15 | | * 2. Redistributions in binary form must reproduce the above copyright |
16 | | * notice, this list of conditions and the following disclaimer in the |
17 | | * documentation and/or other materials provided with the distribution. |
18 | | * |
19 | | * 3. Neither the name of the Institute nor the names of its contributors |
20 | | * may be used to endorse or promote products derived from this software |
21 | | * without specific prior written permission. |
22 | | * |
23 | | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
24 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
27 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 | | * SUCH DAMAGE. |
34 | | */ |
35 | | |
36 | | #include "baselocl.h" |
37 | | #include <string.h> |
38 | | |
39 | | static void HEIM_CALLCONV |
40 | | string_dealloc(void *ptr) |
41 | 0 | { |
42 | 0 | heim_string_t s = ptr; |
43 | 0 | heim_string_free_f_t *deallocp; |
44 | 0 | heim_string_free_f_t dealloc; |
45 | |
|
46 | 0 | if (*(const char *)ptr != '\0') |
47 | 0 | return; |
48 | | |
49 | | /* Possible string ref */ |
50 | 0 | deallocp = _heim_get_isaextra(s, 0); |
51 | 0 | dealloc = *deallocp; |
52 | 0 | if (dealloc != NULL) { |
53 | 0 | char **strp = _heim_get_isaextra(s, 1); |
54 | 0 | dealloc(*strp); |
55 | 0 | } |
56 | 0 | } |
57 | | |
58 | | static int |
59 | | string_cmp(void *a, void *b) |
60 | 0 | { |
61 | 0 | if (*(char *)a == '\0') { |
62 | 0 | char **strp = _heim_get_isaextra(a, 1); |
63 | |
|
64 | 0 | if (*strp != NULL) |
65 | 0 | a = *strp; /* a is a string ref */ |
66 | 0 | } |
67 | 0 | if (*(char *)b == '\0') { |
68 | 0 | char **strp = _heim_get_isaextra(b, 1); |
69 | |
|
70 | 0 | if (*strp != NULL) |
71 | 0 | b = *strp; /* b is a string ref */ |
72 | 0 | } |
73 | 0 | return strcmp(a, b); |
74 | 0 | } |
75 | | |
76 | | static uintptr_t |
77 | | string_hash(void *ptr) |
78 | 0 | { |
79 | 0 | const char *s = ptr; |
80 | 0 | uintptr_t n; |
81 | |
|
82 | 0 | for (n = 0; *s; ++s) |
83 | 0 | n += *s; |
84 | 0 | return n; |
85 | 0 | } |
86 | | |
87 | | struct heim_type_data _heim_string_object = { |
88 | | HEIM_TID_STRING, |
89 | | "string-object", |
90 | | NULL, |
91 | | string_dealloc, |
92 | | NULL, |
93 | | string_cmp, |
94 | | string_hash, |
95 | | NULL |
96 | | }; |
97 | | |
98 | | /** |
99 | | * Create a string object |
100 | | * |
101 | | * @param string the string to create, must be an utf8 string |
102 | | * |
103 | | * @return string object |
104 | | */ |
105 | | |
106 | | heim_string_t |
107 | | heim_string_create(const char *string) |
108 | 0 | { |
109 | 0 | return heim_string_create_with_bytes(string, strlen(string)); |
110 | 0 | } |
111 | | |
112 | | /** |
113 | | * Create a string object without copying the source. |
114 | | * |
115 | | * @param string the string to referenced, must be UTF-8 |
116 | | * @param dealloc the function to use to release the referece to the string |
117 | | * |
118 | | * @return string object |
119 | | */ |
120 | | |
121 | | heim_string_t |
122 | | heim_string_ref_create(const char *string, heim_string_free_f_t dealloc) |
123 | 0 | { |
124 | 0 | heim_string_t s; |
125 | 0 | heim_string_free_f_t *deallocp; |
126 | |
|
127 | 0 | s = _heim_alloc_object(&_heim_string_object, 1); |
128 | 0 | if (s) { |
129 | 0 | const char **strp; |
130 | |
|
131 | 0 | ((char *)s)[0] = '\0'; |
132 | 0 | deallocp = _heim_get_isaextra(s, 0); |
133 | 0 | *deallocp = dealloc; |
134 | 0 | strp = _heim_get_isaextra(s, 1); |
135 | 0 | *strp = string; |
136 | 0 | } |
137 | 0 | return s; |
138 | 0 | } |
139 | | |
140 | | /** |
141 | | * Create a string object |
142 | | * |
143 | | * @param string the string to create, must be an utf8 string |
144 | | * @param len the length of the string |
145 | | * |
146 | | * @return string object |
147 | | */ |
148 | | |
149 | | heim_string_t |
150 | | heim_string_create_with_bytes(const void *data, size_t len) |
151 | 0 | { |
152 | 0 | heim_string_t s; |
153 | |
|
154 | 0 | s = _heim_alloc_object(&_heim_string_object, len + 1); |
155 | 0 | if (s) { |
156 | 0 | if (len) |
157 | 0 | memcpy(s, data, len); |
158 | 0 | ((char *)s)[len] = '\0'; |
159 | 0 | } |
160 | 0 | return s; |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * Create a string object using a format string |
165 | | * |
166 | | * @param fmt format string |
167 | | * @param ... |
168 | | * |
169 | | * @return string object |
170 | | */ |
171 | | |
172 | | heim_string_t |
173 | | heim_string_create_with_format(const char *fmt, ...) |
174 | 0 | { |
175 | 0 | heim_string_t s; |
176 | 0 | char *str = NULL; |
177 | 0 | va_list ap; |
178 | 0 | int ret; |
179 | |
|
180 | 0 | va_start(ap, fmt); |
181 | 0 | ret = vasprintf(&str, fmt, ap); |
182 | 0 | va_end(ap); |
183 | 0 | if (ret < 0 || str == NULL) |
184 | 0 | return NULL; |
185 | | |
186 | 0 | s = heim_string_ref_create(str, free); |
187 | 0 | if (s == NULL) |
188 | 0 | free(str); |
189 | 0 | return s; |
190 | 0 | } |
191 | | |
192 | | /** |
193 | | * Return the type ID of string objects |
194 | | * |
195 | | * @return type id of string objects |
196 | | */ |
197 | | |
198 | | heim_tid_t |
199 | | heim_string_get_type_id(void) |
200 | 0 | { |
201 | 0 | return HEIM_TID_STRING; |
202 | 0 | } |
203 | | |
204 | | /** |
205 | | * Get the string value of the content. |
206 | | * |
207 | | * @param string the string object to get the value from |
208 | | * |
209 | | * @return a utf8 string |
210 | | */ |
211 | | |
212 | | const char * |
213 | | heim_string_get_utf8(heim_string_t string) |
214 | 0 | { |
215 | 0 | if (*(const char *)string == '\0') { |
216 | 0 | const char **strp; |
217 | | |
218 | | /* String ref */ |
219 | 0 | strp = _heim_get_isaextra(string, 1); |
220 | 0 | if (*strp != NULL) |
221 | 0 | return *strp; |
222 | 0 | } |
223 | 0 | return (const char *)string; |
224 | 0 | } |
225 | | |
226 | | /* |
227 | | * |
228 | | */ |
229 | | |
230 | | static void |
231 | | init_string(void *ptr) |
232 | 0 | { |
233 | 0 | heim_dict_t *dict = ptr; |
234 | 0 | *dict = heim_dict_create(101); |
235 | 0 | heim_assert(*dict != NULL, "__heim_string_constant"); |
236 | 0 | } |
237 | | |
238 | | heim_string_t |
239 | | __heim_string_constant(const char *_str) |
240 | 0 | { |
241 | 0 | static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER; |
242 | 0 | static heim_base_once_t once = HEIM_BASE_ONCE_INIT; |
243 | 0 | static heim_dict_t dict = NULL; |
244 | 0 | heim_string_t s, s2; |
245 | |
|
246 | 0 | heim_base_once_f(&once, &dict, init_string); |
247 | 0 | s = heim_string_create(_str); |
248 | |
|
249 | 0 | HEIMDAL_MUTEX_lock(&mutex); |
250 | 0 | s2 = heim_dict_get_value(dict, s); |
251 | 0 | if (s2) { |
252 | 0 | heim_release(s); |
253 | 0 | s = s2; |
254 | 0 | } else { |
255 | 0 | _heim_make_permanent(s); |
256 | 0 | heim_dict_set_value(dict, s, s); |
257 | 0 | } |
258 | 0 | HEIMDAL_MUTEX_unlock(&mutex); |
259 | |
|
260 | 0 | return s; |
261 | 0 | } |