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 3009515 : string_dealloc(void *ptr)
41 : {
42 3009515 : heim_string_t s = ptr;
43 : heim_string_free_f_t *deallocp;
44 : heim_string_free_f_t dealloc;
45 :
46 3009515 : if (*(const char *)ptr != '\0')
47 2626733 : return;
48 :
49 : /* Possible string ref */
50 382782 : deallocp = _heim_get_isaextra(s, 0);
51 382782 : dealloc = *deallocp;
52 382782 : if (dealloc != NULL) {
53 382782 : char **strp = _heim_get_isaextra(s, 1);
54 382782 : dealloc(*strp);
55 : }
56 : }
57 :
58 : static int
59 1921200 : string_cmp(void *a, void *b)
60 : {
61 1921200 : 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 1921200 : 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 1921200 : return strcmp(a, b);
74 : }
75 :
76 : static uintptr_t
77 3801509 : string_hash(void *ptr)
78 : {
79 3801509 : const char *s = ptr;
80 : uintptr_t n;
81 :
82 33352522 : for (n = 0; *s; ++s)
83 29551013 : n += *s;
84 3801509 : 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 2675208 : heim_string_create(const char *string)
108 : {
109 2675208 : 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 382782 : heim_string_ref_create(const char *string, heim_string_free_f_t dealloc)
123 : {
124 : heim_string_t s;
125 : heim_string_free_f_t *deallocp;
126 :
127 382782 : s = _heim_alloc_object(&_heim_string_object, 1);
128 382782 : if (s) {
129 : const char **strp;
130 :
131 382782 : ((char *)s)[0] = '\0';
132 382782 : deallocp = _heim_get_isaextra(s, 0);
133 382782 : *deallocp = dealloc;
134 382782 : strp = _heim_get_isaextra(s, 1);
135 382782 : *strp = string;
136 : }
137 382782 : 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 2675208 : heim_string_create_with_bytes(const void *data, size_t len)
151 : {
152 : heim_string_t s;
153 :
154 2675208 : s = _heim_alloc_object(&_heim_string_object, len + 1);
155 2675208 : if (s) {
156 2675208 : memcpy(s, data, len);
157 2675208 : ((char *)s)[len] = '\0';
158 : }
159 2675208 : return s;
160 : }
161 :
162 : /**
163 : * Create a string object using a format string
164 : *
165 : * @param fmt format string
166 : * @param ...
167 : *
168 : * @return string object
169 : */
170 :
171 : heim_string_t
172 0 : heim_string_create_with_format(const char *fmt, ...)
173 : {
174 : heim_string_t s;
175 0 : char *str = NULL;
176 : va_list ap;
177 : int ret;
178 :
179 0 : va_start(ap, fmt);
180 0 : ret = vasprintf(&str, fmt, ap);
181 0 : va_end(ap);
182 0 : if (ret < 0 || str == NULL)
183 0 : return NULL;
184 :
185 0 : s = heim_string_ref_create(str, free);
186 0 : if (s == NULL)
187 0 : free(str);
188 0 : return s;
189 : }
190 :
191 : /**
192 : * Return the type ID of string objects
193 : *
194 : * @return type id of string objects
195 : */
196 :
197 : heim_tid_t
198 0 : heim_string_get_type_id(void)
199 : {
200 0 : return HEIM_TID_STRING;
201 : }
202 :
203 : /**
204 : * Get the string value of the content.
205 : *
206 : * @param string the string object to get the value from
207 : *
208 : * @return a utf8 string
209 : */
210 :
211 : const char *
212 1786521 : heim_string_get_utf8(heim_string_t string)
213 : {
214 1786521 : if (*(const char *)string == '\0') {
215 : const char **strp;
216 :
217 : /* String ref */
218 784285 : strp = _heim_get_isaextra(string, 1);
219 784285 : if (*strp != NULL)
220 784285 : return *strp;
221 : }
222 1002236 : return (const char *)string;
223 : }
224 :
225 : /*
226 : *
227 : */
228 :
229 : static void
230 16111 : init_string(void *ptr)
231 : {
232 16111 : heim_dict_t *dict = ptr;
233 16111 : *dict = heim_dict_create(101);
234 16111 : heim_assert(*dict != NULL, "__heim_string_constant");
235 16111 : }
236 :
237 : heim_string_t
238 16253 : __heim_string_constant(const char *_str)
239 : {
240 : static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER;
241 : static heim_base_once_t once;
242 : static heim_dict_t dict = NULL;
243 : heim_string_t s, s2;
244 :
245 16253 : heim_base_once_f(&once, &dict, init_string);
246 16253 : s = heim_string_create(_str);
247 :
248 : HEIMDAL_MUTEX_lock(&mutex);
249 16253 : s2 = heim_dict_get_value(dict, s);
250 16253 : if (s2) {
251 142 : heim_release(s);
252 142 : s = s2;
253 : } else {
254 16111 : _heim_make_permanent(s);
255 16111 : heim_dict_set_value(dict, s, s);
256 : }
257 : HEIMDAL_MUTEX_unlock(&mutex);
258 :
259 16253 : return s;
260 : }
|