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 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "eina_config.h"
30 #include "eina_private.h"
31 #include "eina_log.h"
32 #include "eina_lock.h"
33 #include "eina_share_common.h"
34 
35 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
36 #include "eina_safety_checks.h"
37 #include "eina_tmpstr.h"
38 
39 typedef struct _Str Str;
40 
41 struct _Str
42 {
43    size_t length;
44    Str *next;
45    char *str;
46    Eina_Bool ma : 1;
47 };
48 
49 static Eina_Lock _mutex;
50 static Str *strs = NULL;
51 
52 Eina_Bool
eina_tmpstr_init(void)53 eina_tmpstr_init(void)
54 {
55    if (!eina_lock_new(&_mutex)) return EINA_FALSE;
56    return EINA_TRUE;
57 }
58 
59 Eina_Bool
eina_tmpstr_shutdown(void)60 eina_tmpstr_shutdown(void)
61 {
62    eina_lock_free(&_mutex);
63    return EINA_TRUE;
64 }
65 
66 EAPI Eina_Tmpstr *
eina_tmpstr_add_length(const char * str,size_t length)67 eina_tmpstr_add_length(const char *str, size_t length)
68 {
69    Str *s;
70 
71    if (!str || !length) return NULL;
72    s = malloc(sizeof(Str) + length + 1);
73    if (!s) return NULL;
74    s->length = length;
75    s->str = ((char *)s) + sizeof(Str);
76    strncpy(s->str, str, length);
77    s->str[length] = '\0';
78    s->ma = EINA_FALSE;
79    eina_lock_take(&_mutex);
80    s->next = strs;
81    strs = s;
82    eina_lock_release(&_mutex);
83    return s->str;
84 }
85 
86 EAPI Eina_Tmpstr *
eina_tmpstr_manage_new_length(char * str,size_t length)87 eina_tmpstr_manage_new_length(char *str, size_t length)
88 {
89    Str *s;
90 
91    if (!str || !length) return NULL;
92    s = calloc(1, sizeof(Str));
93    if (!s) return NULL;
94    s->length = length;
95    s->str = str;
96    s->ma = EINA_TRUE;
97    eina_lock_take(&_mutex);
98    s->next = strs;
99    strs = s;
100    eina_lock_release(&_mutex);
101    return s->str;
102 }
103 
104 EAPI Eina_Tmpstr *
eina_tmpstr_manage_new(char * str)105 eina_tmpstr_manage_new(char *str)
106 {
107    size_t len;
108 
109    if (!str) return NULL;
110    len = strlen(str);
111    return eina_tmpstr_manage_new_length(str, len);
112 }
113 
114 EAPI Eina_Tmpstr *
eina_tmpstr_add(const char * str)115 eina_tmpstr_add(const char *str)
116 {
117    size_t len;
118 
119    if (!str) return NULL;
120    len = strlen(str);
121    return eina_tmpstr_add_length(str, len);
122 }
123 
124 EAPI void
eina_tmpstr_del(Eina_Tmpstr * tmpstr)125 eina_tmpstr_del(Eina_Tmpstr *tmpstr)
126 {
127    Str *s, *sp;
128 
129    if ((!strs) || (!tmpstr)) return;
130    eina_lock_take(&_mutex);
131    for (sp = NULL, s = strs; s; sp = s, s = s->next)
132      {
133         if (s->str == tmpstr)
134           {
135              if (sp) sp->next = s->next;
136              else strs = s->next;
137              if (s->ma) free(s->str);
138              free(s);
139              break;
140           }
141      }
142    eina_lock_release(&_mutex);
143 }
144 
145 EAPI size_t
eina_tmpstr_strlen(Eina_Tmpstr * tmpstr)146 eina_tmpstr_strlen(Eina_Tmpstr *tmpstr)
147 {
148    if (!tmpstr) return 0;
149    return eina_tmpstr_len(tmpstr) + 1;
150 }
151 
152 EAPI size_t
eina_tmpstr_len(Eina_Tmpstr * tmpstr)153 eina_tmpstr_len(Eina_Tmpstr *tmpstr)
154 {
155    Str *s;
156 
157    if (!tmpstr) return 0;
158    if (!strs) return strlen(tmpstr);
159    eina_lock_take(&_mutex);
160    for (s = strs; s; s = s->next)
161      {
162         if (s->str == tmpstr)
163 	  {
164              size_t ret = s->length;
165              eina_lock_release(&_mutex);
166              return ret;
167 	  }
168      }
169    eina_lock_release(&_mutex);
170 
171    return strlen(tmpstr);
172 }
173