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 3011338 : string_dealloc(void *ptr)
41 : {
42 3011338 : heim_string_t s = ptr;
43 : heim_string_free_f_t *deallocp;
44 : heim_string_free_f_t dealloc;
45 :
46 3011338 : if (*(const char *)ptr != '\0')
47 2628261 : return;
48 :
49 : /* Possible string ref */
50 383077 : deallocp = _heim_get_isaextra(s, 0);
51 383077 : dealloc = *deallocp;
52 383077 : if (dealloc != NULL) {
53 383077 : char **strp = _heim_get_isaextra(s, 1);
54 383077 : dealloc(*strp);
55 : }
56 : }
57 :
58 : static int
59 1922434 : string_cmp(void *a, void *b)
60 : {
61 1922434 : 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 1922434 : 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 1922434 : return strcmp(a, b);
74 : }
75 :
76 : static uintptr_t
77 3803861 : string_hash(void *ptr)
78 : {
79 3803861 : const char *s = ptr;
80 : uintptr_t n;
81 :
82 33373048 : for (n = 0; *s; ++s)
83 29569187 : n += *s;
84 3803861 : 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 2676754 : heim_string_create(const char *string)
108 : {
109 2676754 : 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 383077 : 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 383077 : s = _heim_alloc_object(&_heim_string_object, 1);
128 383077 : if (s) {
129 : const char **strp;
130 :
131 383077 : ((char *)s)[0] = '\0';
132 383077 : deallocp = _heim_get_isaextra(s, 0);
133 383077 : *deallocp = dealloc;
134 383077 : strp = _heim_get_isaextra(s, 1);
135 383077 : *strp = string;
136 : }
137 383077 : 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 2676754 : heim_string_create_with_bytes(const void *data, size_t len)
151 : {
152 : heim_string_t s;
153 :
154 2676754 : s = _heim_alloc_object(&_heim_string_object, len + 1);
155 2676754 : if (s) {
156 2676754 : memcpy(s, data, len);
157 2676754 : ((char *)s)[len] = '\0';
158 : }
159 2676754 : 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 1787883 : heim_string_get_utf8(heim_string_t string)
213 : {
214 1787883 : if (*(const char *)string == '\0') {
215 : const char **strp;
216 :
217 : /* String ref */
218 784889 : strp = _heim_get_isaextra(string, 1);
219 784889 : if (*strp != NULL)
220 784889 : return *strp;
221 : }
222 1002994 : return (const char *)string;
223 : }
224 :
225 : /*
226 : *
227 : */
228 :
229 : static void
230 16117 : init_string(void *ptr)
231 : {
232 16117 : heim_dict_t *dict = ptr;
233 16117 : *dict = heim_dict_create(101);
234 16117 : heim_assert(*dict != NULL, "__heim_string_constant");
235 16117 : }
236 :
237 : heim_string_t
238 16259 : __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 16259 : heim_base_once_f(&once, &dict, init_string);
246 16259 : s = heim_string_create(_str);
247 :
248 : HEIMDAL_MUTEX_lock(&mutex);
249 16259 : s2 = heim_dict_get_value(dict, s);
250 16259 : if (s2) {
251 142 : heim_release(s);
252 142 : s = s2;
253 : } else {
254 16117 : _heim_make_permanent(s);
255 16117 : heim_dict_set_value(dict, s, s);
256 : }
257 : HEIMDAL_MUTEX_unlock(&mutex);
258 :
259 16259 : return s;
260 : }
|