summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-09-16 10:57:48 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-09-16 10:57:48 +0000
commit785f2a6b3a70454ecfe94addc6480ebf20c44c13 (patch)
tree17a195d2c1f022cd480fd0e0b95be5035ad915e2 /src/lib
parentdfc0331373c3f98df7cb996abc588c7dcf44af0a (diff)
merge : add eina
currently, examples, tests and benchmark are not set. That's the next things i'll do SVN revision: 76710
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am2
-rw-r--r--src/lib/eina/Makefile.am111
-rw-r--r--src/lib/eina/eina_accessor.c179
-rw-r--r--src/lib/eina/eina_array.c491
-rw-r--r--src/lib/eina/eina_benchmark.c372
-rw-r--r--src/lib/eina/eina_binbuf.c62
-rw-r--r--src/lib/eina/eina_binbuf_template_c.x153
-rw-r--r--src/lib/eina/eina_binshare.c182
-rw-r--r--src/lib/eina/eina_convert.c482
-rw-r--r--src/lib/eina/eina_counter.c362
-rw-r--r--src/lib/eina/eina_cpu.c224
-rw-r--r--src/lib/eina/eina_error.c279
-rw-r--r--src/lib/eina/eina_file.c1501
-rw-r--r--src/lib/eina/eina_file_win32.c1388
-rw-r--r--src/lib/eina/eina_fp.c486
-rw-r--r--src/lib/eina/eina_hamster.c113
-rw-r--r--src/lib/eina/eina_hash.c1379
-rw-r--r--src/lib/eina/eina_inarray.c795
-rw-r--r--src/lib/eina/eina_inlist.c914
-rw-r--r--src/lib/eina/eina_iterator.c176
-rw-r--r--src/lib/eina/eina_lalloc.c158
-rw-r--r--src/lib/eina/eina_list.c1493
-rw-r--r--src/lib/eina/eina_log.c2099
-rw-r--r--src/lib/eina/eina_magic.c322
-rw-r--r--src/lib/eina/eina_main.c461
-rw-r--r--src/lib/eina/eina_matrixsparse.c1427
-rw-r--r--src/lib/eina/eina_mempool.c391
-rw-r--r--src/lib/eina/eina_mmap.c190
-rw-r--r--src/lib/eina/eina_model.c5551
-rw-r--r--src/lib/eina/eina_module.c603
-rw-r--r--src/lib/eina/eina_object.c852
-rw-r--r--src/lib/eina/eina_prefix.c746
-rw-r--r--src/lib/eina/eina_private.h150
-rw-r--r--src/lib/eina/eina_quadtree.c937
-rw-r--r--src/lib/eina/eina_rbtree.c530
-rw-r--r--src/lib/eina/eina_rectangle.c571
-rw-r--r--src/lib/eina/eina_safety_checks.c90
-rw-r--r--src/lib/eina/eina_sched.c101
-rw-r--r--src/lib/eina/eina_share_common.c949
-rw-r--r--src/lib/eina/eina_share_common.h86
-rw-r--r--src/lib/eina/eina_simple_xml_parser.c1170
-rw-r--r--src/lib/eina/eina_str.c588
-rw-r--r--src/lib/eina/eina_strbuf.c202
-rw-r--r--src/lib/eina/eina_strbuf_common.c874
-rw-r--r--src/lib/eina/eina_strbuf_common.h120
-rw-r--r--src/lib/eina/eina_strbuf_template_c.x97
-rw-r--r--src/lib/eina/eina_stringshare.c795
-rw-r--r--src/lib/eina/eina_tiler.c1290
-rw-r--r--src/lib/eina/eina_unicode.c450
-rw-r--r--src/lib/eina/eina_ustrbuf.c74
-rw-r--r--src/lib/eina/eina_ustringshare.c189
-rw-r--r--src/lib/eina/eina_value.c5308
-rw-r--r--src/lib/eina/eina_xattr.c483
53 files changed, 38998 insertions, 0 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index d89d02e560..92c50645f5 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -7,3 +7,5 @@ if HAVE_WINDOWS
7SUBDIRS += evil 7SUBDIRS += evil
8 8
9endif 9endif
10
11SUBDIRS += eina
diff --git a/src/lib/eina/Makefile.am b/src/lib/eina/Makefile.am
new file mode 100644
index 0000000000..7b1901238f
--- /dev/null
+++ b/src/lib/eina/Makefile.am
@@ -0,0 +1,111 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3AM_CPPFLAGS = \
4-I$(top_srcdir)/src/include/eina \
5-I$(top_builddir)/src/include/eina \
6-DPACKAGE_BIN_DIR=\"$(bindir)\" \
7-DPACKAGE_LIB_DIR=\"$(libdir)\" \
8-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
9@EFL_EINA_BUILD@ \
10@EFL_PTHREAD_CFLAGS@ \
11@EINA_CFLAGS@ \
12@VALGRIND_CFLAGS@
13
14lib_LTLIBRARIES = libeina.la
15
16libeina_la_SOURCES = \
17eina_accessor.c \
18eina_array.c \
19eina_benchmark.c \
20eina_binbuf.c \
21eina_binshare.c \
22eina_convert.c \
23eina_counter.c \
24eina_cpu.c \
25eina_error.c \
26eina_fp.c \
27eina_hamster.c \
28eina_hash.c \
29eina_inarray.c \
30eina_inlist.c \
31eina_iterator.c \
32eina_lalloc.c \
33eina_list.c \
34eina_log.c \
35eina_magic.c \
36eina_main.c \
37eina_matrixsparse.c \
38eina_mempool.c \
39eina_mmap.c \
40eina_module.c \
41eina_prefix.c \
42eina_quadtree.c \
43eina_rbtree.c \
44eina_rectangle.c \
45eina_safety_checks.c \
46eina_sched.c \
47eina_share_common.c \
48eina_simple_xml_parser.c \
49eina_str.c \
50eina_strbuf.c \
51eina_strbuf_common.c \
52eina_stringshare.c \
53eina_tiler.c \
54eina_unicode.c \
55eina_ustrbuf.c \
56eina_ustringshare.c \
57eina_value.c \
58eina_xattr.c \
59eina_share_common.h \
60eina_private.h \
61eina_strbuf_common.h
62
63# Will be back for developper after 1.2
64# eina_model.c \
65# eina_object.c
66
67if HAVE_WIN32
68libeina_la_SOURCES += eina_file_win32.c
69else
70libeina_la_SOURCES += eina_file.c
71endif
72
73EXTRA_DIST = \
74eina_strbuf_template_c.x \
75eina_binbuf_template_c.x
76
77
78
79if EINA_STATIC_BUILD_BUDDY
80libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/buddy/eina_buddy.c
81endif
82
83if EINA_STATIC_BUILD_CHAINED_POOL
84libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/chained_pool/eina_chained_mempool.c
85endif
86
87if EINA_STATIC_BUILD_EMEMOA_FIXED
88libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/ememoa_fixed/eina_ememoa_fixed.c
89endif
90
91if EINA_STATIC_BUILD_EMEMOA_UNKNOWN
92libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/ememoa_unknown/eina_ememoa_unknown.c
93endif
94
95if EINA_STATIC_BUILD_FIXED_BITMAP
96libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/fixed_bitmap/eina_fixed_bitmap.c
97endif
98
99if EINA_STATIC_BUILD_ONE_BIG
100libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/one_big/eina_one_big.c
101endif
102
103if EINA_STATIC_BUILD_PASS_THROUGH
104libeina_la_SOURCES += $(top_srcdir)/src/modules/eina/mp/pass_through/eina_pass_through.c
105endif
106
107libeina_la_LIBADD = @EINA_LIBS@ -lm
108libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@
109
110clean-local:
111 rm -rf *.gcno
diff --git a/src/lib/eina/eina_accessor.c b/src/lib/eina/eina_accessor.c
new file mode 100644
index 0000000000..994704dba9
--- /dev/null
+++ b/src/lib/eina/eina_accessor.c
@@ -0,0 +1,179 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdlib.h>
24
25#include "eina_config.h"
26#include "eina_private.h"
27
28/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
29#include "eina_safety_checks.h"
30#include "eina_accessor.h"
31
32/*============================================================================*
33* Local *
34*============================================================================*/
35
36/**
37 * @cond LOCAL
38 */
39
40static const char EINA_MAGIC_ACCESSOR_STR[] = "Eina Accessor";
41
42#define EINA_MAGIC_CHECK_ACCESSOR(d) \
43 do { \
44 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ACCESSOR)) { \
45 EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); } \
46 } while(0)
47
48/**
49 * @endcond
50 */
51
52/*============================================================================*
53* Global *
54*============================================================================*/
55
56/**
57 * @internal
58 * @brief Initialize the accessor module.
59 *
60 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
61 *
62 * This function sets up the accessor module of Eina. It is called by
63 * eina_init().
64 *
65 * @see eina_init()
66 */
67Eina_Bool
68eina_accessor_init(void)
69{
70 return eina_magic_string_set(EINA_MAGIC_ACCESSOR, EINA_MAGIC_ACCESSOR_STR);
71}
72
73/**
74 * @internal
75 * @brief Shut down the accessor module.
76 *
77 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
78 *
79 * This function shuts down the accessor module set up by
80 * eina_accessor_init(). It is called by eina_shutdown().
81 *
82 * @see eina_shutdown()
83 */
84Eina_Bool
85eina_accessor_shutdown(void)
86{
87 return EINA_TRUE;
88}
89
90/*============================================================================*
91* API *
92*============================================================================*/
93
94
95EAPI void
96eina_accessor_free(Eina_Accessor *accessor)
97{
98 if (!accessor)
99 return;
100
101 EINA_MAGIC_CHECK_ACCESSOR(accessor);
102 EINA_SAFETY_ON_NULL_RETURN(accessor->free);
103 accessor->free(accessor);
104}
105
106EAPI void *
107eina_accessor_container_get(Eina_Accessor *accessor)
108{
109 EINA_MAGIC_CHECK_ACCESSOR(accessor);
110 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, NULL);
111 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_container, NULL);
112 return accessor->get_container(accessor);
113}
114
115EAPI Eina_Bool
116eina_accessor_data_get(Eina_Accessor *accessor,
117 unsigned int position,
118 void **data)
119{
120 EINA_MAGIC_CHECK_ACCESSOR(accessor);
121 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
122 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_at, EINA_FALSE);
123 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
124 return accessor->get_at(accessor, position, data);
125}
126
127EAPI void
128eina_accessor_over(Eina_Accessor *accessor,
129 Eina_Each_Cb cb,
130 unsigned int start,
131 unsigned int end,
132 const void *fdata)
133{
134 const void *container;
135 void *data;
136 unsigned int i;
137
138 if (!accessor) return ;
139
140 EINA_MAGIC_CHECK_ACCESSOR(accessor);
141 EINA_SAFETY_ON_NULL_RETURN(accessor->get_container);
142 EINA_SAFETY_ON_NULL_RETURN(accessor->get_at);
143 EINA_SAFETY_ON_NULL_RETURN(cb);
144 EINA_SAFETY_ON_FALSE_RETURN(start < end);
145
146 if (!eina_accessor_lock(accessor))
147 return ;
148
149 container = accessor->get_container(accessor);
150 for (i = start; i < end && accessor->get_at(accessor, i, &data) == EINA_TRUE;
151 ++i)
152 if (cb(container, data, (void *)fdata) != EINA_TRUE)
153 goto on_exit;
154
155 on_exit:
156 (void) eina_accessor_unlock(accessor);
157}
158
159EAPI Eina_Bool
160eina_accessor_lock(Eina_Accessor *accessor)
161{
162 EINA_MAGIC_CHECK_ACCESSOR(accessor);
163 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
164
165 if (accessor->lock)
166 return accessor->lock(accessor);
167 return EINA_TRUE;
168}
169
170EAPI Eina_Bool
171eina_accessor_unlock(Eina_Accessor *accessor)
172{
173 EINA_MAGIC_CHECK_ACCESSOR(accessor);
174 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
175
176 if (accessor->unlock)
177 return accessor->unlock(accessor);
178 return EINA_TRUE;
179}
diff --git a/src/lib/eina/eina_array.c b/src/lib/eina/eina_array.c
new file mode 100644
index 0000000000..4bcab61a71
--- /dev/null
+++ b/src/lib/eina/eina_array.c
@@ -0,0 +1,491 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include <assert.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28
29#include "eina_config.h"
30#include "eina_private.h"
31#include "eina_error.h"
32#include "eina_log.h"
33
34/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
35#include "eina_safety_checks.h"
36#include "eina_array.h"
37
38/*============================================================================*
39 * Local *
40 *============================================================================*/
41
42/**
43 * @cond LOCAL
44 */
45
46static const char EINA_MAGIC_ARRAY_STR[] = "Eina Array";
47static const char EINA_MAGIC_ARRAY_ITERATOR_STR[] = "Eina Array Iterator";
48static const char EINA_MAGIC_ARRAY_ACCESSOR_STR[] = "Eina Array Accessor";
49
50#define EINA_MAGIC_CHECK_ARRAY(d) \
51 do { \
52 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY)) { \
53 EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY); } \
54 } while (0)
55
56#define EINA_MAGIC_CHECK_ARRAY_ITERATOR(d, ...) \
57 do { \
58 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ITERATOR)) \
59 { \
60 EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY_ITERATOR); \
61 return __VA_ARGS__; \
62 } \
63 } while (0)
64
65#define EINA_MAGIC_CHECK_ARRAY_ACCESSOR(d, ...) \
66 do { \
67 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ACCESSOR)) \
68 { \
69 EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); \
70 return __VA_ARGS__; \
71 } \
72 } while (0)
73
74
75typedef struct _Eina_Iterator_Array Eina_Iterator_Array;
76struct _Eina_Iterator_Array
77{
78 Eina_Iterator iterator;
79
80 const Eina_Array *array;
81 unsigned int index;
82
83 EINA_MAGIC
84};
85
86typedef struct _Eina_Accessor_Array Eina_Accessor_Array;
87struct _Eina_Accessor_Array
88{
89 Eina_Accessor accessor;
90 const Eina_Array *array;
91 EINA_MAGIC
92};
93
94static int _eina_array_log_dom = -1;
95
96#ifdef ERR
97#undef ERR
98#endif
99#define ERR(...) EINA_LOG_DOM_ERR(_eina_array_log_dom, __VA_ARGS__)
100
101#ifdef DBG
102#undef DBG
103#endif
104#define DBG(...) EINA_LOG_DOM_DBG(_eina_array_log_dom, __VA_ARGS__)
105
106static void eina_array_iterator_free(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
107static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
108static Eina_Bool eina_array_iterator_next(Eina_Iterator_Array *it,
109 void **data) EINA_ARG_NONNULL(1);
110
111static Eina_Bool eina_array_accessor_get_at(Eina_Accessor_Array *it,
112 unsigned int idx,
113 void **data) EINA_ARG_NONNULL(1);
114static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
115static void eina_array_accessor_free(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
116
117static Eina_Bool
118eina_array_iterator_next(Eina_Iterator_Array *it, void **data)
119{
120 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
121
122 if (!(it->index < eina_array_count(it->array)))
123 return EINA_FALSE;
124
125 if (data)
126 *data = eina_array_data_get(it->array, it->index);
127
128 it->index++;
129 return EINA_TRUE;
130}
131
132static Eina_Array *
133eina_array_iterator_get_container(Eina_Iterator_Array *it)
134{
135 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, NULL);
136 return (Eina_Array *)it->array;
137}
138
139static void
140eina_array_iterator_free(Eina_Iterator_Array *it)
141{
142 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it);
143 MAGIC_FREE(it);
144}
145
146static Eina_Bool
147eina_array_accessor_get_at(Eina_Accessor_Array *it,
148 unsigned int idx,
149 void **data)
150{
151 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, EINA_FALSE);
152
153 if (!(idx < eina_array_count(it->array)))
154 return EINA_FALSE;
155
156 if (data)
157 *data = eina_array_data_get(it->array, idx);
158
159 return EINA_TRUE;
160}
161
162static Eina_Array *
163eina_array_accessor_get_container(Eina_Accessor_Array *it)
164{
165 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, NULL);
166 return (Eina_Array *)it->array;
167}
168
169static void
170eina_array_accessor_free(Eina_Accessor_Array *it)
171{
172 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it);
173 MAGIC_FREE(it);
174}
175
176/* used from eina_inline_array.x, thus a needed symbol */
177EAPI Eina_Bool
178eina_array_grow(Eina_Array *array)
179{
180 void **tmp;
181 unsigned int total;
182
183 EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
184
185 EINA_MAGIC_CHECK_ARRAY(array);
186
187 total = array->total + array->step;
188 eina_error_set(0);
189 tmp = realloc(array->data, sizeof (void *) * total);
190 if (EINA_UNLIKELY(!tmp))
191 {
192 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
193 return 0;
194 }
195
196 array->total = total;
197 array->data = tmp;
198
199 return 1;
200}
201
202/**
203 * @endcond
204 */
205
206
207/*============================================================================*
208 * Global *
209 *============================================================================*/
210
211/**
212 * @internal
213 * @brief Initialize the array module.
214 *
215 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
216 *
217 * This function sets up the error and magic modules or Eina. It is
218 * called by eina_init().
219 *
220 * @see eina_init()
221 */
222Eina_Bool
223eina_array_init(void)
224{
225 _eina_array_log_dom = eina_log_domain_register("eina_array",
226 EINA_LOG_COLOR_DEFAULT);
227 if (_eina_array_log_dom < 0)
228 {
229 EINA_LOG_ERR("Could not register log domain: eina_array");
230 return EINA_FALSE;
231 }
232
233#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
234 EMS(EINA_MAGIC_ARRAY);
235 EMS(EINA_MAGIC_ARRAY_ITERATOR);
236 EMS(EINA_MAGIC_ARRAY_ACCESSOR);
237#undef EMS
238 return EINA_TRUE;
239}
240
241/**
242 * @internal
243 * @brief Shut down the array module.
244 *
245 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
246 *
247 * This function shuts down the array module set up by
248 * eina_array_init(). It is called by eina_shutdown().
249 *
250 * @see eina_shutdown()
251 */
252Eina_Bool
253eina_array_shutdown(void)
254{
255 eina_log_domain_unregister(_eina_array_log_dom);
256 _eina_array_log_dom = -1;
257 return EINA_TRUE;
258}
259
260/*============================================================================*
261 * API *
262 *============================================================================*/
263
264EAPI Eina_Array *
265eina_array_new(unsigned int step)
266{
267 Eina_Array *array;
268
269 eina_error_set(0);
270 array = malloc(sizeof (Eina_Array));
271 if (!array)
272 {
273 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
274 return NULL;
275 }
276
277 EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
278
279 array->version = EINA_ARRAY_VERSION;
280 array->data = NULL;
281 array->total = 0;
282 array->count = 0;
283 array->step = step;
284
285 return array;
286}
287
288EAPI void
289eina_array_free(Eina_Array *array)
290{
291 eina_array_flush(array);
292
293 EINA_SAFETY_ON_NULL_RETURN(array);
294 EINA_MAGIC_CHECK_ARRAY(array);
295 MAGIC_FREE(array);
296}
297
298EAPI void
299eina_array_step_set(Eina_Array *array,
300 unsigned int sizeof_eina_array,
301 unsigned int step)
302{
303 EINA_SAFETY_ON_NULL_RETURN(array);
304
305 if (sizeof (Eina_Array) != sizeof_eina_array)
306 {
307 ERR("Unknow Eina_Array size ! Got %i, expected %i !\n",
308 sizeof_eina_array,
309 (int) sizeof (Eina_Array));
310 /* Force memory to zero to provide a small layer of security */
311 memset(array, 0, sizeof_eina_array);
312 return ;
313 }
314
315 array->version = EINA_ARRAY_VERSION;
316 array->data = NULL;
317 array->total = 0;
318 array->count = 0;
319 array->step = step;
320 EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
321}
322
323EAPI void
324eina_array_flush(Eina_Array *array)
325{
326 EINA_SAFETY_ON_NULL_RETURN(array);
327 EINA_MAGIC_CHECK_ARRAY(array);
328
329 array->count = 0;
330 array->total = 0;
331
332 if (!array->data)
333 return;
334
335 free(array->data);
336 array->data = NULL;
337}
338
339EAPI Eina_Bool
340eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data,
341 void *gdata),
342 void *gdata)
343{
344 void **tmp;
345 /* WARNING:
346 The algorithm does exit before using unitialized data. So compiler is
347 giving you a false positiv here too.
348 */
349 void *data = NULL;
350 unsigned int total = 0;
351 unsigned int limit;
352 unsigned int i;
353
354 EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
355 EINA_SAFETY_ON_NULL_RETURN_VAL(keep, EINA_FALSE);
356 EINA_MAGIC_CHECK_ARRAY(array);
357
358 if (array->total == 0)
359 return EINA_TRUE;
360
361 for (i = 0; i < array->count; ++i)
362 {
363 data = eina_array_data_get(array, i);
364
365 if (keep(data, gdata) == EINA_FALSE)
366 break;
367 }
368 limit = i;
369 if (i < array->count)
370 ++i;
371
372 for (; i < array->count; ++i)
373 {
374 data = eina_array_data_get(array, i);
375
376 if (keep(data, gdata) == EINA_TRUE)
377 break;
378 }
379 /* Special case all objects that need to stay are at the beginning of the array. */
380 if (i == array->count)
381 {
382 array->count = limit;
383 if (array->count == 0)
384 {
385 free(array->data);
386 array->total = 0;
387 array->data = NULL;
388 }
389
390 return EINA_TRUE;
391 }
392
393 eina_error_set(0);
394 tmp = malloc(sizeof (void *) * array->total);
395 if (!tmp)
396 {
397 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
398 return EINA_FALSE;
399 }
400
401 memcpy(tmp, array->data, limit * sizeof(void *));
402 total = limit;
403
404 if (i < array->count)
405 {
406 tmp[total] = data;
407 total++;
408 ++i;
409 }
410
411 for (; i < array->count; ++i)
412 {
413 data = eina_array_data_get(array, i);
414
415 if (keep(data, gdata))
416 {
417 tmp[total] = data;
418 total++;
419 }
420 }
421
422 free(array->data);
423
424 /* If we do not keep any object in the array, we should have exited
425 earlier in test (i == array->count). */
426 assert(total != 0);
427
428 array->data = tmp;
429 array->count = total;
430 return EINA_TRUE;
431}
432
433EAPI Eina_Iterator *
434eina_array_iterator_new(const Eina_Array *array)
435{
436 Eina_Iterator_Array *it;
437
438 EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
439 EINA_MAGIC_CHECK_ARRAY(array);
440
441 eina_error_set(0);
442 it = calloc(1, sizeof (Eina_Iterator_Array));
443 if (!it)
444 {
445 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
446 return NULL;
447 }
448
449 EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ITERATOR);
450 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
451
452 it->array = array;
453
454 it->iterator.version = EINA_ITERATOR_VERSION;
455 it->iterator.next = FUNC_ITERATOR_NEXT(eina_array_iterator_next);
456 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
457 eina_array_iterator_get_container);
458 it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free);
459
460 return &it->iterator;
461}
462
463EAPI Eina_Accessor *
464eina_array_accessor_new(const Eina_Array *array)
465{
466 Eina_Accessor_Array *ac;
467
468 EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
469 EINA_MAGIC_CHECK_ARRAY(array);
470
471 eina_error_set(0);
472 ac = calloc(1, sizeof (Eina_Accessor_Array));
473 if (!ac)
474 {
475 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
476 return NULL;
477 }
478
479 EINA_MAGIC_SET(ac, EINA_MAGIC_ARRAY_ACCESSOR);
480 EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
481
482 ac->array = array;
483
484 ac->accessor.version = EINA_ACCESSOR_VERSION;
485 ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_array_accessor_get_at);
486 ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
487 eina_array_accessor_get_container);
488 ac->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free);
489
490 return &ac->accessor;
491}
diff --git a/src/lib/eina/eina_benchmark.c b/src/lib/eina/eina_benchmark.c
new file mode 100644
index 0000000000..1ba2a00fec
--- /dev/null
+++ b/src/lib/eina/eina_benchmark.c
@@ -0,0 +1,372 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#ifdef HAVE_ALLOCA_H
24# include <alloca.h>
25#elif defined __GNUC__
26# define alloca __builtin_alloca
27#elif defined _AIX
28# define alloca __alloca
29#elif defined _MSC_VER
30# include <malloc.h>
31# define alloca _alloca
32#else
33# include <stddef.h>
34# ifdef __cplusplus
35extern "C"
36# endif
37void *alloca (size_t);
38#endif
39
40#include <stdlib.h>
41#include <stdio.h>
42#include <string.h>
43
44#ifdef HAVE_EVIL
45# include <Evil.h>
46#endif
47
48#include "eina_config.h"
49#include "eina_private.h"
50#include "eina_log.h"
51#include "eina_benchmark.h"
52#include "eina_inlist.h"
53#include "eina_list.h"
54#include "eina_counter.h"
55
56/*============================================================================*
57* Local *
58*============================================================================*/
59
60/**
61 * @cond LOCAL
62 */
63
64#define EINA_BENCHMARK_FILENAME_MASK "bench_%s_%s.gnuplot"
65#define EINA_BENCHMARK_DATA_MASK "bench_%s_%s.%s.data"
66
67typedef struct _Eina_Run Eina_Run;
68struct _Eina_Run
69{
70 EINA_INLIST;
71
72 Eina_Benchmark_Specimens cb;
73 const char *name;
74 int start;
75 int end;
76 int step;
77};
78
79struct _Eina_Benchmark
80{
81 const char *name;
82 const char *run;
83
84 Eina_Inlist *runs;
85 Eina_List *names;
86};
87
88static int _eina_benchmark_log_dom = -1;
89
90#ifdef ERR
91#undef ERR
92#endif
93#define ERR(...) EINA_LOG_DOM_ERR(_eina_benchmark_log_dom, __VA_ARGS__)
94
95#ifdef DBG
96#undef DBG
97#endif
98#define DBG(...) EINA_LOG_DOM_DBG(_eina_benchmark_log_dom, __VA_ARGS__)
99
100/**
101 * @endcond
102 */
103
104/*============================================================================*
105* Global *
106*============================================================================*/
107
108/**
109 * @internal
110 * @brief Initialize the benchmark module.
111 *
112 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
113 *
114 * This function sets up the benchmark module of Eina. It is called by
115 * eina_init().
116 *
117 * @see eina_init()
118 */
119Eina_Bool
120eina_benchmark_init(void)
121{
122 _eina_benchmark_log_dom = eina_log_domain_register("eina_benchmark",
123 EINA_LOG_COLOR_DEFAULT);
124 if (_eina_benchmark_log_dom < 0)
125 {
126 EINA_LOG_ERR("Could not register log domain: eina_benchmark");
127 return EINA_FALSE;
128 }
129
130 return EINA_TRUE;
131}
132
133/**
134 * @internal
135 * @brief Shut down the benchmark module.
136 *
137 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
138 *
139 * This function shuts down the benchmark module set up by
140 * eina_benchmark_init(). It is called by eina_shutdown().
141 *
142 * @see eina_shutdown()
143 */
144Eina_Bool
145eina_benchmark_shutdown(void)
146{
147 eina_log_domain_unregister(_eina_benchmark_log_dom);
148 _eina_benchmark_log_dom = -1;
149 return EINA_TRUE;
150}
151
152/*============================================================================*
153* API *
154*============================================================================*/
155
156EAPI Eina_Benchmark *
157eina_benchmark_new(const char *name, const char *run)
158{
159 Eina_Benchmark *new;
160
161 eina_error_set(0);
162 new = calloc(1, sizeof (Eina_Benchmark));
163 if (!new)
164 {
165 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
166 return NULL;
167 }
168
169 new->name = name;
170 new->run = run;
171
172 return new;
173}
174
175EAPI void
176eina_benchmark_free(Eina_Benchmark *bench)
177{
178 Eina_Array *names;
179
180 if (!bench)
181 return;
182
183 while (bench->runs)
184 {
185 Eina_Run *run = (Eina_Run *)bench->runs;
186
187 bench->runs = eina_inlist_remove(bench->runs, bench->runs);
188 free(run);
189 }
190
191 EINA_LIST_FREE(bench->names, names)
192 {
193 Eina_Array_Iterator it;
194 char *tmp;
195 unsigned int i;
196
197 EINA_ARRAY_ITER_NEXT(names, i, tmp, it)
198 free(tmp);
199
200 eina_array_free(names);
201 }
202
203 free(bench);
204}
205
206EAPI Eina_Bool
207eina_benchmark_register(Eina_Benchmark *bench,
208 const char *name,
209 Eina_Benchmark_Specimens bench_cb,
210 int count_start,
211 int count_end,
212 int count_step)
213{
214 Eina_Run *run;
215
216 if (!bench)
217 return EINA_FALSE;
218
219 if (count_step == 0)
220 return EINA_FALSE;
221
222 eina_error_set(0);
223 run = calloc(1, sizeof (Eina_Run));
224 if (!run)
225 {
226 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
227 return EINA_FALSE;
228 }
229
230 run->cb = bench_cb;
231 run->name = name;
232 run->start = count_start;
233 run->end = count_end;
234 run->step = count_step;
235
236 bench->runs = eina_inlist_append(bench->runs, EINA_INLIST_GET(run));
237
238 return EINA_TRUE;
239}
240
241EAPI Eina_Array *
242eina_benchmark_run(Eina_Benchmark *bench)
243{
244 FILE *main_script;
245 FILE *current_data;
246 Eina_Array *ea;
247 Eina_Run *run;
248 char *buffer;
249 Eina_Bool first = EINA_FALSE;
250 size_t length;
251
252 if (!bench)
253 return NULL;
254
255 length = strlen(EINA_BENCHMARK_FILENAME_MASK) + strlen(bench->name) + strlen(
256 bench->run);
257
258 buffer = alloca(sizeof (char) * length);
259 if (!buffer)
260 return NULL;
261
262 snprintf(buffer,
263 length,
264 EINA_BENCHMARK_FILENAME_MASK,
265 bench->name,
266 bench->run);
267
268 main_script = fopen(buffer, "w");
269 if (!main_script)
270 return NULL;
271
272 ea = eina_array_new(16);
273 if (!ea)
274 {
275 fclose(main_script);
276 return NULL;
277 }
278
279 eina_array_push(ea, strdup(buffer));
280
281 fprintf(
282 main_script,
283 "set autoscale # scale axes automatically\n"
284 "unset log # remove any log-scaling\n"
285 "unset label # remove any previous labels\n"
286 "set xtic auto # set xtics automatically\n"
287 "set ytic auto # set ytics automatically\n"
288/* "set logscale y\n" */
289 "set terminal png size 1024,768\n"
290 "set output \"output_%s_%s.png\"\n"
291 "set title \"%s %s\n"
292 "set xlabel \"tests\"\n"
293 "set ylabel \"time\"\n"
294 "plot ",
295 bench->name,
296 bench->run,
297 bench->name,
298 bench->run);
299
300 EINA_INLIST_FOREACH(bench->runs, run)
301 {
302 Eina_Counter *counter;
303 char *result;
304 size_t tmp;
305 int i;
306
307 tmp = strlen(EINA_BENCHMARK_DATA_MASK) + strlen(bench->name) + strlen(
308 bench->run) + strlen(run->name);
309 if (tmp > length)
310 {
311 buffer = alloca(sizeof (char) * tmp);
312 length = tmp;
313 }
314
315 snprintf(buffer,
316 length,
317 EINA_BENCHMARK_DATA_MASK,
318 bench->name,
319 bench->run,
320 run->name);
321
322 current_data = fopen(buffer, "w");
323 if (!current_data)
324 continue;
325
326 eina_array_push(ea, strdup(buffer));
327
328 counter = eina_counter_new(run->name);
329
330 for (i = run->start; i < run->end; i += run->step)
331 {
332 fprintf(stderr, "Run %s: %i\n", run->name, i);
333 eina_counter_start(counter);
334
335 run->cb(i);
336
337 eina_counter_stop(counter, i);
338 }
339
340 result = eina_counter_dump(counter);
341 if (result)
342 {
343 fprintf(current_data, "%s", result);
344 free(result);
345 }
346
347 eina_counter_free(counter);
348
349 fclose(current_data);
350
351 if (first == EINA_FALSE)
352 first = EINA_TRUE;
353 else
354 fprintf(main_script, ", \\\n");
355
356 fprintf(main_script,
357 "\"%s\" using 1:2 title \'%s\' with line",
358 buffer, run->name);
359 }
360
361 fprintf(main_script, "\n");
362
363 fclose(main_script);
364
365 bench->names = eina_list_append(bench->names, ea);
366
367 return ea;
368}
369
370/**
371 * @}
372 */
diff --git a/src/lib/eina/eina_binbuf.c b/src/lib/eina/eina_binbuf.c
new file mode 100644
index 0000000000..3cbebd1b2b
--- /dev/null
+++ b/src/lib/eina/eina_binbuf.c
@@ -0,0 +1,62 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdio.h>
6#include <string.h>
7
8#ifdef HAVE_EVIL
9# include <Evil.h>
10#endif
11
12#include "eina_private.h"
13#include "eina_strbuf_common.h"
14#include "eina_binbuf.h"
15
16/*============================================================================*
17 * Local *
18 *============================================================================*/
19
20/**
21 * @cond LOCAL
22 */
23
24#ifdef _STRBUF_DATA_TYPE
25# undef _STRBUF_DATA_TYPE
26#endif
27
28#ifdef _STRBUF_CSIZE
29# undef _STRBUF_CSIZE
30#endif
31
32#ifdef _STRBUF_STRUCT_NAME
33# undef _STRBUF_STRUCT_NAME
34#endif
35
36#ifdef _STRBUF_MAGIC
37# undef _STRBUF_MAGIC
38#endif
39
40#ifdef _STRBUF_MAGIC_STR
41# undef _STRBUF_MAGIC_STR
42#endif
43
44#ifdef _FUNC_EXPAND
45# undef _FUNC_EXPAND
46#endif
47
48
49#define _STRBUF_DATA_TYPE unsigned char
50#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE)
51#define _STRBUF_STRUCT_NAME Eina_Binbuf
52#define _STRBUF_MAGIC EINA_MAGIC_BINBUF
53#define _STRBUF_MAGIC_STR __BINBUF_MAGIC_STR
54static const char __BINBUF_MAGIC_STR[] = "Eina Binbuf";
55
56#define _FUNC_EXPAND(y) eina_binbuf_ ## y
57
58#include "eina_binbuf_template_c.x"
59
60/**
61 * @endcond
62 */
diff --git a/src/lib/eina/eina_binbuf_template_c.x b/src/lib/eina/eina_binbuf_template_c.x
new file mode 100644
index 0000000000..7e0c539f9a
--- /dev/null
+++ b/src/lib/eina/eina_binbuf_template_c.x
@@ -0,0 +1,153 @@
1/*
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */
4
5/* This file should be included from files implementing binbuf.
6 * The including file should define the following macros:
7 * _STRBUF_DATA_TYPE
8 * _STRBUF_CSIZE
9 * _STRBUF_STRUCT_NAME
10 * _STRBUF_MAGIC
11 * _STRBUF_MAGIC_STR
12 * _FUNC_EXPAND
13 * See how it's done in eina_ustrbuf.c and eina_strbuf.c. This just makes things
14 * a lot easier since those are essentially the same just with different sizes.
15 */
16
17/*============================================================================*
18 * Global *
19 *============================================================================*/
20
21/**
22 * @internal
23 * @brief Initialize the strbuf module.
24 *
25 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
26 *
27 * This function sets up the strbuf module of Eina. It is called by
28 * eina_init().
29 *
30 * @see eina_init()
31 */
32Eina_Bool
33_FUNC_EXPAND(init)(void)
34{
35 eina_magic_string_static_set(_STRBUF_MAGIC, _STRBUF_MAGIC_STR);
36 return eina_strbuf_common_init();
37}
38
39/**
40 * @internal
41 * @brief Shut down the strbuf module.
42 *
43 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
44 *
45 * This function shuts down the strbuf module set up by
46 * eina_ustrbuf_init(). It is called by eina_shutdown().
47 *
48 * @see eina_shutdown()
49 */
50Eina_Bool
51_FUNC_EXPAND(shutdown)(void)
52{
53 return eina_strbuf_common_shutdown();
54}
55
56/*============================================================================*
57 * API *
58 *============================================================================*/
59
60EAPI _STRBUF_STRUCT_NAME *
61_FUNC_EXPAND(new)(void)
62{
63 _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_new(_STRBUF_CSIZE);
64 EINA_MAGIC_SET(buf, _STRBUF_MAGIC);
65 return buf;
66}
67
68EAPI _STRBUF_STRUCT_NAME *
69_FUNC_EXPAND(manage_new_length)(_STRBUF_DATA_TYPE *str, size_t length)
70{
71 _STRBUF_STRUCT_NAME *buf =
72 eina_strbuf_common_manage_new(_STRBUF_CSIZE, (void *) str, length);
73 EINA_MAGIC_SET(buf, _STRBUF_MAGIC);
74 return buf;
75}
76
77EAPI void
78_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf)
79{
80 EINA_MAGIC_CHECK_STRBUF(buf);
81 EINA_MAGIC_SET(buf, EINA_MAGIC_NONE);
82 eina_strbuf_common_free(buf);
83}
84
85EAPI void
86_FUNC_EXPAND(reset)(_STRBUF_STRUCT_NAME *buf)
87{
88 EINA_MAGIC_CHECK_STRBUF(buf);
89 eina_strbuf_common_reset(_STRBUF_CSIZE, buf);
90}
91
92EAPI Eina_Bool
93_FUNC_EXPAND(append_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length)
94{
95 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
96 return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, (const void *) str, length);
97}
98
99EAPI Eina_Bool
100_FUNC_EXPAND(insert_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length, size_t pos)
101{
102 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
103 return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, (const void *) str, length, pos);
104}
105
106EAPI Eina_Bool
107_FUNC_EXPAND(append_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c)
108{
109 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
110 return eina_strbuf_common_append_char(_STRBUF_CSIZE, buf, (const void *) &c);
111}
112
113EAPI Eina_Bool
114_FUNC_EXPAND(insert_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c, size_t pos)
115{
116 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
117 return eina_strbuf_common_insert_char(_STRBUF_CSIZE, buf, (const void *) &c, pos);
118}
119
120EAPI Eina_Bool
121_FUNC_EXPAND(remove)(_STRBUF_STRUCT_NAME *buf, size_t start, size_t end)
122{
123 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
124 return eina_strbuf_common_remove(_STRBUF_CSIZE, buf, start, end);
125}
126
127EAPI const _STRBUF_DATA_TYPE *
128_FUNC_EXPAND(string_get)(const _STRBUF_STRUCT_NAME *buf)
129{
130 EINA_MAGIC_CHECK_STRBUF(buf, NULL);
131 return (const _STRBUF_DATA_TYPE *) eina_strbuf_common_string_get(buf);
132}
133
134EAPI _STRBUF_DATA_TYPE *
135_FUNC_EXPAND(string_steal)(_STRBUF_STRUCT_NAME *buf)
136{
137 EINA_MAGIC_CHECK_STRBUF(buf, NULL);
138 return (_STRBUF_DATA_TYPE *) eina_strbuf_common_string_steal(_STRBUF_CSIZE, buf);
139}
140
141EAPI void
142_FUNC_EXPAND(string_free)(_STRBUF_STRUCT_NAME *buf)
143{
144 EINA_MAGIC_CHECK_STRBUF(buf);
145 eina_strbuf_common_string_free(_STRBUF_CSIZE, buf);
146}
147
148EAPI size_t
149_FUNC_EXPAND(length_get)(const _STRBUF_STRUCT_NAME *buf)
150{
151 EINA_MAGIC_CHECK_STRBUF(buf, 0);
152 return eina_strbuf_common_length_get(buf);
153}
diff --git a/src/lib/eina/eina_binshare.c b/src/lib/eina/eina_binshare.c
new file mode 100644
index 0000000000..01e8046e01
--- /dev/null
+++ b/src/lib/eina/eina_binshare.c
@@ -0,0 +1,182 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler,
3 * Jorge Luis Zapata Muga,
4 * Cedric Bail,
5 * Gustavo Sverzut Barbieri
6 * Tom Hacohen
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library;
20 * if not, see <http://www.gnu.org/licenses/>.
21
22 */
23
24#ifdef HAVE_CONFIG_H
25# include "config.h"
26#endif
27
28#include "eina_config.h"
29#include "eina_private.h"
30#include "eina_unicode.h"
31#include "eina_log.h"
32#include "eina_share_common.h"
33
34/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
35#include "eina_safety_checks.h"
36#include "eina_binshare.h"
37
38/*============================================================================*
39 * Local *
40 *============================================================================*/
41
42/**
43 * @cond LOCAL
44 */
45
46#ifdef CRITICAL
47#undef CRITICAL
48#endif
49#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_binshare_log_dom, __VA_ARGS__)
50
51#ifdef ERR
52#undef ERR
53#endif
54#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_binshare_log_dom, __VA_ARGS__)
55
56#ifdef DBG
57#undef DBG
58#endif
59#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_binshare_log_dom, __VA_ARGS__)
60
61static int _eina_share_binshare_log_dom = -1;
62
63/* The actual share */
64static Eina_Share *binshare_share;
65static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node";
66
67/**
68 * @endcond
69 */
70
71/*============================================================================*
72* Global *
73*============================================================================*/
74
75/**
76 * @internal
77 * @brief Initialize the share_common module.
78 *
79 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
80 *
81 * This function sets up the share_common module of Eina. It is called by
82 * eina_init().
83 *
84 * @see eina_init()
85 */
86EAPI Eina_Bool
87eina_binshare_init(void)
88{
89 Eina_Bool ret;
90
91 if (_eina_share_binshare_log_dom < 0)
92 {
93 _eina_share_binshare_log_dom = eina_log_domain_register
94 ("eina_binshare", EINA_LOG_COLOR_DEFAULT);
95
96 if (_eina_share_binshare_log_dom < 0)
97 {
98 EINA_LOG_ERR("Could not register log domain: eina_binshare");
99 return EINA_FALSE;
100 }
101 }
102
103 ret = eina_share_common_init(&binshare_share,
104 EINA_MAGIC_BINSHARE_NODE,
105 EINA_MAGIC_BINSHARE_NODE_STR);
106
107 if (!ret)
108 {
109 eina_log_domain_unregister(_eina_share_binshare_log_dom);
110 _eina_share_binshare_log_dom = -1;
111 }
112
113 return ret;
114}
115
116/**
117 * @internal
118 * @brief Shut down the share_common module.
119 *
120 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
121 *
122 * This function shuts down the share_common module set up by
123 * eina_share_common_init(). It is called by eina_shutdown().
124 *
125 * @see eina_shutdown()
126 */
127EAPI Eina_Bool
128eina_binshare_shutdown(void)
129{
130 Eina_Bool ret;
131 ret = eina_share_common_shutdown(&binshare_share);
132
133 if (_eina_share_binshare_log_dom > 0)
134 {
135 eina_log_domain_unregister(_eina_share_binshare_log_dom);
136 _eina_share_binshare_log_dom = -1;
137 }
138
139 return ret;
140}
141
142
143/*============================================================================*
144 * API *
145 *============================================================================*/
146
147EAPI void
148eina_binshare_del(const void *obj)
149{
150 if (!obj)
151 return;
152
153 if (!eina_share_common_del(binshare_share, obj))
154 CRITICAL("EEEK trying to del non-shared binshare %p", obj);
155}
156
157EAPI const void *
158eina_binshare_add_length(const void *obj, unsigned int olen)
159{
160 return eina_share_common_add_length(binshare_share,
161 obj,
162 (olen) * sizeof(char),
163 0);
164}
165
166EAPI const void *
167eina_binshare_ref(const void *obj)
168{
169 return eina_share_common_ref(binshare_share, obj);
170}
171
172EAPI int
173eina_binshare_length(const void *obj)
174{
175 return eina_share_common_length(binshare_share, obj);
176}
177
178EAPI void
179eina_binshare_dump(void)
180{
181 eina_share_common_dump(binshare_share, NULL, 0);
182}
diff --git a/src/lib/eina/eina_convert.c b/src/lib/eina/eina_convert.c
new file mode 100644
index 0000000000..7e397e0e6e
--- /dev/null
+++ b/src/lib/eina/eina_convert.c
@@ -0,0 +1,482 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric BAIL, Vincent Torri
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <math.h>
24#include <stdlib.h>
25#include <string.h>
26#include <stdio.h>
27
28#ifdef HAVE_EVIL
29# include <Evil.h>
30#endif
31
32#include "eina_config.h"
33#include "eina_private.h"
34#include "eina_log.h"
35
36/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
37#include "eina_safety_checks.h"
38#include "eina_convert.h"
39#include "eina_fp.h"
40
41/*============================================================================*
42* Local *
43*============================================================================*/
44
45/**
46 * @cond LOCAL
47 */
48
49static const char look_up_table[] = {'0', '1', '2', '3', '4',
50 '5', '6', '7', '8', '9',
51 'a', 'b', 'c', 'd', 'e', 'f'};
52static int _eina_convert_log_dom = -1;
53
54#ifdef ERR
55#undef ERR
56#endif
57#define ERR(...) EINA_LOG_DOM_ERR(_eina_convert_log_dom, __VA_ARGS__)
58
59#ifdef DBG
60#undef DBG
61#endif
62#define DBG(...) EINA_LOG_DOM_DBG(_eina_convert_log_dom, __VA_ARGS__)
63
64#define HEXA_TO_INT(Hexa) (Hexa >= 'a') ? Hexa - 'a' + 10 : Hexa - '0'
65
66static inline void reverse(char s[], int length)
67{
68 int i, j;
69 char c;
70
71 for (i = 0, j = length - 1; i < j; i++, j--)
72 {
73 c = s[i];
74 s[i] = s[j];
75 s[j] = c;
76 }
77}
78
79/**
80 * @endcond
81 */
82
83/*============================================================================*
84* Global *
85*============================================================================*/
86
87/**
88 * @cond LOCAL
89 */
90
91EAPI Eina_Error EINA_ERROR_CONVERT_P_NOT_FOUND = 0;
92EAPI Eina_Error EINA_ERROR_CONVERT_0X_NOT_FOUND = 0;
93EAPI Eina_Error EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = 0;
94
95static const char EINA_ERROR_CONVERT_0X_NOT_FOUND_STR[] =
96 "Error during string conversion to float, First '0x' was not found.";
97static const char EINA_ERROR_CONVERT_P_NOT_FOUND_STR[] =
98 "Error during string conversion to float, First 'p' was not found.";
99static const char EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH_STR[] =
100 "Error outrun string limit during conversion string conversion to float.";
101
102/**
103 * @endcond
104 */
105
106/**
107 * @internal
108 * @brief Initialize the convert module.
109 *
110 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
111 *
112 * This function sets up the convert module of Eina. It is called by
113 * eina_init().
114 *
115 * This function sets up the error module of Eina and registers the
116 * errors #EINA_ERROR_CONVERT_0X_NOT_FOUND, #EINA_ERROR_CONVERT_P_NOT_FOUND
117 * and #EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH.
118 *
119 * @see eina_init()
120 */
121Eina_Bool
122eina_convert_init(void)
123{
124 _eina_convert_log_dom = eina_log_domain_register("eina_convert",
125 EINA_LOG_COLOR_DEFAULT);
126 if (_eina_convert_log_dom < 0)
127 {
128 EINA_LOG_ERR("Could not register log domain: eina_convert");
129 return EINA_FALSE;
130 }
131
132#define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
133 EEMR(EINA_ERROR_CONVERT_0X_NOT_FOUND);
134 EEMR(EINA_ERROR_CONVERT_P_NOT_FOUND);
135 EEMR(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
136#undef EEMR
137
138 return EINA_TRUE;
139}
140
141/**
142 * @internal
143 * @brief Shut down the convert module.
144 *
145 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
146 *
147 * This function shuts down the convert module set up by
148 * eina_convert_init(). It is called by eina_shutdown().
149 *
150 * @see eina_shutdown()
151 */
152Eina_Bool
153eina_convert_shutdown(void)
154{
155 eina_log_domain_unregister(_eina_convert_log_dom);
156 _eina_convert_log_dom = -1;
157 return EINA_TRUE;
158}
159
160/*============================================================================*
161* API *
162*============================================================================*/
163
164/*
165 * Come from the second edition of The C Programming Language ("K&R2") on page 64
166 */
167
168EAPI int
169eina_convert_itoa(int n, char *s)
170{
171 int i = 0;
172 int r = 0;
173
174 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
175
176 if (n < 0)
177 {
178 n = -n;
179 *s++ = '-';
180 r = 1;
181 }
182
183 do {
184 s[i++] = n % 10 + '0';
185 } while ((n /= 10) > 0);
186
187 s[i] = '\0';
188
189 reverse(s, i);
190
191 return i + r;
192}
193
194EAPI int
195eina_convert_xtoa(unsigned int n, char *s)
196{
197 int i;
198
199 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
200
201 i = 0;
202 do {
203 s[i++] = look_up_table[n & 0xF];
204 } while ((n >>= 4) > 0);
205
206 s[i] = '\0';
207
208 reverse(s, i);
209
210 return i;
211}
212
213EAPI Eina_Bool
214eina_convert_atod(const char *src, int length, long long *m, long *e)
215{
216 const char *str = src;
217 long long mantisse;
218 long exponent;
219 int nbr_decimals = 0;
220 int sign = 1;
221
222 EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
223 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
225
226 if (length <= 0)
227 goto on_length_error;
228
229 /* Compute the mantisse. */
230 if (*str == '-')
231 {
232 sign = -1;
233 str++;
234 length--;
235 }
236
237 if (length <= 2)
238 goto on_length_error;
239
240 if (strncmp(str, "0x", 2))
241 {
242 eina_error_set(EINA_ERROR_CONVERT_0X_NOT_FOUND);
243 DBG("'0x' not found in '%s'", src);
244 return EINA_FALSE;
245 }
246
247 str += 2;
248 length -= 2;
249
250 mantisse = HEXA_TO_INT(*str);
251
252 str++;
253 length--; if (length <= 0)
254 goto on_length_error;
255
256 if (*str == '.')
257 for (str++, length--;
258 length > 0 && *str != 'p';
259 ++str, --length, ++nbr_decimals)
260 {
261 mantisse <<= 4;
262 mantisse += HEXA_TO_INT(*str);
263 }
264
265 if (sign < 0)
266 mantisse = -mantisse;
267
268 /* Compute the exponent. */
269 if (*str != 'p')
270 {
271 eina_error_set(EINA_ERROR_CONVERT_P_NOT_FOUND);
272 DBG("'p' not found in '%s'", src);
273 return EINA_FALSE;
274 }
275
276 sign = +1;
277
278 str++;
279 length--; if (length <= 0)
280 goto on_length_error;
281
282 if (strchr("-+", *str))
283 {
284 sign = (*str == '-') ? -1 : +1;
285
286 str++; length--;
287 }
288
289 for (exponent = 0; length > 0 && *str != '\0'; ++str, --length)
290 {
291 exponent *= 10;
292 exponent += *str - '0';
293 }
294
295 if (length < 0)
296 goto on_length_error;
297
298 if (sign < 0)
299 exponent = -exponent;
300
301 *m = mantisse;
302 *e = exponent - (nbr_decimals << 2);
303
304 return EINA_TRUE;
305
306on_length_error:
307 eina_error_set(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
308 return EINA_FALSE;
309}
310
311EAPI int
312eina_convert_dtoa(double d, char *des)
313{
314 int length = 0;
315 int p;
316 int i;
317
318 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
319
320 if (d < 0.0)
321 {
322 *(des++) = '-';
323 d = -d;
324 length++;
325 }
326
327 d = frexp(d, &p);
328
329 if (p)
330 {
331 d *= 2;
332 p -= 1;
333 }
334
335 *(des++) = '0';
336 *(des++) = 'x';
337 *(des++) = look_up_table[(size_t)d];
338 *(des++) = '.';
339 length += 4;
340
341 for (i = 0; i < 16; i++, length++)
342 {
343 d -= floor(d);
344 d *= 16;
345 *(des++) = look_up_table[(size_t)d];
346 }
347
348 while (*(des - 1) == '0')
349 {
350 des--;
351 length--;
352 }
353
354 if (*(des - 1) == '.')
355 {
356 des--;
357 length--;
358 }
359
360 *(des++) = 'p';
361 if (p < 0)
362 {
363 *(des++) = '-';
364 p = -p;
365 }
366 else
367 *(des++) = '+';
368
369 length += 2;
370
371 return length + eina_convert_itoa(p, des);
372}
373
374EAPI int
375eina_convert_fptoa(Eina_F32p32 fp, char *des)
376{
377 int length = 0;
378 int p = 0;
379 int i;
380
381 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
382
383 if (fp == 0)
384 {
385 memcpy(des, "0x0p+0", 7);
386 return 7;
387 }
388
389 if (fp < 0)
390 {
391 *(des++) = '-';
392 fp = -fp;
393 length++;
394 }
395
396 /* fp >= 1 */
397 if (fp >= 0x0000000100000000LL)
398 while (fp >= 0x0000000100000000LL)
399 {
400 p++;
401 /* fp /= 2 */
402 fp >>= 1;
403 } /* fp < 0.5 */
404 else if (fp < 0x80000000)
405 while (fp < 0x80000000)
406 {
407 p--;
408 /* fp *= 2 */
409 fp <<= 1;
410 }
411
412 if (p)
413 {
414 p--;
415 /* fp *= 2 */
416 fp <<= 1;
417 }
418
419 *(des++) = '0';
420 *(des++) = 'x';
421 *(des++) = look_up_table[fp >> 32];
422 *(des++) = '.';
423 length += 4;
424
425 for (i = 0; i < 16; i++, length++)
426 {
427 fp &= 0x00000000ffffffffLL;
428 fp <<= 4; /* fp *= 16 */
429 *(des++) = look_up_table[fp >> 32];
430 }
431
432 while (*(des - 1) == '0')
433 {
434 des--;
435 length--;
436 }
437
438 if (*(des - 1) == '.')
439 {
440 des--;
441 length--;
442 }
443
444 *(des++) = 'p';
445 if (p < 0)
446 {
447 *(des++) = '-';
448 p = -p;
449 }
450 else
451 *(des++) = '+';
452
453 length += 2;
454
455 return length + eina_convert_itoa(p, des);
456}
457
458EAPI Eina_Bool
459eina_convert_atofp(const char *src, int length, Eina_F32p32 *fp)
460{
461 long long m;
462 long e;
463
464 if (!eina_convert_atod(src, length, &m, &e))
465 return EINA_FALSE;
466
467 if (!fp)
468 return EINA_FALSE;
469
470 e += 32;
471
472 if (e > 0)
473 *fp = m << e;
474 else
475 *fp = m >> -e;
476
477 return EINA_TRUE;
478}
479
480/**
481 * @}
482 */
diff --git a/src/lib/eina/eina_counter.c b/src/lib/eina/eina_counter.c
new file mode 100644
index 0000000000..6ca94179c9
--- /dev/null
+++ b/src/lib/eina/eina_counter.c
@@ -0,0 +1,362 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail, Vincent Torri
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <stdarg.h>
27#ifndef _WIN32
28# include <time.h>
29# include <sys/time.h>
30#else
31# define WIN32_LEAN_AND_MEAN
32# include <windows.h>
33# undef WIN32_LEAN_AND_MEAN
34#endif /* _WIN2 */
35
36#include "eina_config.h"
37#include "eina_private.h"
38#include "eina_inlist.h"
39#include "eina_error.h"
40
41/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
42#include "eina_safety_checks.h"
43#include "eina_counter.h"
44
45#ifdef HAVE_ESCAPE
46# include <Escape.h>
47#endif
48
49/*============================================================================*
50 * Local *
51 *============================================================================*/
52
53/**
54 * @cond LOCAL
55 */
56
57#ifndef _WIN32
58typedef struct timespec Eina_Nano_Time;
59#else
60typedef LARGE_INTEGER Eina_Nano_Time;
61#endif
62
63typedef struct _Eina_Clock Eina_Clock;
64
65struct _Eina_Counter
66{
67 EINA_INLIST;
68
69 Eina_Inlist *clocks;
70 const char *name;
71};
72
73struct _Eina_Clock
74{
75 EINA_INLIST;
76
77 Eina_Nano_Time start;
78 Eina_Nano_Time end;
79 int specimen;
80
81 Eina_Bool valid;
82};
83
84#ifndef _WIN32
85static inline int
86_eina_counter_time_get(Eina_Nano_Time *tp)
87{
88# if defined(CLOCK_PROCESS_CPUTIME_ID)
89 return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, tp);
90# elif defined(CLOCK_PROF)
91 return clock_gettime(CLOCK_PROF, tp);
92# elif defined(CLOCK_REALTIME)
93 return clock_gettime(CLOCK_REALTIME, tp);
94# else
95 struct timeval tv;
96
97 if (gettimeofday(&tv, NULL))
98 return -1;
99
100 tp->tv_sec = tv.tv_sec;
101 tp->tv_nsec = tv.tv_usec * 1000L;
102
103 return 0;
104# endif
105}
106#else
107static const char EINA_ERROR_COUNTER_WINDOWS_STR[] =
108 "Change your OS, you moron !";
109static int EINA_ERROR_COUNTER_WINDOWS = 0;
110static LARGE_INTEGER _eina_counter_frequency;
111
112static inline int
113_eina_counter_time_get(Eina_Nano_Time *tp)
114{
115 return QueryPerformanceCounter(tp);
116}
117#endif /* _WIN2 */
118
119static char *
120_eina_counter_asiprintf(char *base, int *position, const char *format, ...)
121{
122 char *tmp, *result;
123 int size = 32;
124 int n;
125 va_list ap;
126
127 tmp = realloc(base, sizeof (char) * (*position + size));
128 if (!tmp)
129 return base;
130
131 result = tmp;
132
133 while (1)
134 {
135 va_start(ap, format);
136 n = vsnprintf(result + *position, size, format, ap);
137 va_end(ap);
138
139 if (n > -1 && n < size)
140 {
141 /* If we always have glibc > 2.2, we could just return *position += n. */
142 *position += strlen(result + *position);
143 return result;
144 }
145
146 if (n > -1)
147 size = n + 1;
148 else
149 size <<= 1;
150
151 tmp = realloc(result, sizeof (char) * (*position + size));
152 if (!tmp)
153 return result;
154
155 result = tmp;
156 }
157}
158
159/**
160 * @endcond
161 */
162
163/*============================================================================*
164 * Global *
165 *============================================================================*/
166
167/**
168 * @internal
169 * @brief Initialize the eina counter internal structure.
170 *
171 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
172 *
173 * This function shuts down the counter module set up by
174 * eina_counter_init(). It is called by eina_init().
175 *
176 * This function sets up the error module of Eina and only on Windows,
177 * it initializes the high precision timer. It also registers, only on
178 * Windows, the error #EINA_ERROR_COUNTER_WINDOWS. It is also called
179 * by eina_init(). It returns 0 on failure, otherwise it returns the
180 * number of times it has already been called.
181 *
182 * @see eina_init()
183 */
184Eina_Bool
185eina_counter_init(void)
186{
187#ifdef _WIN32
188 EINA_ERROR_COUNTER_WINDOWS = eina_error_msg_static_register(
189 EINA_ERROR_COUNTER_WINDOWS_STR);
190 if (!QueryPerformanceFrequency(&_eina_counter_frequency))
191 {
192 eina_error_set(EINA_ERROR_COUNTER_WINDOWS);
193 return EINA_FALSE;
194 }
195
196#endif /* _WIN2 */
197 return EINA_TRUE;
198}
199
200/**
201 * @internal
202 * @brief Shut down the counter module.
203 *
204 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
205 *
206 * This function shuts down the counter module set up by
207 * eina_counter_init(). It is called by eina_shutdown().
208 *
209 * @see eina_shutdown()
210 */
211Eina_Bool
212eina_counter_shutdown(void)
213{
214 return EINA_TRUE;
215}
216
217/*============================================================================*
218 * API *
219 *============================================================================*/
220
221EAPI Eina_Counter *
222eina_counter_new(const char *name)
223{
224 Eina_Counter *counter;
225 size_t length;
226
227 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
228
229 length = strlen(name) + 1;
230
231 eina_error_set(0);
232 counter = calloc(1, sizeof (Eina_Counter) + length);
233 if (!counter)
234 {
235 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
236 return NULL;
237 }
238
239 counter->name = (char *)(counter + 1);
240 memcpy((char *)counter->name, name, length);
241
242 return counter;
243}
244
245EAPI void
246eina_counter_free(Eina_Counter *counter)
247{
248 EINA_SAFETY_ON_NULL_RETURN(counter);
249
250 while (counter->clocks)
251 {
252 Eina_Clock *clk = (Eina_Clock *)counter->clocks;
253
254 counter->clocks = eina_inlist_remove(counter->clocks, counter->clocks);
255 free(clk);
256 }
257
258 free(counter);
259}
260
261EAPI void
262eina_counter_start(Eina_Counter *counter)
263{
264 Eina_Clock *clk;
265 Eina_Nano_Time tp;
266
267 EINA_SAFETY_ON_NULL_RETURN(counter);
268 if (_eina_counter_time_get(&tp) != 0)
269 return;
270
271 eina_error_set(0);
272 clk = calloc(1, sizeof (Eina_Clock));
273 if (!clk)
274 {
275 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
276 return;
277 }
278
279 counter->clocks = eina_inlist_prepend(counter->clocks, EINA_INLIST_GET(clk));
280
281 clk->valid = EINA_FALSE;
282 clk->start = tp;
283}
284
285EAPI void
286eina_counter_stop(Eina_Counter *counter, int specimen)
287{
288 Eina_Clock *clk;
289 Eina_Nano_Time tp;
290
291 EINA_SAFETY_ON_NULL_RETURN(counter);
292 if (_eina_counter_time_get(&tp) != 0)
293 return;
294
295 clk = (Eina_Clock *)counter->clocks;
296
297 if (!clk || clk->valid == EINA_TRUE)
298 return;
299
300 clk->end = tp;
301 clk->specimen = specimen;
302 clk->valid = EINA_TRUE;
303}
304
305EAPI char *
306eina_counter_dump(Eina_Counter *counter)
307{
308 Eina_Clock *clk;
309 char *result = NULL;
310 int position = 0;
311
312 EINA_SAFETY_ON_NULL_RETURN_VAL(counter, NULL);
313
314 result = _eina_counter_asiprintf(
315 result,
316 &position,
317 "# specimen\texperiment time\tstarting time\tending time\n");
318 if (!result)
319 return NULL;
320
321 EINA_INLIST_REVERSE_FOREACH(counter->clocks, clk)
322 {
323 long int start;
324 long int end;
325 long int diff;
326
327 if (clk->valid == EINA_FALSE)
328 continue;
329
330#ifndef _WIN32
331 start = clk->start.tv_sec * 1000000000 + clk->start.tv_nsec;
332 end = clk->end.tv_sec * 1000000000 + clk->end.tv_nsec;
333 diff =
334 (clk->end.tv_sec -
335 clk->start.tv_sec) * 1000000000 + clk->end.tv_nsec -
336 clk->start.tv_nsec;
337#else
338 start =
339 (long int)(((long long int)clk->start.QuadPart *
340 1000000000ll) /
341 (long long int)_eina_counter_frequency.QuadPart);
342 end =
343 (long int)(((long long int)clk->end.QuadPart *
344 1000000000LL) /
345 (long long int)_eina_counter_frequency.QuadPart);
346 diff =
347 (long int)(((long long int)(clk->end.QuadPart -
348 clk->start.QuadPart) *
349 1000000000LL) /
350 (long long int)_eina_counter_frequency.QuadPart);
351#endif /* _WIN2 */
352
353 result = _eina_counter_asiprintf(result, &position,
354 "%i\t%li\t%li\t%li\n",
355 clk->specimen,
356 diff,
357 start,
358 end);
359 }
360
361 return result;
362}
diff --git a/src/lib/eina/eina_cpu.c b/src/lib/eina/eina_cpu.c
new file mode 100644
index 0000000000..b5bb2cfc32
--- /dev/null
+++ b/src/lib/eina/eina_cpu.c
@@ -0,0 +1,224 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#ifdef EFL_HAVE_THREADS
24# ifdef _WIN32
25# define WIN32_LEAN_AND_MEAN
26# include <windows.h>
27# elif defined (__sun) || defined(__GNU__)
28# include <unistd.h>
29# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \
30 defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \
31 (defined (__MACH__) && defined (__APPLE__))
32# include <unistd.h>
33# include <sys/param.h>
34# include <sys/sysctl.h>
35# elif defined (__linux__) || defined(__GLIBC__)
36# include <sched.h>
37# endif
38# ifdef EFL_HAVE_POSIX_THREADS
39# include <pthread.h>
40# endif
41
42# define TH_MAX 8
43#endif
44
45#include <stdlib.h>
46#include <stdio.h>
47#include <string.h>
48#include <errno.h>
49
50#include "eina_cpu.h"
51
52/*============================================================================*
53* Local *
54*============================================================================*/
55
56/* FIXME this ifdefs should be replaced */
57#if defined(__i386__) || defined(__x86_64__)
58/* We save ebx and restore it to be PIC compatible */
59static inline void _x86_cpuid(int op, int *a, int *b, int *c, int *d)
60{
61 __asm__ volatile (
62#if defined(__x86_64__)
63 "pushq %%rbx \n\t" /* save %ebx */
64#else
65 "pushl %%ebx \n\t" /* save %ebx */
66#endif
67 "cpuid \n\t"
68 "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */
69#if defined(__x86_64__)
70 "popq %%rbx \n\t" /* restore the old %ebx */
71#else
72 "popl %%ebx \n\t" /* restore the old %ebx */
73#endif
74 : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
75 : "a" (op)
76 : "cc");
77}
78
79static
80void _x86_simd(Eina_Cpu_Features *features)
81{
82 int a, b, c, d;
83
84 _x86_cpuid(1, &a, &b, &c, &d);
85 /*
86 * edx
87 * 18 = PN (Processor Number)
88 * 19 = CLFlush (Cache Line Flush)
89 * 23 = MMX
90 * 25 = SSE
91 * 26 = SSE2
92 * 28 = HTT (Hyper Threading)
93 * ecx
94 * 0 = SSE3
95 */
96 if ((d >> 23) & 1)
97 *features |= EINA_CPU_MMX;
98
99 if ((d >> 25) & 1)
100 *features |= EINA_CPU_SSE;
101
102 if ((d >> 26) & 1)
103 *features |= EINA_CPU_SSE2;
104
105 if (c & 1)
106 *features |= EINA_CPU_SSE3;
107}
108#endif
109
110/*============================================================================*
111* Global *
112*============================================================================*/
113
114/*============================================================================*
115* API *
116*============================================================================*/
117
118/* FIXME the features checks should be called when this function is called?
119 * or make it static by doing eina_cpu_init() and return a local var
120 */
121/**
122 *
123 * @return
124 */
125EAPI Eina_Cpu_Features eina_cpu_features_get(void)
126{
127 Eina_Cpu_Features ecf = 0;
128#if defined(__i386__) || defined(__x86_64__)
129 _x86_simd(&ecf);
130#endif
131 return ecf;
132}
133
134static int _cpu_count = -1;
135
136static int
137_eina_cpu_count_internal(void)
138{
139#ifdef EFL_HAVE_THREADS
140
141# if defined (_WIN32)
142 SYSTEM_INFO sysinfo;
143
144 GetSystemInfo(&sysinfo);
145 return sysinfo.dwNumberOfProcessors;
146
147# elif defined (__sun) || defined(__GNU__)
148 /*
149 * _SC_NPROCESSORS_ONLN: number of processors that are online, that
150 is available when sysconf is called. The number
151 of cpu can change by admins.
152 * _SC_NPROCESSORS_CONF: maximum number of processors that are available
153 to the current OS instance. That number can be
154 change after a reboot.
155 * _SC_NPROCESSORS_MAX : maximum number of processors that are on the
156 motherboard.
157 */
158 return sysconf(_SC_NPROCESSORS_ONLN);
159
160# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \
161 defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \
162 (defined (__MACH__) && defined (__APPLE__))
163
164 int mib[4];
165 int cpus;
166 size_t len = sizeof(cpus);
167
168 mib[0] = CTL_HW;
169#ifdef HW_AVAILCPU
170 mib[1] = HW_AVAILCPU;
171#else
172 mib[1] = HW_NCPU;
173#endif
174 sysctl(mib, 2, &cpus, &len, NULL, 0);
175 if (cpus < 1)
176 cpus = 1;
177
178 return cpus;
179
180# elif defined (__linux__) || defined(__GLIBC__)
181 cpu_set_t cpu;
182 int i;
183 static int cpus = 0;
184
185 if (cpus != 0)
186 return cpus;
187
188 CPU_ZERO(&cpu);
189 if (sched_getaffinity(0, sizeof(cpu), &cpu) != 0)
190 {
191 fprintf(stderr, "[Eina] could not get cpu affinity: %s\n",
192 strerror(errno));
193 return 1;
194 }
195
196 for (i = 0; i < TH_MAX; i++)
197 {
198 if (CPU_ISSET(i, &cpu))
199 cpus = i + 1;
200 else
201 break;
202 }
203 return cpus;
204
205# else
206# error "eina_cpu_count() error: Platform not supported"
207# endif
208#else
209 return 1;
210#endif
211}
212
213EAPI int eina_cpu_count(void)
214{
215 return _cpu_count;
216}
217
218void eina_cpu_count_internal(void)
219{
220 if (getenv("EINA_CPU_FAKE"))
221 _cpu_count = atoi(getenv("EINA_CPU_FAKE"));
222 else
223 _cpu_count = _eina_cpu_count_internal();
224}
diff --git a/src/lib/eina/eina_error.c b/src/lib/eina/eina_error.c
new file mode 100644
index 0000000000..428c4146b9
--- /dev/null
+++ b/src/lib/eina/eina_error.c
@@ -0,0 +1,279 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26
27#ifdef HAVE_EVIL
28# include <Evil.h>
29#endif
30
31#include "eina_config.h"
32#include "eina_private.h"
33
34
35/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
36#include "eina_safety_checks.h"
37#include "eina_error.h"
38#include "eina_stringshare.h"
39
40/* TODO
41 * + add a wrapper for assert?
42 * + add common error numbers, messages
43 * + add a calltrace of errors, not only store the last error but a list of them
44 * and also store the function that set it
45 */
46
47/*============================================================================*
48* Local *
49*============================================================================*/
50
51/**
52 * @cond LOCAL
53 */
54
55typedef struct _Eina_Error_Message Eina_Error_Message;
56struct _Eina_Error_Message
57{
58 Eina_Bool string_allocated;
59 const char *string;
60};
61
62static Eina_Error_Message *_eina_errors = NULL;
63static size_t _eina_errors_count = 0;
64static size_t _eina_errors_allocated = 0;
65static Eina_Error _eina_last_error;
66
67static Eina_Error_Message *
68_eina_error_msg_alloc(void)
69{
70 size_t idx;
71
72 if (_eina_errors_count == _eina_errors_allocated)
73 {
74 void *tmp;
75 size_t size;
76
77 if (EINA_UNLIKELY(_eina_errors_allocated == 0))
78 size = 24;
79 else
80 size = _eina_errors_allocated + 8;
81
82 tmp = realloc(_eina_errors, sizeof(Eina_Error_Message) * size);
83 if (!tmp)
84 return NULL;
85
86 _eina_errors = tmp;
87 _eina_errors_allocated = size;
88 }
89
90 idx = _eina_errors_count;
91 _eina_errors_count++;
92 return _eina_errors + idx;
93}
94
95/**
96 * @endcond
97 */
98
99
100/*============================================================================*
101* Global *
102*============================================================================*/
103
104/**
105 * @cond LOCAL
106 */
107
108EAPI Eina_Error EINA_ERROR_OUT_OF_MEMORY = 0;
109
110static const char EINA_ERROR_OUT_OF_MEMORY_STR[] = "Out of memory";
111
112/**
113 * @endcond
114 */
115
116/**
117 * @internal
118 * @brief Initialize the error module.
119 *
120 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
121 *
122 * This function sets up the error module of Eina. It is called by
123 * eina_init().
124 *
125 * This function registers the error #EINA_ERROR_OUT_OF_MEMORY.
126 *
127 * @see eina_init()
128 */
129Eina_Bool
130eina_error_init(void)
131{
132 /* TODO register the eina's basic errors */
133 EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_static_register(
134 EINA_ERROR_OUT_OF_MEMORY_STR);
135 return EINA_TRUE;
136}
137
138/**
139 * @internal
140 * @brief Shut down the error module.
141 *
142 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
143 *
144 * This function shuts down the error module set up by
145 * eina_error_init(). It is called by eina_shutdown().
146 *
147 * @see eina_shutdown()
148 */
149Eina_Bool
150eina_error_shutdown(void)
151{
152 Eina_Error_Message *eem, *eem_end;
153
154 eem = _eina_errors;
155 eem_end = eem + _eina_errors_count;
156
157 for (; eem < eem_end; eem++)
158 if (eem->string_allocated)
159 eina_stringshare_del(eem->string);
160
161 free(_eina_errors);
162 _eina_errors = NULL;
163 _eina_errors_count = 0;
164 _eina_errors_allocated = 0;
165
166 return EINA_TRUE;
167}
168
169/*============================================================================*
170* API *
171*============================================================================*/
172
173EAPI Eina_Error
174eina_error_msg_register(const char *msg)
175{
176 Eina_Error_Message *eem;
177
178 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
179
180 eem = _eina_error_msg_alloc();
181 if (!eem)
182 return 0;
183
184 eem->string_allocated = EINA_TRUE;
185 eem->string = eina_stringshare_add(msg);
186 if (!eem->string)
187 {
188 _eina_errors_count--;
189 return 0;
190 }
191
192 return _eina_errors_count; /* identifier = index + 1 (== _count). */
193}
194
195EAPI Eina_Error
196eina_error_msg_static_register(const char *msg)
197{
198 Eina_Error_Message *eem;
199
200 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
201
202 eem = _eina_error_msg_alloc();
203 if (!eem)
204 return 0;
205
206 eem->string_allocated = EINA_FALSE;
207 eem->string = msg;
208 return _eina_errors_count; /* identifier = index + 1 (== _count). */
209}
210
211EAPI Eina_Bool
212eina_error_msg_modify(Eina_Error error, const char *msg)
213{
214 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
215 if (error < 1)
216 return EINA_FALSE;
217
218 if ((size_t)error > _eina_errors_count)
219 return EINA_FALSE;
220
221 if (_eina_errors[error - 1].string_allocated)
222 {
223 const char *tmp;
224
225 if (!(tmp = eina_stringshare_add(msg)))
226 return EINA_FALSE;
227
228 eina_stringshare_del(_eina_errors[error - 1].string);
229 _eina_errors[error - 1].string = tmp;
230 return EINA_TRUE;
231 }
232
233 _eina_errors[error - 1].string = msg;
234 return EINA_TRUE;
235}
236
237EAPI const char *
238eina_error_msg_get(Eina_Error error)
239{
240 if (error < 1)
241 return NULL;
242
243 if ((size_t)error > _eina_errors_count)
244 return NULL;
245
246 return _eina_errors[error - 1].string;
247}
248
249EAPI Eina_Error
250eina_error_get(void)
251{
252 return _eina_last_error;
253}
254
255EAPI void
256eina_error_set(Eina_Error err)
257{
258 _eina_last_error = err;
259}
260
261EAPI Eina_Error
262eina_error_find(const char *msg)
263{
264 size_t i;
265
266 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
267
268 for (i = 0; i < _eina_errors_count; i++)
269 {
270 if (_eina_errors[i].string_allocated)
271 {
272 if (_eina_errors[i].string == msg)
273 return i + 1;
274 }
275 if (!strcmp(_eina_errors[i].string, msg))
276 return i + 1;
277 }
278 return 0;
279}
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
new file mode 100644
index 0000000000..d34f917b1b
--- /dev/null
+++ b/src/lib/eina/eina_file.c
@@ -0,0 +1,1501 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Vincent Torri
3 * Copyright (C) 2010-2011 Cedric Bail
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#ifdef HAVE_ALLOCA_H
25# include <alloca.h>
26#elif defined __GNUC__
27# define alloca __builtin_alloca
28#elif defined _AIX
29# define alloca __alloca
30#elif defined _MSC_VER
31# include <malloc.h>
32# define alloca _alloca
33#else
34# include <stddef.h>
35# ifdef __cplusplus
36extern "C"
37# endif
38void *alloca (size_t);
39#endif
40
41#include <stdlib.h>
42#include <string.h>
43#include <stddef.h>
44#include <stdint.h>
45#ifdef HAVE_DIRENT_H
46# include <dirent.h>
47#endif
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <unistd.h>
51#ifdef HAVE_SYS_MMAN_H
52# include <sys/mman.h>
53#endif
54#include <fcntl.h>
55
56#define PATH_DELIM '/'
57
58#include "eina_config.h"
59#include "eina_private.h"
60
61/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
62#include "eina_safety_checks.h"
63#include "eina_file.h"
64#include "eina_stringshare.h"
65#include "eina_hash.h"
66#include "eina_list.h"
67#include "eina_lock.h"
68#include "eina_mmap.h"
69#include "eina_log.h"
70#include "eina_xattr.h"
71
72#ifdef HAVE_ESCAPE
73# include <Escape.h>
74#endif
75
76/*============================================================================*
77 * Local *
78 *============================================================================*/
79
80/**
81 * @cond LOCAL
82 */
83
84#ifndef EINA_LOG_COLOR_DEFAULT
85#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
86#endif
87
88#ifdef ERR
89#undef ERR
90#endif
91#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
92
93#ifdef WRN
94#undef WRN
95#endif
96#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
97
98#ifdef DBG
99#undef DBG
100#endif
101#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
102
103#define EINA_SMALL_PAGE 4096
104# define EINA_HUGE_PAGE 16 * 1024 * 1024
105
106#ifdef HAVE_DIRENT_H
107typedef struct _Eina_File_Iterator Eina_File_Iterator;
108struct _Eina_File_Iterator
109{
110 Eina_Iterator iterator;
111
112 DIR *dirp;
113 int length;
114
115 char dir[1];
116};
117#endif
118
119struct _Eina_File
120{
121 const char *filename;
122
123 Eina_Hash *map;
124 Eina_Hash *rmap;
125 void *global_map;
126
127 Eina_Lock lock;
128
129 unsigned long long length;
130 time_t mtime;
131 ino_t inode;
132#ifdef _STAT_VER_LINUX
133 unsigned long int mtime_nsec;
134#endif
135
136 int refcount;
137 int global_refcount;
138
139 int fd;
140
141 Eina_Bool shared : 1;
142 Eina_Bool delete_me : 1;
143 Eina_Bool global_faulty : 1;
144};
145
146typedef struct _Eina_File_Map Eina_File_Map;
147struct _Eina_File_Map
148{
149 void *map;
150
151 unsigned long int offset;
152 unsigned long int length;
153
154 int refcount;
155
156 Eina_Bool hugetlb : 1;
157 Eina_Bool faulty : 1;
158};
159
160static Eina_Hash *_eina_file_cache = NULL;
161static Eina_Lock _eina_file_lock_cache;
162
163static int _eina_file_log_dom = -1;
164
165/*
166 * This complex piece of code is needed due to possible race condition.
167 * The code and description of the issue can be found at :
168 * http://womble.decadent.org.uk/readdir_r-advisory.html
169 */
170#ifdef HAVE_DIRENT_H
171static long
172_eina_name_max(DIR *dirp)
173{
174 long name_max;
175
176#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX)
177 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
178
179 if (name_max == -1)
180 {
181# if defined(NAME_MAX)
182 name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
183# else
184 name_max = PATH_MAX;
185# endif
186 }
187#else
188# if defined(NAME_MAX)
189 name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
190# else
191# ifdef _PC_NAME_MAX
192# warning "buffer size for readdir_r cannot be determined safely, best effort, but racy"
193 name_max = pathconf(dirp, _PC_NAME_MAX);
194# else
195# error "buffer size for readdir_r cannot be determined safely"
196# endif
197# endif
198#endif
199
200 return name_max;
201}
202
203static size_t
204_eina_dirent_buffer_size(DIR *dirp)
205{
206 long name_max = _eina_name_max(dirp);
207 size_t name_end;
208
209 name_end = (size_t) offsetof(struct dirent, d_name) + name_max + 1;
210
211 return (name_end > sizeof (struct dirent) ? name_end : sizeof (struct dirent));
212}
213
214static Eina_Bool
215_eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data)
216{
217 struct dirent *dp;
218 char *name;
219 size_t length;
220
221 dp = alloca(_eina_dirent_buffer_size(it->dirp));
222
223 do
224 {
225 if (readdir_r(it->dirp, dp, &dp))
226 return EINA_FALSE;
227 if (dp == NULL)
228 return EINA_FALSE;
229 }
230 while ((dp->d_name[0] == '.') &&
231 ((dp->d_name[1] == '\0') ||
232 ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
233
234#ifdef _DIRENT_HAVE_D_NAMLEN
235 length = dp->d_namlen;
236#else
237 length = strlen(dp->d_name);
238#endif
239 name = alloca(length + 2 + it->length);
240
241 memcpy(name, it->dir, it->length);
242 memcpy(name + it->length, "/", 1);
243 memcpy(name + it->length + 1, dp->d_name, length + 1);
244
245 *data = (char *)eina_stringshare_add(name);
246 return EINA_TRUE;
247}
248
249static DIR *
250_eina_file_ls_iterator_container(Eina_File_Iterator *it)
251{
252 return it->dirp;
253}
254
255static void
256_eina_file_ls_iterator_free(Eina_File_Iterator *it)
257{
258 closedir(it->dirp);
259
260 EINA_MAGIC_SET(&it->iterator, 0);
261 free(it);
262}
263
264typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
265struct _Eina_File_Direct_Iterator
266{
267 Eina_Iterator iterator;
268
269 DIR *dirp;
270 int length;
271
272 Eina_File_Direct_Info info;
273
274 char dir[1];
275};
276
277static Eina_Bool
278_eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
279{
280 struct dirent *dp;
281 size_t length;
282
283 dp = alloca(_eina_dirent_buffer_size(it->dirp));
284
285 do
286 {
287 if (readdir_r(it->dirp, dp, &dp))
288 return EINA_FALSE;
289 if (!dp)
290 return EINA_FALSE;
291
292#ifdef _DIRENT_HAVE_D_NAMLEN
293 length = dp->d_namlen;
294#else
295 length = strlen(dp->d_name);
296#endif
297 if (it->info.name_start + length + 1 >= EINA_PATH_MAX)
298 continue;
299 }
300 while ((dp->d_name[0] == '.') &&
301 ((dp->d_name[1] == '\0') ||
302 ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
303
304 memcpy(it->info.path + it->info.name_start, dp->d_name, length);
305 it->info.name_length = length;
306 it->info.path_length = it->info.name_start + length;
307 it->info.path[it->info.path_length] = '\0';
308
309#ifdef _DIRENT_HAVE_D_TYPE
310 switch (dp->d_type)
311 {
312 case DT_FIFO:
313 it->info.type = EINA_FILE_FIFO;
314 break;
315 case DT_CHR:
316 it->info.type = EINA_FILE_CHR;
317 break;
318 case DT_DIR:
319 it->info.type = EINA_FILE_DIR;
320 break;
321 case DT_BLK:
322 it->info.type = EINA_FILE_BLK;
323 break;
324 case DT_REG:
325 it->info.type = EINA_FILE_REG;
326 break;
327 case DT_LNK:
328 it->info.type = EINA_FILE_LNK;
329 break;
330 case DT_SOCK:
331 it->info.type = EINA_FILE_SOCK;
332 break;
333 case DT_WHT:
334 it->info.type = EINA_FILE_WHT;
335 break;
336 default:
337 it->info.type = EINA_FILE_UNKNOWN;
338 break;
339 }
340#else
341 it->info.type = EINA_FILE_UNKNOWN;
342#endif
343
344 *data = &it->info;
345 return EINA_TRUE;
346}
347
348static DIR *
349_eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
350{
351 return it->dirp;
352}
353
354static void
355_eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
356{
357 closedir(it->dirp);
358
359 EINA_MAGIC_SET(&it->iterator, 0);
360 free(it);
361}
362
363static Eina_Bool
364_eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
365{
366 Eina_Stat st;
367
368 if (!_eina_file_direct_ls_iterator_next(it, data))
369 return EINA_FALSE;
370
371 if (it->info.type == EINA_FILE_UNKNOWN)
372 {
373 if (eina_file_statat(it->dirp, &it->info, &st) != 0)
374 it->info.type = EINA_FILE_UNKNOWN;
375 }
376
377 return EINA_TRUE;
378}
379#endif
380
381static void
382_eina_file_real_close(Eina_File *file)
383{
384 if (file->refcount != 0) return;
385
386 eina_hash_free(file->rmap);
387 eina_hash_free(file->map);
388
389 if (file->global_map != MAP_FAILED)
390 munmap(file->global_map, file->length);
391
392 close(file->fd);
393
394 free(file);
395}
396
397static void
398_eina_file_map_close(Eina_File_Map *map)
399{
400 munmap(map->map, map->length);
401 free(map);
402}
403
404static unsigned int
405_eina_file_map_key_length(const void *key __UNUSED__)
406{
407 return sizeof (unsigned long int) * 2;
408}
409
410static int
411_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__,
412 const unsigned long int *key2, int key2_length __UNUSED__)
413{
414 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
415 return key1[0] - key2[0];
416}
417
418static int
419_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__)
420{
421 return eina_hash_int64(&key[0], sizeof (unsigned long int))
422 ^ eina_hash_int64(&key[1], sizeof (unsigned long int));
423}
424
425#ifndef MAP_POPULATE
426static unsigned int
427_eina_file_map_populate(char *map, unsigned int size, Eina_Bool hugetlb)
428{
429 unsigned int r = 0xDEADBEEF;
430 unsigned int i;
431 unsigned int s;
432
433 s = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE;
434
435 for (i = 0; i < size; i += s)
436 r ^= map[i];
437
438 r ^= map[size];
439
440 return r;
441}
442#endif
443
444static int
445_eina_file_map_rule_apply(Eina_File_Populate rule, void *addr, unsigned long int size, Eina_Bool hugetlb)
446{
447 int tmp = 42;
448 int flag = MADV_RANDOM;
449
450 switch (rule)
451 {
452 case EINA_FILE_RANDOM: flag = MADV_RANDOM; break;
453 case EINA_FILE_SEQUENTIAL: flag = MADV_SEQUENTIAL; break;
454 case EINA_FILE_POPULATE: flag = MADV_WILLNEED; break;
455 case EINA_FILE_WILLNEED: flag = MADV_WILLNEED; break;
456 }
457
458 madvise(addr, size, flag);
459
460#ifndef MAP_POPULATE
461 if (rule == EINA_FILE_POPULATE)
462 tmp ^= _eina_file_map_populate(addr, size, hugetlb);
463#else
464 (void) hugetlb;
465#endif
466
467 return tmp;
468}
469
470static Eina_Bool
471_eina_file_timestamp_compare(Eina_File *f, struct stat *st)
472{
473 if (f->mtime != st->st_mtime) return EINA_FALSE;
474 if (f->length != (unsigned long long) st->st_size) return EINA_FALSE;
475 if (f->inode != st->st_ino) return EINA_FALSE;
476#ifdef _STAT_VER_LINUX
477# if (defined __USE_MISC && defined st_mtime)
478 if (f->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
479 return EINA_FALSE;
480# else
481 if (f->mtime_nsec != (unsigned long int)st->st_mtimensec)
482 return EINA_FALSE;
483# endif
484#endif
485 return EINA_TRUE;
486}
487
488static void
489slprintf(char *str, size_t size, const char *format, ...)
490{
491 va_list ap;
492
493 va_start(ap, format);
494
495 vsnprintf(str, size, format, ap);
496 str[size - 1] = 0;
497
498 va_end(ap);
499}
500
501static char *
502_eina_file_escape(const char *path, int *length)
503{
504 char *result;
505 char *p;
506 char *q;
507 size_t len;
508
509 result = strdup(path ? path : "");
510 p = result;
511 q = result;
512
513 if (!result)
514 return NULL;
515
516 if (length) len = *length;
517 else len = strlen(result);
518
519 while ((p = strchr(p, '/')))
520 {
521 // remove double `/'
522 if (p[1] == '/')
523 {
524 memmove(p, p + 1, --len - (p - result));
525 result[len] = '\0';
526 }
527 else
528 if (p[1] == '.'
529 && p[2] == '.')
530 {
531 // remove `/../'
532 if (p[3] == '/')
533 {
534 char tmp;
535
536 len -= p + 3 - q;
537 memmove(q, p + 3, len - (q - result));
538 result[len] = '\0';
539 p = q;
540
541 /* Update q correctly. */
542 tmp = *p;
543 *p = '\0';
544 q = strrchr(result, '/');
545 if (!q) q = result;
546 *p = tmp;
547 }
548 else
549 // remove '/..$'
550 if (p[3] == '\0')
551 {
552 len -= p + 2 - q;
553 result[len] = '\0';
554 q = p;
555 ++p;
556 }
557 else
558 {
559 q = p;
560 ++p;
561 }
562 }
563 else
564 {
565 q = p;
566 ++p;
567 }
568 }
569
570 if (length)
571 *length = len;
572 return result;
573}
574
575/**
576 * @endcond
577 */
578
579/*============================================================================*
580 * Global *
581 *============================================================================*/
582
583Eina_Bool
584eina_file_init(void)
585{
586 _eina_file_log_dom = eina_log_domain_register("eina_file",
587 EINA_LOG_COLOR_DEFAULT);
588 if (_eina_file_log_dom < 0)
589 {
590 EINA_LOG_ERR("Could not register log domain: eina_file");
591 return EINA_FALSE;
592 }
593
594 _eina_file_cache = eina_hash_string_djb2_new(NULL);
595 if (!_eina_file_cache)
596 {
597 ERR("Could not create cache.");
598 eina_log_domain_unregister(_eina_file_log_dom);
599 _eina_file_log_dom = -1;
600 return EINA_FALSE;
601 }
602
603 eina_lock_new(&_eina_file_lock_cache);
604
605 return EINA_TRUE;
606}
607
608Eina_Bool
609eina_file_shutdown(void)
610{
611 if (eina_hash_population(_eina_file_cache) > 0)
612 {
613 Eina_Iterator *it;
614 const char *key;
615
616 it = eina_hash_iterator_key_new(_eina_file_cache);
617 EINA_ITERATOR_FOREACH(it, key)
618 ERR("File [%s] still open !", key);
619 eina_iterator_free(it);
620 }
621
622 eina_hash_free(_eina_file_cache);
623
624 eina_lock_free(&_eina_file_lock_cache);
625
626 eina_log_domain_unregister(_eina_file_log_dom);
627 _eina_file_log_dom = -1;
628 return EINA_TRUE;
629}
630
631void
632eina_file_mmap_faulty(void *addr, long page_size)
633{
634 Eina_File_Map *m;
635 Eina_File *f;
636 Eina_Iterator *itf;
637 Eina_Iterator *itm;
638
639 /* NOTE: I actually don't know if other thread are running, I will try to take the lock.
640 It may be possible that if other thread are not running and they were in the middle of
641 accessing an Eina_File this lock are still taken and we will result as a deadlock. */
642 eina_lock_take(&_eina_file_lock_cache);
643
644 itf = eina_hash_iterator_data_new(_eina_file_cache);
645 EINA_ITERATOR_FOREACH(itf, f)
646 {
647 Eina_Bool faulty = EINA_FALSE;
648
649 eina_lock_take(&f->lock);
650
651 if (f->global_map)
652 {
653 if ((unsigned char *) addr < (((unsigned char *)f->global_map) + f->length) &&
654 (((unsigned char *) addr) + page_size) >= (unsigned char *) f->global_map)
655 {
656 f->global_faulty = EINA_TRUE;
657 faulty = EINA_TRUE;
658 }
659 }
660
661 if (!faulty)
662 {
663 itm = eina_hash_iterator_data_new(f->map);
664 EINA_ITERATOR_FOREACH(itm, m)
665 {
666 if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
667 (((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
668 {
669 m->faulty = EINA_TRUE;
670 faulty = EINA_TRUE;
671 break;
672 }
673 }
674 eina_iterator_free(itm);
675 }
676
677 eina_lock_release(&f->lock);
678
679 if (faulty) break;
680 }
681 eina_iterator_free(itf);
682
683 eina_lock_release(&_eina_file_lock_cache);
684}
685
686/*============================================================================*
687 * API *
688 *============================================================================*/
689
690EAPI char *
691eina_file_path_sanitize(const char *path)
692{
693 char *result = NULL;
694 int len;
695
696 if (!path) return NULL;
697
698 len = strlen(path);
699
700 if (*path != '/')
701 {
702 char cwd[PATH_MAX];
703 char *tmp = NULL;
704
705 tmp = getcwd(cwd, PATH_MAX);
706 if (!tmp) return NULL;
707
708 len += strlen(cwd) + 2;
709 tmp = alloca(sizeof (char) * len);
710
711 slprintf(tmp, len, "%s/%s", cwd, path);
712
713 result = tmp;
714 }
715
716 return _eina_file_escape(result ? result : path, &len);
717}
718
719EAPI Eina_Bool
720eina_file_dir_list(const char *dir,
721 Eina_Bool recursive,
722 Eina_File_Dir_List_Cb cb,
723 void *data)
724{
725 Eina_File_Direct_Info *info;
726 Eina_Iterator *it;
727
728 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
729 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
730 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
731
732 it = eina_file_stat_ls(dir);
733 if (!it)
734 return EINA_FALSE;
735
736 EINA_ITERATOR_FOREACH(it, info)
737 {
738 cb(info->path + info->name_start, dir, data);
739
740 if (recursive == EINA_TRUE && info->type == EINA_FILE_DIR)
741 {
742 eina_file_dir_list(info->path, recursive, cb, data);
743 }
744 }
745
746 eina_iterator_free(it);
747
748 return EINA_TRUE;
749}
750
751EAPI Eina_Array *
752eina_file_split(char *path)
753{
754 Eina_Array *ea;
755 char *current;
756 size_t length;
757
758 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
759
760 ea = eina_array_new(16);
761
762 if (!ea)
763 return NULL;
764
765 for (current = strchr(path, PATH_DELIM);
766 current;
767 path = current + 1, current = strchr(path, PATH_DELIM))
768 {
769 length = current - path;
770
771 if (length <= 0)
772 continue;
773
774 eina_array_push(ea, path);
775 *current = '\0';
776 }
777
778 if (*path != '\0')
779 eina_array_push(ea, path);
780
781 return ea;
782}
783
784EAPI Eina_Iterator *
785eina_file_ls(const char *dir)
786{
787#ifdef HAVE_DIRENT_H
788 Eina_File_Iterator *it;
789 size_t length;
790
791 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
792
793 length = strlen(dir);
794 if (length < 1)
795 return NULL;
796
797 it = calloc(1, sizeof (Eina_File_Iterator) + length);
798 if (!it)
799 return NULL;
800
801 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
802
803 it->dirp = opendir(dir);
804 if (!it->dirp)
805 {
806 free(it);
807 return NULL;
808 }
809
810 memcpy(it->dir, dir, length + 1);
811 if (dir[length - 1] != '/')
812 it->length = length;
813 else
814 it->length = length - 1;
815
816 it->iterator.version = EINA_ITERATOR_VERSION;
817 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_ls_iterator_next);
818 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
819 _eina_file_ls_iterator_container);
820 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free);
821
822 return &it->iterator;
823#else
824 (void) dir;
825 return NULL;
826#endif
827}
828
829EAPI Eina_Iterator *
830eina_file_direct_ls(const char *dir)
831{
832#ifdef HAVE_DIRENT_H
833 Eina_File_Direct_Iterator *it;
834 size_t length;
835
836 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
837
838 length = strlen(dir);
839 if (length < 1)
840 return NULL;
841
842 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
843 if (!it)
844 return NULL;
845
846 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
847
848 it->dirp = opendir(dir);
849 if (!it->dirp)
850 {
851 free(it);
852 return NULL;
853 }
854
855 if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX)
856 {
857 _eina_file_direct_ls_iterator_free(it);
858 return NULL;
859 }
860
861 memcpy(it->dir, dir, length + 1);
862 it->length = length;
863
864 memcpy(it->info.path, dir, length);
865 if (dir[length - 1] == '/')
866 it->info.name_start = length;
867 else
868 {
869 it->info.path[length] = '/';
870 it->info.name_start = length + 1;
871 }
872
873 it->iterator.version = EINA_ITERATOR_VERSION;
874 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_direct_ls_iterator_next);
875 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
876 _eina_file_direct_ls_iterator_container);
877 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
878
879 return &it->iterator;
880#else
881 (void) dir;
882 return NULL;
883#endif
884}
885
886EAPI Eina_Iterator *
887eina_file_stat_ls(const char *dir)
888{
889#ifdef HAVE_DIRENT_H
890 Eina_File_Direct_Iterator *it;
891 size_t length;
892
893 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
894
895 length = strlen(dir);
896 if (length < 1)
897 return NULL;
898
899 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
900 if (!it)
901 return NULL;
902
903 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
904
905 it->dirp = opendir(dir);
906 if (!it->dirp)
907 {
908 free(it);
909 return NULL;
910 }
911
912 if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX)
913 {
914 _eina_file_direct_ls_iterator_free(it);
915 return NULL;
916 }
917
918 memcpy(it->dir, dir, length + 1);
919 it->length = length;
920
921 memcpy(it->info.path, dir, length);
922 if (dir[length - 1] == '/')
923 it->info.name_start = length;
924 else
925 {
926 it->info.path[length] = '/';
927 it->info.name_start = length + 1;
928 }
929
930 it->iterator.version = EINA_ITERATOR_VERSION;
931 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_stat_ls_iterator_next);
932 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
933 _eina_file_direct_ls_iterator_container);
934 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
935
936 return &it->iterator;
937#else
938 (void) dir;
939 return NULL;
940#endif
941}
942
943EAPI Eina_File *
944eina_file_open(const char *path, Eina_Bool shared)
945{
946 Eina_File *file;
947 Eina_File *n;
948 char *filename;
949 struct stat file_stat;
950 int fd = -1;
951#ifdef HAVE_EXECVP
952 int flags;
953#endif
954
955 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
956
957 filename = eina_file_path_sanitize(path);
958 if (!filename) return NULL;
959
960 if (shared)
961#ifdef HAVE_SHM_OPEN
962 fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
963#else
964 goto on_error;
965#endif
966 else
967 fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
968
969 if (fd < 0) goto on_error;
970
971#ifdef HAVE_EXECVP
972 flags = fcntl(fd, F_GETFD);
973 if (flags == -1)
974 goto on_error;
975
976 flags |= FD_CLOEXEC;
977 if (fcntl(fd, F_SETFD, flags) == -1)
978 goto on_error;
979#endif
980
981 if (fstat(fd, &file_stat))
982 goto on_error;
983
984 eina_lock_take(&_eina_file_lock_cache);
985
986 file = eina_hash_find(_eina_file_cache, filename);
987 if ((file) && !_eina_file_timestamp_compare(file, &file_stat))
988 {
989 file->delete_me = EINA_TRUE;
990 eina_hash_del(_eina_file_cache, file->filename, file);
991 _eina_file_real_close(file);
992 file = NULL;
993 }
994
995 if (!file)
996 {
997 n = malloc(sizeof(Eina_File) + strlen(filename) + 1);
998 if (!n)
999 {
1000 eina_lock_release(&_eina_file_lock_cache);
1001 goto on_error;
1002 }
1003
1004 memset(n, 0, sizeof(Eina_File));
1005 n->filename = (char*) (n + 1);
1006 strcpy((char*) n->filename, filename);
1007 n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
1008 EINA_KEY_CMP(_eina_file_map_key_cmp),
1009 EINA_KEY_HASH(_eina_file_map_key_hash),
1010 EINA_FREE_CB(_eina_file_map_close),
1011 3);
1012 n->rmap = eina_hash_pointer_new(NULL);
1013 n->global_map = MAP_FAILED;
1014 n->length = file_stat.st_size;
1015 n->mtime = file_stat.st_mtime;
1016#ifdef _STAT_VER_LINUX
1017# if (defined __USE_MISC && defined st_mtime)
1018 n->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
1019# else
1020 n->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
1021# endif
1022#endif
1023 n->inode = file_stat.st_ino;
1024 n->fd = fd;
1025 n->shared = shared;
1026 eina_lock_new(&n->lock);
1027 eina_hash_direct_add(_eina_file_cache, n->filename, n);
1028 }
1029 else
1030 {
1031 close(fd);
1032 n = file;
1033 }
1034 eina_lock_take(&n->lock);
1035 n->refcount++;
1036 eina_lock_release(&n->lock);
1037
1038 eina_lock_release(&_eina_file_lock_cache);
1039
1040 free(filename);
1041
1042 return n;
1043
1044 on_error:
1045 free(filename);
1046 if (fd >= 0) close(fd);
1047 return NULL;
1048}
1049
1050EAPI void
1051eina_file_close(Eina_File *file)
1052{
1053 EINA_SAFETY_ON_NULL_RETURN(file);
1054
1055 eina_lock_take(&file->lock);
1056 file->refcount--;
1057 eina_lock_release(&file->lock);
1058
1059 if (file->refcount != 0) return;
1060 eina_lock_take(&_eina_file_lock_cache);
1061
1062 eina_hash_del(_eina_file_cache, file->filename, file);
1063 _eina_file_real_close(file);
1064
1065 eina_lock_release(&_eina_file_lock_cache);
1066}
1067
1068EAPI size_t
1069eina_file_size_get(Eina_File *file)
1070{
1071 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1072 return file->length;
1073}
1074
1075EAPI time_t
1076eina_file_mtime_get(Eina_File *file)
1077{
1078 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1079 return file->mtime;
1080}
1081
1082EAPI const char *
1083eina_file_filename_get(Eina_File *file)
1084{
1085 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1086 return file->filename;
1087}
1088
1089EAPI void *
1090eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
1091{
1092 int flags = MAP_SHARED;
1093 void *ret = NULL;
1094
1095 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1096
1097// bsd people will lack this feature
1098#ifdef MAP_POPULATE
1099 if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
1100#endif
1101#ifdef MAP_HUGETLB
1102 if (file->length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB;
1103#endif
1104
1105 eina_mmap_safety_enabled_set(EINA_TRUE);
1106 eina_lock_take(&file->lock);
1107 if (file->global_map == MAP_FAILED)
1108 file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
1109#ifdef MAP_HUGETLB
1110 if ((file->global_map == MAP_FAILED) && (flags & MAP_HUGETLB))
1111 {
1112 flags &= ~MAP_HUGETLB;
1113 file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
1114 }
1115#endif
1116
1117 if (file->global_map != MAP_FAILED)
1118 {
1119 Eina_Bool hugetlb = EINA_FALSE;
1120
1121#ifdef MAP_HUGETLB
1122 hugetlb = !!(flags & MAP_HUGETLB);
1123#endif
1124 _eina_file_map_rule_apply(rule, file->global_map, file->length, hugetlb);
1125 file->global_refcount++;
1126 ret = file->global_map;
1127 }
1128
1129 eina_lock_release(&file->lock);
1130 return ret;
1131}
1132
1133typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
1134struct _Eina_Lines_Iterator
1135{
1136 Eina_Iterator iterator;
1137
1138 Eina_File *fp;
1139 const char *map;
1140 const char *end;
1141
1142 int boundary;
1143
1144 Eina_File_Line current;
1145};
1146
1147/* search '\r' and '\n' by preserving cache locality and page locality