diff options
author | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
commit | 07274513e984f0b5544586c74508ccd16e7dcafa (patch) | |
tree | b32ff2a9136fbc1a4a6a0ed1e4d79cde0f5f16d9 /libraries/eina/src/lib/eina_stringshare.c | |
parent | Added Irrlicht 1.8, but without all the Windows binaries. (diff) | |
download | SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.zip SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.gz SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.bz2 SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.xz |
Remove EFL, since it's been released now.
Diffstat (limited to '')
-rw-r--r-- | libraries/eina/src/lib/eina_stringshare.c | 792 |
1 files changed, 0 insertions, 792 deletions
diff --git a/libraries/eina/src/lib/eina_stringshare.c b/libraries/eina/src/lib/eina_stringshare.c deleted file mode 100644 index f371fcd..0000000 --- a/libraries/eina/src/lib/eina_stringshare.c +++ /dev/null | |||
@@ -1,792 +0,0 @@ | |||
1 | /* EINA - EFL data type library | ||
2 | * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010 | ||
3 | * Carsten Haitzler, | ||
4 | * Jorge Luis Zapata Muga, | ||
5 | * Cedric Bail, | ||
6 | * Gustavo Sverzut Barbieri | ||
7 | * Tom Hacohen | ||
8 | * Brett Nash | ||
9 | * | ||
10 | * This library is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU Lesser General Public | ||
12 | * License as published by the Free Software Foundation; either | ||
13 | * version 2.1 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This library is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * Lesser General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Lesser General Public | ||
21 | * License along with this library; | ||
22 | * if not, see <http://www.gnu.org/licenses/>. | ||
23 | */ | ||
24 | |||
25 | #ifdef HAVE_CONFIG_H | ||
26 | # include "config.h" | ||
27 | #endif | ||
28 | |||
29 | #ifdef HAVE_ALLOCA_H | ||
30 | # include <alloca.h> | ||
31 | #elif defined __GNUC__ | ||
32 | # define alloca __builtin_alloca | ||
33 | #elif defined _AIX | ||
34 | # define alloca __alloca | ||
35 | #elif defined _MSC_VER | ||
36 | # include <malloc.h> | ||
37 | # define alloca _alloca | ||
38 | #else | ||
39 | # include <stddef.h> | ||
40 | # ifdef __cplusplus | ||
41 | extern "C" | ||
42 | # endif | ||
43 | void *alloca (size_t); | ||
44 | #endif | ||
45 | |||
46 | #include <stdlib.h> | ||
47 | #include <stdio.h> | ||
48 | #include <string.h> | ||
49 | |||
50 | #ifdef HAVE_EVIL | ||
51 | # include <Evil.h> | ||
52 | #endif | ||
53 | |||
54 | #include "eina_config.h" | ||
55 | #include "eina_private.h" | ||
56 | #include "eina_error.h" | ||
57 | #include "eina_log.h" | ||
58 | #include "eina_lock.h" | ||
59 | #include "eina_share_common.h" | ||
60 | |||
61 | /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ | ||
62 | #include "eina_safety_checks.h" | ||
63 | #include "eina_stringshare.h" | ||
64 | |||
65 | |||
66 | #ifdef CRITICAL | ||
67 | #undef CRITICAL | ||
68 | #endif | ||
69 | #define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_stringshare_log_dom, __VA_ARGS__) | ||
70 | |||
71 | #ifdef ERR | ||
72 | #undef ERR | ||
73 | #endif | ||
74 | #define ERR(...) EINA_LOG_DOM_ERR(_eina_share_stringshare_log_dom, __VA_ARGS__) | ||
75 | |||
76 | #ifdef DBG | ||
77 | #undef DBG | ||
78 | #endif | ||
79 | #define DBG(...) EINA_LOG_DOM_DBG(_eina_share_stringshare_log_dom, __VA_ARGS__) | ||
80 | |||
81 | static int _eina_share_stringshare_log_dom = -1; | ||
82 | |||
83 | /* The actual share */ | ||
84 | static Eina_Share *stringshare_share; | ||
85 | static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node"; | ||
86 | |||
87 | extern Eina_Bool _share_common_threads_activated; | ||
88 | static Eina_Lock _mutex_small; | ||
89 | |||
90 | /* Stringshare optimizations */ | ||
91 | static const unsigned char _eina_stringshare_single[512] = { | ||
92 | 0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0, | ||
93 | 16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0, | ||
94 | 31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0, | ||
95 | 46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0, | ||
96 | 61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0, | ||
97 | 76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0, | ||
98 | 91,0,92,0,93,0,94,0,95,0,96,0,97,0,98,0,99,0,100,0,101,0,102,0,103,0,104,0, | ||
99 | 105,0, | ||
100 | 106,0,107,0,108,0,109,0,110,0,111,0,112,0,113,0,114,0,115,0,116,0,117,0,118, | ||
101 | 0,119,0,120,0, | ||
102 | 121,0,122,0,123,0,124,0,125,0,126,0,127,0,128,0,129,0,130,0,131,0,132,0,133, | ||
103 | 0,134,0,135,0, | ||
104 | 136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148, | ||
105 | 0,149,0,150,0, | ||
106 | 151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163, | ||
107 | 0,164,0,165,0, | ||
108 | 166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178, | ||
109 | 0,179,0,180,0, | ||
110 | 181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,191,0,192,0,193, | ||
111 | 0,194,0,195,0, | ||
112 | 196,0,197,0,198,0,199,0,200,0,201,0,202,0,203,0,204,0,205,0,206,0,207,0,208, | ||
113 | 0,209,0,210,0, | ||
114 | 211,0,212,0,213,0,214,0,215,0,216,0,217,0,218,0,219,0,220,0,221,0,222,0,223, | ||
115 | 0,224,0,225,0, | ||
116 | 226,0,227,0,228,0,229,0,230,0,231,0,232,0,233,0,234,0,235,0,236,0,237,0,238, | ||
117 | 0,239,0,240,0, | ||
118 | 241,0,242,0,243,0,244,0,245,0,246,0,247,0,248,0,249,0,250,0,251,0,252,0,253, | ||
119 | 0,254,0,255,0 | ||
120 | }; | ||
121 | |||
122 | typedef struct _Eina_Stringshare_Small Eina_Stringshare_Small; | ||
123 | typedef struct _Eina_Stringshare_Small_Bucket Eina_Stringshare_Small_Bucket; | ||
124 | |||
125 | struct _Eina_Stringshare_Small_Bucket | ||
126 | { | ||
127 | /* separate arrays for faster lookups */ | ||
128 | const char **strings; | ||
129 | unsigned char *lengths; | ||
130 | unsigned short *references; | ||
131 | int count; | ||
132 | int size; | ||
133 | }; | ||
134 | |||
135 | struct _Eina_Stringshare_Small | ||
136 | { | ||
137 | Eina_Stringshare_Small_Bucket *buckets[256]; | ||
138 | }; | ||
139 | |||
140 | #define EINA_STRINGSHARE_SMALL_BUCKET_STEP 8 | ||
141 | static Eina_Stringshare_Small _eina_small_share; | ||
142 | |||
143 | static inline int | ||
144 | _eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket, | ||
145 | int i, | ||
146 | const char *pstr, | ||
147 | unsigned char plength) | ||
148 | { | ||
149 | /* pstr and plength are from second char and on, since the first is | ||
150 | * always the same. | ||
151 | * | ||
152 | * First string being always the same, size being between 2 and 3 | ||
153 | * characters (there is a check for special case length==1 and then | ||
154 | * small stringshare is applied to strings < 4), we just need to | ||
155 | * compare 2 characters of both strings. | ||
156 | */ | ||
157 | const unsigned char cur_plength = bucket->lengths[i] - 1; | ||
158 | const char *cur_pstr; | ||
159 | |||
160 | if (cur_plength > plength) | ||
161 | return 1; | ||
162 | else if (cur_plength < plength) | ||
163 | return -1; | ||
164 | |||
165 | cur_pstr = bucket->strings[i] + 1; | ||
166 | |||
167 | if (cur_pstr[0] > pstr[0]) | ||
168 | return 1; | ||
169 | else if (cur_pstr[0] < pstr[0]) | ||
170 | return -1; | ||
171 | |||
172 | if (plength == 1) | ||
173 | return 0; | ||
174 | |||
175 | if (cur_pstr[1] > pstr[1]) | ||
176 | return 1; | ||
177 | else if (cur_pstr[1] < pstr[1]) | ||
178 | return -1; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static const char * | ||
184 | _eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket, | ||
185 | const char *str, | ||
186 | unsigned char length, | ||
187 | int *idx) | ||
188 | { | ||
189 | const char *pstr = str + 1; /* skip first letter, it's always the same */ | ||
190 | unsigned char plength = length - 1; | ||
191 | int i, low, high; | ||
192 | |||
193 | if (bucket->count == 0) | ||
194 | { | ||
195 | *idx = 0; | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
199 | low = 0; | ||
200 | high = bucket->count; | ||
201 | |||
202 | while (low < high) | ||
203 | { | ||
204 | int r; | ||
205 | |||
206 | i = (low + high - 1) / 2; | ||
207 | |||
208 | r = _eina_stringshare_small_cmp(bucket, i, pstr, plength); | ||
209 | if (r > 0) | ||
210 | high = i; | ||
211 | else if (r < 0) | ||
212 | low = i + 1; | ||
213 | else | ||
214 | { | ||
215 | *idx = i; | ||
216 | return bucket->strings[i]; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | *idx = low; | ||
221 | return NULL; | ||
222 | } | ||
223 | |||
224 | static Eina_Bool | ||
225 | _eina_stringshare_small_bucket_resize(Eina_Stringshare_Small_Bucket *bucket, | ||
226 | int size) | ||
227 | { | ||
228 | void *tmp; | ||
229 | |||
230 | tmp = realloc((void *)bucket->strings, size * sizeof(bucket->strings[0])); | ||
231 | if (!tmp) | ||
232 | { | ||
233 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | bucket->strings = tmp; | ||
238 | |||
239 | tmp = realloc(bucket->lengths, size * sizeof(bucket->lengths[0])); | ||
240 | if (!tmp) | ||
241 | { | ||
242 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | bucket->lengths = tmp; | ||
247 | |||
248 | tmp = realloc(bucket->references, size * sizeof(bucket->references[0])); | ||
249 | if (!tmp) | ||
250 | { | ||
251 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | bucket->references = tmp; | ||
256 | |||
257 | bucket->size = size; | ||
258 | return 1; | ||
259 | } | ||
260 | |||
261 | static const char * | ||
262 | _eina_stringshare_small_bucket_insert_at( | ||
263 | Eina_Stringshare_Small_Bucket **p_bucket, | ||
264 | const char *str, | ||
265 | unsigned char length, | ||
266 | int idx) | ||
267 | { | ||
268 | Eina_Stringshare_Small_Bucket *bucket = *p_bucket; | ||
269 | int todo, off; | ||
270 | char *snew; | ||
271 | |||
272 | if (!bucket) | ||
273 | { | ||
274 | *p_bucket = bucket = calloc(1, sizeof(*bucket)); | ||
275 | if (!bucket) | ||
276 | { | ||
277 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
278 | return NULL; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | if (bucket->count + 1 >= bucket->size) | ||
283 | { | ||
284 | int size = bucket->size + EINA_STRINGSHARE_SMALL_BUCKET_STEP; | ||
285 | if (!_eina_stringshare_small_bucket_resize(bucket, size)) | ||
286 | return NULL; | ||
287 | } | ||
288 | |||
289 | snew = malloc(length + 1); | ||
290 | if (!snew) | ||
291 | { | ||
292 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
293 | return NULL; | ||
294 | } | ||
295 | |||
296 | memcpy(snew, str, length); | ||
297 | snew[length] = '\0'; | ||
298 | |||
299 | off = idx + 1; | ||
300 | todo = bucket->count - idx; | ||
301 | if (todo > 0) | ||
302 | { | ||
303 | memmove((void *)(bucket->strings + off), bucket->strings + idx, | ||
304 | todo * sizeof(bucket->strings[0])); | ||
305 | memmove(bucket->lengths + off, bucket->lengths + idx, | ||
306 | todo * sizeof(bucket->lengths[0])); | ||
307 | memmove(bucket->references + off, bucket->references + idx, | ||
308 | todo * sizeof(bucket->references[0])); | ||
309 | } | ||
310 | |||
311 | bucket->strings[idx] = snew; | ||
312 | bucket->lengths[idx] = length; | ||
313 | bucket->references[idx] = 1; | ||
314 | bucket->count++; | ||
315 | |||
316 | return snew; | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | _eina_stringshare_small_bucket_remove_at( | ||
321 | Eina_Stringshare_Small_Bucket **p_bucket, | ||
322 | int idx) | ||
323 | { | ||
324 | Eina_Stringshare_Small_Bucket *bucket = *p_bucket; | ||
325 | int todo, off; | ||
326 | |||
327 | if (bucket->references[idx] > 1) | ||
328 | { | ||
329 | bucket->references[idx]--; | ||
330 | return; | ||
331 | } | ||
332 | |||
333 | free((char *)bucket->strings[idx]); | ||
334 | |||
335 | if (bucket->count == 1) | ||
336 | { | ||
337 | free((void *)bucket->strings); | ||
338 | free(bucket->lengths); | ||
339 | free(bucket->references); | ||
340 | free(bucket); | ||
341 | *p_bucket = NULL; | ||
342 | return; | ||
343 | } | ||
344 | |||
345 | bucket->count--; | ||
346 | if (idx == bucket->count) | ||
347 | goto end; | ||
348 | |||
349 | off = idx + 1; | ||
350 | todo = bucket->count - idx; | ||
351 | |||
352 | memmove((void *)(bucket->strings + idx), bucket->strings + off, | ||
353 | todo * sizeof(bucket->strings[0])); | ||
354 | memmove(bucket->lengths + idx, bucket->lengths + off, | ||
355 | todo * sizeof(bucket->lengths[0])); | ||
356 | memmove(bucket->references + idx, bucket->references + off, | ||
357 | todo * sizeof(bucket->references[0])); | ||
358 | |||
359 | end: | ||
360 | if (bucket->count + EINA_STRINGSHARE_SMALL_BUCKET_STEP < bucket->size) | ||
361 | { | ||
362 | int size = bucket->size - EINA_STRINGSHARE_SMALL_BUCKET_STEP; | ||
363 | _eina_stringshare_small_bucket_resize(bucket, size); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static const char * | ||
368 | _eina_stringshare_small_add(const char *str, unsigned char length) | ||
369 | { | ||
370 | Eina_Stringshare_Small_Bucket **bucket; | ||
371 | int i; | ||
372 | |||
373 | bucket = _eina_small_share.buckets + (unsigned char)str[0]; | ||
374 | if (!*bucket) | ||
375 | i = 0; | ||
376 | else | ||
377 | { | ||
378 | const char *ret; | ||
379 | ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i); | ||
380 | if (ret) | ||
381 | { | ||
382 | (*bucket)->references[i]++; | ||
383 | return ret; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | return _eina_stringshare_small_bucket_insert_at(bucket, str, length, i); | ||
388 | } | ||
389 | |||
390 | static void | ||
391 | _eina_stringshare_small_del(const char *str, unsigned char length) | ||
392 | { | ||
393 | Eina_Stringshare_Small_Bucket **bucket; | ||
394 | const char *ret; | ||
395 | int i; | ||
396 | |||
397 | bucket = _eina_small_share.buckets + (unsigned char)str[0]; | ||
398 | if (!*bucket) | ||
399 | goto error; | ||
400 | |||
401 | ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i); | ||
402 | if (!ret) | ||
403 | goto error; | ||
404 | |||
405 | _eina_stringshare_small_bucket_remove_at(bucket, i); | ||
406 | return; | ||
407 | |||
408 | error: | ||
409 | CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); | ||
410 | } | ||
411 | |||
412 | static void | ||
413 | _eina_stringshare_small_init(void) | ||
414 | { | ||
415 | eina_lock_new(&_mutex_small); | ||
416 | memset(&_eina_small_share, 0, sizeof(_eina_small_share)); | ||
417 | } | ||
418 | |||
419 | static void | ||
420 | _eina_stringshare_small_shutdown(void) | ||
421 | { | ||
422 | Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end; | ||
423 | |||
424 | p_bucket = _eina_small_share.buckets; | ||
425 | p_bucket_end = p_bucket + 256; | ||
426 | |||
427 | for (; p_bucket < p_bucket_end; p_bucket++) | ||
428 | { | ||
429 | Eina_Stringshare_Small_Bucket *bucket = *p_bucket; | ||
430 | char **s, **s_end; | ||
431 | |||
432 | if (!bucket) | ||
433 | continue; | ||
434 | |||
435 | s = (char **)bucket->strings; | ||
436 | s_end = s + bucket->count; | ||
437 | for (; s < s_end; s++) | ||
438 | free(*s); | ||
439 | |||
440 | free((void *)bucket->strings); | ||
441 | free(bucket->lengths); | ||
442 | free(bucket->references); | ||
443 | free(bucket); | ||
444 | *p_bucket = NULL; | ||
445 | } | ||
446 | |||
447 | eina_lock_free(&_mutex_small); | ||
448 | } | ||
449 | |||
450 | static void | ||
451 | _eina_stringshare_small_bucket_dump(Eina_Stringshare_Small_Bucket *bucket, | ||
452 | struct dumpinfo *di) | ||
453 | { | ||
454 | const char **s = bucket->strings; | ||
455 | unsigned char *l = bucket->lengths; | ||
456 | unsigned short *r = bucket->references; | ||
457 | int i; | ||
458 | |||
459 | di->used += sizeof(*bucket); | ||
460 | di->used += bucket->count * sizeof(*s); | ||
461 | di->used += bucket->count * sizeof(*l); | ||
462 | di->used += bucket->count * sizeof(*r); | ||
463 | di->unique += bucket->count; | ||
464 | |||
465 | for (i = 0; i < bucket->count; i++, s++, l++, r++) | ||
466 | { | ||
467 | int dups; | ||
468 | |||
469 | printf("DDD: %5hhu %5hu '%s'\n", *l, *r, *s); | ||
470 | |||
471 | dups = (*r - 1); | ||
472 | |||
473 | di->used += *l; | ||
474 | di->saved += *l * dups; | ||
475 | di->dups += dups; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | static void | ||
480 | _eina_stringshare_small_dump(struct dumpinfo *di) | ||
481 | { | ||
482 | Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end; | ||
483 | |||
484 | p_bucket = _eina_small_share.buckets; | ||
485 | p_bucket_end = p_bucket + 256; | ||
486 | |||
487 | for (; p_bucket < p_bucket_end; p_bucket++) | ||
488 | { | ||
489 | Eina_Stringshare_Small_Bucket *bucket = *p_bucket; | ||
490 | |||
491 | if (!bucket) | ||
492 | continue; | ||
493 | |||
494 | _eina_stringshare_small_bucket_dump(bucket, di); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | |||
499 | /*============================================================================* | ||
500 | * Global * | ||
501 | *============================================================================*/ | ||
502 | |||
503 | /** | ||
504 | * @internal | ||
505 | * @brief Initialize the share_common module. | ||
506 | * | ||
507 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
508 | * | ||
509 | * This function sets up the share_common module of Eina. It is called by | ||
510 | * eina_init(). | ||
511 | * | ||
512 | * @see eina_init() | ||
513 | */ | ||
514 | Eina_Bool | ||
515 | eina_stringshare_init(void) | ||
516 | { | ||
517 | Eina_Bool ret; | ||
518 | |||
519 | if (_eina_share_stringshare_log_dom < 0) | ||
520 | { | ||
521 | _eina_share_stringshare_log_dom = eina_log_domain_register | ||
522 | ("eina_stringshare", EINA_LOG_COLOR_DEFAULT); | ||
523 | |||
524 | if (_eina_share_stringshare_log_dom < 0) | ||
525 | { | ||
526 | EINA_LOG_ERR("Could not register log domain: eina_stringshare"); | ||
527 | return EINA_FALSE; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | ret = eina_share_common_init(&stringshare_share, | ||
532 | EINA_MAGIC_STRINGSHARE_NODE, | ||
533 | EINA_MAGIC_STRINGSHARE_NODE_STR); | ||
534 | if (ret) | ||
535 | _eina_stringshare_small_init(); | ||
536 | else | ||
537 | { | ||
538 | eina_log_domain_unregister(_eina_share_stringshare_log_dom); | ||
539 | _eina_share_stringshare_log_dom = -1; | ||
540 | } | ||
541 | |||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * @internal | ||
547 | * @brief Shut down the share_common module. | ||
548 | * | ||
549 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
550 | * | ||
551 | * This function shuts down the share_common module set up by | ||
552 | * eina_share_common_init(). It is called by eina_shutdown(). | ||
553 | * | ||
554 | * @see eina_shutdown() | ||
555 | */ | ||
556 | Eina_Bool | ||
557 | eina_stringshare_shutdown(void) | ||
558 | { | ||
559 | Eina_Bool ret; | ||
560 | _eina_stringshare_small_shutdown(); | ||
561 | ret = eina_share_common_shutdown(&stringshare_share); | ||
562 | |||
563 | if (_eina_share_stringshare_log_dom >= 0) | ||
564 | { | ||
565 | eina_log_domain_unregister(_eina_share_stringshare_log_dom); | ||
566 | _eina_share_stringshare_log_dom = -1; | ||
567 | } | ||
568 | |||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | /*============================================================================* | ||
573 | * API * | ||
574 | *============================================================================*/ | ||
575 | |||
576 | EAPI void | ||
577 | eina_stringshare_del(Eina_Stringshare *str) | ||
578 | { | ||
579 | int slen; | ||
580 | |||
581 | if (!str) | ||
582 | return; | ||
583 | |||
584 | /* special cases */ | ||
585 | if (str[0] == '\0') | ||
586 | slen = 0; | ||
587 | else if (str[1] == '\0') | ||
588 | slen = 1; | ||
589 | else if (str[2] == '\0') | ||
590 | slen = 2; | ||
591 | else if (str[3] == '\0') | ||
592 | slen = 3; | ||
593 | else | ||
594 | slen = 4; /* handled later */ | ||
595 | |||
596 | if (slen < 2) | ||
597 | return; | ||
598 | else if (slen < 4) | ||
599 | { | ||
600 | eina_share_common_population_del(stringshare_share, slen); | ||
601 | eina_lock_take(&_mutex_small); | ||
602 | _eina_stringshare_small_del(str, slen); | ||
603 | eina_lock_release(&_mutex_small); | ||
604 | return; | ||
605 | } | ||
606 | |||
607 | if (!eina_share_common_del(stringshare_share, str)) | ||
608 | CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); | ||
609 | } | ||
610 | |||
611 | EAPI Eina_Stringshare * | ||
612 | eina_stringshare_add_length(const char *str, unsigned int slen) | ||
613 | { | ||
614 | if ((!str) || (slen <= 0)) | ||
615 | return ""; | ||
616 | else if (slen == 1) | ||
617 | return (Eina_Stringshare *) _eina_stringshare_single + ((*str) << 1); | ||
618 | else if (slen < 4) | ||
619 | { | ||
620 | const char *s; | ||
621 | |||
622 | eina_lock_take(&_mutex_small); | ||
623 | s = _eina_stringshare_small_add(str, slen); | ||
624 | eina_lock_release(&_mutex_small); | ||
625 | return s; | ||
626 | } | ||
627 | |||
628 | return eina_share_common_add_length(stringshare_share, str, slen * | ||
629 | sizeof(char), sizeof(char)); | ||
630 | } | ||
631 | |||
632 | EAPI Eina_Stringshare * | ||
633 | eina_stringshare_add(const char *str) | ||
634 | { | ||
635 | int slen; | ||
636 | if (!str) | ||
637 | return NULL; | ||
638 | |||
639 | if (str[0] == '\0') | ||
640 | slen = 0; | ||
641 | else if (str[1] == '\0') | ||
642 | slen = 1; | ||
643 | else if (str[2] == '\0') | ||
644 | slen = 2; | ||
645 | else if (str[3] == '\0') | ||
646 | slen = 3; | ||
647 | else | ||
648 | slen = 3 + (int)strlen(str + 3); | ||
649 | |||
650 | return eina_stringshare_add_length(str, slen); | ||
651 | } | ||
652 | |||
653 | EAPI Eina_Stringshare * | ||
654 | eina_stringshare_printf(const char *fmt, ...) | ||
655 | { | ||
656 | va_list args; | ||
657 | char *tmp; | ||
658 | const char *ret; | ||
659 | int len; | ||
660 | |||
661 | if (!fmt) | ||
662 | return NULL; | ||
663 | |||
664 | va_start(args, fmt); | ||
665 | len = vasprintf(&tmp, fmt, args); | ||
666 | va_end(args); | ||
667 | |||
668 | if (len < 1) | ||
669 | return NULL; | ||
670 | |||
671 | ret = eina_stringshare_add_length(tmp, len); | ||
672 | free(tmp); | ||
673 | |||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | EAPI Eina_Stringshare * | ||
678 | eina_stringshare_vprintf(const char *fmt, va_list args) | ||
679 | { | ||
680 | char *tmp; | ||
681 | const char *ret; | ||
682 | int len; | ||
683 | |||
684 | if (!fmt) | ||
685 | return NULL; | ||
686 | |||
687 | len = vasprintf(&tmp, fmt, args); | ||
688 | |||
689 | if (len < 1) | ||
690 | return NULL; | ||
691 | |||
692 | ret = eina_stringshare_add_length(tmp, len); | ||
693 | free(tmp); | ||
694 | |||
695 | return ret; | ||
696 | } | ||
697 | |||
698 | EAPI Eina_Stringshare * | ||
699 | eina_stringshare_nprintf(unsigned int len, const char *fmt, ...) | ||
700 | { | ||
701 | va_list args; | ||
702 | char *tmp; | ||
703 | int size; | ||
704 | |||
705 | if (!fmt) | ||
706 | return NULL; | ||
707 | |||
708 | if (len < 1) | ||
709 | return NULL; | ||
710 | |||
711 | tmp = alloca(sizeof(char) * len + 1); | ||
712 | |||
713 | va_start(args, fmt); | ||
714 | size = vsnprintf(tmp, len, fmt, args); | ||
715 | va_end(args); | ||
716 | |||
717 | if (size < 1) | ||
718 | return NULL; | ||
719 | |||
720 | return eina_stringshare_add_length(tmp, len); | ||
721 | } | ||
722 | |||
723 | EAPI Eina_Stringshare * | ||
724 | eina_stringshare_ref(Eina_Stringshare *str) | ||
725 | { | ||
726 | int slen; | ||
727 | |||
728 | if (!str) | ||
729 | return eina_share_common_ref(stringshare_share, str); | ||
730 | |||
731 | /* special cases */ | ||
732 | if (str[0] == '\0') | ||
733 | slen = 0; | ||
734 | else if (str[1] == '\0') | ||
735 | slen = 1; | ||
736 | else if (str[2] == '\0') | ||
737 | slen = 2; | ||
738 | else if (str[3] == '\0') | ||
739 | slen = 3; | ||
740 | else | ||
741 | slen = 3 + (int)strlen(str + 3); | ||
742 | |||
743 | if (slen < 2) | ||
744 | { | ||
745 | eina_share_common_population_add(stringshare_share, slen); | ||
746 | |||
747 | return str; | ||
748 | } | ||
749 | else if (slen < 4) | ||
750 | { | ||
751 | const char *s; | ||
752 | eina_share_common_population_add(stringshare_share, slen); | ||
753 | |||
754 | eina_lock_take(&_mutex_small); | ||
755 | s = _eina_stringshare_small_add(str, slen); | ||
756 | eina_lock_release(&_mutex_small); | ||
757 | |||
758 | return s; | ||
759 | } | ||
760 | |||
761 | return eina_share_common_ref(stringshare_share, str); | ||
762 | } | ||
763 | |||
764 | EAPI int | ||
765 | eina_stringshare_strlen(Eina_Stringshare *str) | ||
766 | { | ||
767 | int len; | ||
768 | /* special cases */ | ||
769 | if (str[0] == '\0') | ||
770 | return 0; | ||
771 | |||
772 | if (str[1] == '\0') | ||
773 | return 1; | ||
774 | |||
775 | if (str[2] == '\0') | ||
776 | return 2; | ||
777 | |||
778 | if (str[3] == '\0') | ||
779 | return 3; | ||
780 | |||
781 | len = eina_share_common_length(stringshare_share, (Eina_Stringshare *) str); | ||
782 | len = (len > 0) ? len / (int)sizeof(char) : -1; | ||
783 | return len; | ||
784 | } | ||
785 | |||
786 | EAPI void | ||
787 | eina_stringshare_dump(void) | ||
788 | { | ||
789 | eina_share_common_dump(stringshare_share, | ||
790 | _eina_stringshare_small_dump, | ||
791 | sizeof(_eina_stringshare_single)); | ||
792 | } | ||