1 #include "e.h"
2
3 /* local subsystem functions */
4 static void _e_path_free(E_Path *ep);
5 static void _e_path_cache_free(E_Path *ep);
6 static Eina_Bool _e_path_cache_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
7
8 /* externally accessible functions */
9 E_API E_Path *
e_path_new(void)10 e_path_new(void)
11 {
12 E_Path *ep;
13
14 ep = E_OBJECT_ALLOC(E_Path, E_PATH_TYPE, _e_path_free);
15 return ep;
16 }
17
18 E_API void
e_path_default_path_append(E_Path * ep,const char * path)19 e_path_default_path_append(E_Path *ep, const char *path)
20 {
21 E_OBJECT_CHECK(ep);
22 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
23 if (!path) return;
24 if (path[0] == '~')
25 {
26 E_Path_Dir *epd;
27 char *new_path;
28 const char *home_dir;
29 int len1, len2;
30
31 home_dir = e_user_homedir_get();
32 len1 = strlen(home_dir);
33 len2 = strlen(path);
34 new_path = malloc(len1 + len2 + 1);
35 if (!new_path) return;
36 epd = malloc(sizeof(E_Path_Dir));
37 if (!epd)
38 {
39 free(new_path);
40 return;
41 }
42
43 strcpy(new_path, home_dir);
44 strcat(new_path, path + 1);
45 epd->dir = eina_stringshare_add(new_path);
46 free(new_path);
47 ep->default_dir_list = eina_list_append(ep->default_dir_list, epd);
48 }
49 else
50 {
51 E_Path_Dir *epd;
52 epd = malloc(sizeof(E_Path_Dir));
53 if (!epd)
54 return;
55 epd->dir = eina_stringshare_add(path);
56 ep->default_dir_list = eina_list_append(ep->default_dir_list, epd);
57 }
58 _e_path_cache_free(ep);
59 }
60
61 E_API void
e_path_user_path_set(E_Path * ep,Eina_List ** user_dir_list)62 e_path_user_path_set(E_Path *ep, Eina_List **user_dir_list)
63 {
64 E_OBJECT_CHECK(ep);
65 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
66
67 ep->user_dir_list = user_dir_list;
68 _e_path_cache_free(ep);
69 }
70
71 E_API void
e_path_user_path_append(E_Path * ep,const char * path)72 e_path_user_path_append(E_Path *ep, const char *path)
73 {
74 E_OBJECT_CHECK(ep);
75 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
76 if (!path) return;
77 if (path[0] == '~')
78 {
79 E_Path_Dir *epd;
80 char *new_path;
81 const char *home_dir;
82 int len1, len2;
83
84 home_dir = e_user_homedir_get();
85 len1 = strlen(home_dir);
86 len2 = strlen(path);
87 new_path = malloc(len1 + len2 + 1);
88 if (!new_path) return;
89 epd = malloc(sizeof(E_Path_Dir));
90 if (!epd)
91 {
92 free(new_path);
93 return;
94 }
95
96 strcpy(new_path, home_dir);
97 strcat(new_path, path + 1);
98 epd->dir = eina_stringshare_add(new_path);
99 free(new_path);
100 *(ep->user_dir_list) = eina_list_append(*(ep->user_dir_list), epd);
101 }
102 else
103 {
104 E_Path_Dir *epd;
105 epd = malloc(sizeof(E_Path_Dir));
106 if (!epd)
107 return;
108 epd->dir = eina_stringshare_add(path);
109 *(ep->user_dir_list) = eina_list_append(*(ep->user_dir_list), epd);
110 }
111 _e_path_cache_free(ep);
112 }
113
114 E_API void
e_path_user_path_prepend(E_Path * ep,const char * path)115 e_path_user_path_prepend(E_Path *ep, const char *path)
116 {
117 E_OBJECT_CHECK(ep);
118 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
119 if (!path) return;
120 if (path[0] == '~')
121 {
122 E_Path_Dir *epd;
123 char *new_path;
124 const char *home_dir;
125 int len1, len2;
126
127 home_dir = e_user_homedir_get();
128 len1 = strlen(home_dir);
129 len2 = strlen(path);
130 new_path = malloc(len1 + len2 + 1);
131 if (!new_path) return;
132 epd = malloc(sizeof(E_Path_Dir));
133 if (!epd)
134 {
135 free(new_path);
136 return;
137 }
138
139 strcpy(new_path, home_dir);
140 strcat(new_path, path + 1);
141 epd->dir = eina_stringshare_add(new_path);
142 free(new_path);
143 *(ep->user_dir_list) = eina_list_prepend(*(ep->user_dir_list), epd);
144 }
145 else
146 {
147 E_Path_Dir *epd;
148 epd = malloc(sizeof(E_Path_Dir));
149 if (!epd)
150 return;
151 epd->dir = eina_stringshare_add(path);
152 *(ep->user_dir_list) = eina_list_prepend(*(ep->user_dir_list), epd);
153 }
154 _e_path_cache_free(ep);
155 }
156
157 E_API void
e_path_user_path_remove(E_Path * ep,const char * path)158 e_path_user_path_remove(E_Path *ep, const char *path)
159 {
160 Eina_List *l;
161 E_Path_Dir *epd;
162
163 E_OBJECT_CHECK(ep);
164 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
165 if (!path) return;
166 if (path[0] == '~')
167 {
168 char *new_path;
169 const char *home_dir;
170 int len1, len2;
171
172 home_dir = e_user_homedir_get();
173 len1 = strlen(home_dir);
174 len2 = strlen(path);
175 new_path = malloc(len1 + len2 + 1);
176 if (!new_path) return;
177 strcpy(new_path, home_dir);
178 strcat(new_path, path + 1);
179 EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
180 {
181 if (epd->dir)
182 {
183 if (!strcmp(epd->dir, new_path))
184 {
185 *(ep->user_dir_list) = eina_list_remove_list(
186 *(ep->user_dir_list), l);
187 eina_stringshare_del(epd->dir);
188 free(epd);
189 free(new_path);
190 _e_path_cache_free(ep);
191 return;
192 }
193 }
194 }
195 free(new_path);
196 }
197 else
198 {
199 EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
200 {
201 if (epd->dir)
202 {
203 if (!strcmp(epd->dir, path))
204 {
205 *(ep->user_dir_list) = eina_list_remove_list(
206 *(ep->user_dir_list), l);
207 eina_stringshare_del(epd->dir);
208 free(epd);
209 _e_path_cache_free(ep);
210 return;
211 }
212 }
213 }
214 }
215 }
216
217 E_API void
e_path_user_path_clear(E_Path * ep)218 e_path_user_path_clear(E_Path *ep)
219 {
220 E_Path_Dir *epd;
221 EINA_LIST_FREE(*(ep->user_dir_list), epd)
222 {
223 eina_stringshare_del(epd->dir);
224 free(epd);
225 }
226 _e_path_cache_free(ep);
227 }
228
229 E_API Eina_Stringshare *
e_path_find(E_Path * ep,const char * file)230 e_path_find(E_Path *ep, const char *file)
231 {
232 Eina_List *l;
233 E_Path_Dir *epd;
234 char *str;
235 Eina_Stringshare *ret;
236 char buf[PATH_MAX] = "";
237
238 E_OBJECT_CHECK_RETURN(ep, NULL);
239 E_OBJECT_TYPE_CHECK_RETURN(ep, E_PATH_TYPE, NULL);
240
241 if (!file) return NULL;
242 str = eina_hash_find(ep->hash, file);
243 if (str) return eina_stringshare_ref(str);
244 /* Look in the default dir list */
245 EINA_LIST_FOREACH(ep->default_dir_list, l, epd)
246 {
247 if (epd->dir)
248 {
249 snprintf(buf, sizeof(buf), "%s/%s", epd->dir, file);
250 if (ecore_file_exists(buf))
251 {
252 if (!ep->hash)
253 ep->hash = eina_hash_string_superfast_new(NULL);
254 if (eina_hash_population(ep->hash) >= 512)
255 _e_path_cache_free(ep);
256 ret = eina_stringshare_add(buf);
257 eina_hash_add(ep->hash, file, ret);
258 return eina_stringshare_ref(ret);
259 }
260 }
261 }
262 /* Look in the users dir list */
263 EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
264 {
265 if (epd->dir)
266 {
267 snprintf(buf, sizeof(buf), "%s/%s", epd->dir, file);
268 if (ecore_file_exists(buf))
269 {
270 if (!ep->hash)
271 ep->hash = eina_hash_string_superfast_new(NULL);
272 if (eina_hash_population(ep->hash) >= 512)
273 _e_path_cache_free(ep);
274 ret = eina_stringshare_add(buf);
275 eina_hash_add(ep->hash, file, ret);
276 return eina_stringshare_ref(ret);
277 }
278 }
279 }
280 return NULL;
281 }
282
283 E_API void
e_path_evas_append(E_Path * ep,Evas * evas)284 e_path_evas_append(E_Path *ep, Evas *evas)
285 {
286 Eina_List *dir_list;
287 E_Path_Dir *epd;
288
289 E_OBJECT_CHECK(ep);
290 E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
291 if (!evas) return;
292
293 dir_list = e_path_dir_list_get(ep);
294
295 EINA_LIST_FREE(dir_list, epd)
296 {
297 if (epd->dir) evas_font_path_append(evas, epd->dir);
298 eina_stringshare_del(epd->dir);
299 free(epd);
300 }
301 }
302
303 /* combine default_list and and user_list in and easy to use list */
304 E_API Eina_List *
e_path_dir_list_get(E_Path * ep)305 e_path_dir_list_get(E_Path *ep)
306 {
307 Eina_List *dir_list;
308 Eina_List *l;
309 E_Path_Dir *new_epd;
310 E_Path_Dir *epd;
311
312 dir_list = NULL;
313
314 if (ep->user_dir_list)
315 {
316 EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
317 {
318 new_epd = malloc(sizeof(E_Path_Dir));
319 new_epd->dir = eina_stringshare_add(epd->dir);
320 dir_list = eina_list_append(dir_list, new_epd);
321 }
322 }
323
324 EINA_LIST_FOREACH(ep->default_dir_list, l, epd)
325 {
326 new_epd = malloc(sizeof(E_Path_Dir));
327 new_epd->dir = eina_stringshare_add(epd->dir);
328 dir_list = eina_list_append(dir_list, new_epd);
329 }
330
331 return dir_list;
332 }
333
334 E_API void
e_path_dir_list_free(Eina_List * dir_list)335 e_path_dir_list_free(Eina_List *dir_list)
336 {
337 E_Path_Dir *epd;
338
339 EINA_LIST_FREE(dir_list, epd)
340 {
341 eina_stringshare_del(epd->dir);
342 free(epd);
343 }
344 }
345
346 /* local subsystem functions */
347 static void
_e_path_free(E_Path * ep)348 _e_path_free(E_Path *ep)
349 {
350 E_Path_Dir *epd;
351
352 _e_path_cache_free(ep);
353 EINA_LIST_FREE(ep->default_dir_list, epd)
354 {
355 eina_stringshare_del(epd->dir);
356 free(epd);
357 }
358 free(ep);
359 }
360
361 static void
_e_path_cache_free(E_Path * ep)362 _e_path_cache_free(E_Path *ep)
363 {
364 if (!ep->hash) return;
365 eina_hash_foreach(ep->hash, _e_path_cache_free_cb, NULL);
366 eina_hash_free(ep->hash);
367 ep->hash = NULL;
368 }
369
370 static Eina_Bool
_e_path_cache_free_cb(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)371 _e_path_cache_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
372 {
373 eina_stringshare_del(data);
374 return 1;
375 }
376
377