Tizen 2.1 release
[platform/core/uifw/e17.git] / src / bin / e_path.c
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 EAPI E_Path *
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 EAPI void
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 EAPI void
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 EAPI void
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 EAPI void
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 EAPI void
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 EAPI void
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 EAPI const char *
230 e_path_find(E_Path *ep, const char *file)
231 {
232    Eina_List *l;
233    E_Path_Dir *epd;
234    char *str;
235    char buf[PATH_MAX] = "";
236
237    E_OBJECT_CHECK_RETURN(ep, NULL);
238    E_OBJECT_TYPE_CHECK_RETURN(ep, E_PATH_TYPE, NULL);
239
240    if (!file) return NULL;
241    str = eina_hash_find(ep->hash, file);
242    if (str) return eina_stringshare_add(str);
243    /* Look in the default dir list */
244    EINA_LIST_FOREACH(ep->default_dir_list, l, epd)
245      {
246         if (epd->dir)
247           {
248              snprintf(buf, sizeof(buf), "%s/%s", epd->dir, file);
249              if (ecore_file_exists(buf))
250                {
251                   if (!ep->hash)
252                     ep->hash = eina_hash_string_superfast_new(NULL);
253                   if (eina_hash_population(ep->hash) >= 512)
254                     _e_path_cache_free(ep);
255                   eina_hash_add(ep->hash, file,
256                                 eina_stringshare_add(buf));
257                   return eina_stringshare_add(buf);
258                }
259           }
260      }
261    /* Look in the users dir list */
262    EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
263      {
264         if (epd->dir)
265           {
266              snprintf(buf, sizeof(buf), "%s/%s", epd->dir, file);
267              if (ecore_file_exists(buf))
268                {
269                   if (!ep->hash)
270                     ep->hash = eina_hash_string_superfast_new(NULL);
271                   if (eina_hash_population(ep->hash) >= 512)
272                     _e_path_cache_free(ep);
273                   eina_hash_add(ep->hash, file,
274                                 eina_stringshare_add(buf));
275                   return eina_stringshare_add(buf);
276                }
277           }
278      }
279    return NULL;
280 }
281
282 EAPI void
283 e_path_evas_append(E_Path *ep, Evas *evas)
284 {
285    Eina_List *dir_list;
286    E_Path_Dir *epd;
287
288    E_OBJECT_CHECK(ep);
289    E_OBJECT_TYPE_CHECK(ep, E_PATH_TYPE);
290    if (!evas) return;
291
292    dir_list = e_path_dir_list_get(ep);
293
294    EINA_LIST_FREE(dir_list, epd)
295      {
296         if (epd->dir) evas_font_path_append(evas, epd->dir);
297         eina_stringshare_del(epd->dir);
298         free(epd);
299      }
300 }
301
302 /* combine default_list and and user_list in and easy to use list */
303 EAPI Eina_List *
304 e_path_dir_list_get(E_Path *ep)
305 {
306    Eina_List    *dir_list;
307    Eina_List    *l;
308    E_Path_Dir   *new_epd;
309    E_Path_Dir   *epd;
310
311    dir_list = NULL;
312
313    if (ep->user_dir_list)
314      {
315         EINA_LIST_FOREACH(*(ep->user_dir_list), l, epd)
316           {
317              new_epd = malloc(sizeof(E_Path_Dir));
318              new_epd->dir = eina_stringshare_add(epd->dir);
319              dir_list = eina_list_append(dir_list, new_epd);
320           }
321      }
322
323    EINA_LIST_FOREACH(ep->default_dir_list, l, epd)
324      {
325         new_epd = malloc(sizeof(E_Path_Dir));
326         new_epd->dir = eina_stringshare_add(epd->dir);
327         dir_list = eina_list_append(dir_list, new_epd);
328      }
329
330    return dir_list;
331 }
332
333 EAPI void
334 e_path_dir_list_free(Eina_List *dir_list)
335 {
336    E_Path_Dir *epd;
337
338    EINA_LIST_FREE(dir_list, epd)
339      {
340         eina_stringshare_del(epd->dir);
341         free(epd);
342      }
343 }
344
345 /* local subsystem functions */
346 static void
347 _e_path_free(E_Path *ep)
348 {
349    E_Path_Dir *epd;
350
351    _e_path_cache_free(ep);
352    EINA_LIST_FREE(ep->default_dir_list, epd)
353      {
354         eina_stringshare_del(epd->dir);
355         free(epd);
356      }
357    free(ep);
358 }
359
360 static void
361 _e_path_cache_free(E_Path *ep)
362 {
363    if (!ep->hash) return;
364    eina_hash_foreach(ep->hash, _e_path_cache_free_cb, NULL);
365    eina_hash_free(ep->hash);
366    ep->hash = NULL;
367 }
368
369 static Eina_Bool
370 _e_path_cache_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
371 {
372    eina_stringshare_del(data);
373    return 1;
374 }