Line data Source code
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 4805343 : string_dealloc(void *ptr)
41 : {
42 4805343 : heim_string_t s = ptr;
43 154727 : heim_string_free_f_t *deallocp;
44 154727 : heim_string_free_f_t dealloc;
45 :
46 4805343 : if (*(const char *)ptr != '\0')
47 4098991 : return;
48 :
49 : /* Possible string ref */
50 572103 : deallocp = _heim_get_isaextra(s, 0);
51 572103 : dealloc = *deallocp;
52 572103 : if (dealloc != NULL) {
53 572103 : char **strp = _heim_get_isaextra(s, 1);
54 572103 : dealloc(*strp);
55 : }
56 : }
57 :
58 : static int
59 3258957 : string_cmp(void *a, void *b)
60 : {
61 3258957 : 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 : }
67 3258957 : 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 : }
73 3258957 : return strcmp(a, b);
74 : }
75 :
76 : static uintptr_t
77 6136414 : string_hash(void *ptr)
78 : {
79 6136414 : const char *s = ptr;
80 203417 : uintptr_t n;
81 :
82 57071090 : for (n = 0; *s; ++s)
83 50934676 : n += *s;
84 6136414 : return n;
85 : }
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 4332110 : heim_string_create(const char *string)
108 : {
109 4332110 : return heim_string_create_with_bytes(string, strlen(string));
110 : }
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 572103 : heim_string_ref_create(const char *string, heim_string_free_f_t dealloc)
123 : {
124 20478 : heim_string_t s;
125 20478 : heim_string_free_f_t *deallocp;
126 :
127 572103 : s = _heim_alloc_object(&_heim_string_object, 1);
128 572103 : if (s) {
129 20478 : const char **strp;
130 :
131 572103 : ((char *)s)[0] = '\0';
132 572103 : deallocp = _heim_get_isaextra(s, 0);
133 572103 : *deallocp = dealloc;
134 572103 : strp = _heim_get_isaextra(s, 1);
135 572103 : *strp = string;
136 : }
137 572103 : return s;
138 : }
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 4332110 : heim_string_create_with_bytes(const void *data, size_t len)
151 : {
152 138063 : heim_string_t s;
153 :
154 4332110 : s = _heim_alloc_object(&_heim_string_object, len + 1);
155 4332110 : if (s) {
156 4332110 : if (len)
157 4332110 : memcpy(s, data, len);
158 4332110 : ((char *)s)[len] = '\0';
159 : }
160 4332110 : return s;
161 : }
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 6 : heim_string_create_with_format(const char *fmt, ...)
174 : {
175 0 : heim_string_t s;
176 6 : char *str = NULL;
177 0 : va_list ap;
178 0 : int ret;
179 :
180 6 : va_start(ap, fmt);
181 6 : ret = vasprintf(&str, fmt, ap);
182 6 : va_end(ap);
183 6 : if (ret < 0 || str == NULL)
184 0 : return NULL;
185 :
186 6 : s = heim_string_ref_create(str, free);
187 6 : if (s == NULL)
188 0 : free(str);
189 6 : return s;
190 : }
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 0 : heim_string_get_type_id(void)
200 : {
201 0 : return HEIM_TID_STRING;
202 : }
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 2722389 : heim_string_get_utf8(heim_string_t string)
214 : {
215 2722389 : if (*(const char *)string == '\0') {
216 42126 : const char **strp;
217 :
218 : /* String ref */
219 1174984 : strp = _heim_get_isaextra(string, 1);
220 1174984 : if (*strp != NULL)
221 1174984 : return *strp;
222 : }
223 1492212 : return (const char *)string;
224 : }
225 :
226 : /*
227 : *
228 : */
229 :
230 : static void
231 32887 : init_string(void *ptr)
232 : {
233 32887 : heim_dict_t *dict = ptr;
234 32887 : *dict = heim_dict_create(101);
235 32887 : heim_assert(*dict != NULL, "__heim_string_constant");
236 32887 : }
237 :
238 : heim_string_t
239 33089 : __heim_string_constant(const char *_str)
240 : {
241 1282 : static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER;
242 1282 : static heim_base_once_t once = HEIM_BASE_ONCE_INIT;
243 1282 : static heim_dict_t dict = NULL;
244 1282 : heim_string_t s, s2;
245 :
246 33089 : heim_base_once_f(&once, &dict, init_string);
247 33089 : s = heim_string_create(_str);
248 :
249 1282 : HEIMDAL_MUTEX_lock(&mutex);
250 33089 : s2 = heim_dict_get_value(dict, s);
251 33089 : if (s2) {
252 186 : heim_release(s);
253 186 : s = s2;
254 : } else {
255 32903 : _heim_make_permanent(s);
256 32903 : heim_dict_set_value(dict, s, s);
257 : }
258 1282 : HEIMDAL_MUTEX_unlock(&mutex);
259 :
260 33089 : return s;
261 : }
|