aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/eina/src/lib/Makefile.am171
-rw-r--r--libraries/eina/src/lib/Makefile.in1226
-rw-r--r--libraries/eina/src/lib/eina_accessor.c176
-rw-r--r--libraries/eina/src/lib/eina_array.c491
-rw-r--r--libraries/eina/src/lib/eina_benchmark.c372
-rw-r--r--libraries/eina/src/lib/eina_binbuf.c62
-rw-r--r--libraries/eina/src/lib/eina_binbuf_template_c.x144
-rw-r--r--libraries/eina/src/lib/eina_binshare.c127
-rw-r--r--libraries/eina/src/lib/eina_convert.c483
-rw-r--r--libraries/eina/src/lib/eina_counter.c362
-rw-r--r--libraries/eina/src/lib/eina_cpu.c207
-rw-r--r--libraries/eina/src/lib/eina_error.c279
-rw-r--r--libraries/eina/src/lib/eina_file.c1187
-rw-r--r--libraries/eina/src/lib/eina_file_win32.c1021
-rw-r--r--libraries/eina/src/lib/eina_fp.c532
-rw-r--r--libraries/eina/src/lib/eina_hamster.c113
-rw-r--r--libraries/eina/src/lib/eina_hash.c1375
-rw-r--r--libraries/eina/src/lib/eina_inlist.c909
-rw-r--r--libraries/eina/src/lib/eina_iterator.c172
-rw-r--r--libraries/eina/src/lib/eina_lalloc.c158
-rw-r--r--libraries/eina/src/lib/eina_list.c1490
-rw-r--r--libraries/eina/src/lib/eina_log.c1852
-rw-r--r--libraries/eina/src/lib/eina_magic.c320
-rw-r--r--libraries/eina/src/lib/eina_main.c431
-rw-r--r--libraries/eina/src/lib/eina_matrixsparse.c1421
-rw-r--r--libraries/eina/src/lib/eina_mempool.c387
-rw-r--r--libraries/eina/src/lib/eina_mmap.c185
-rw-r--r--libraries/eina/src/lib/eina_module.c599
-rw-r--r--libraries/eina/src/lib/eina_prefix.c727
-rw-r--r--libraries/eina/src/lib/eina_private.h140
-rw-r--r--libraries/eina/src/lib/eina_quadtree.c935
-rw-r--r--libraries/eina/src/lib/eina_rbtree.c518
-rw-r--r--libraries/eina/src/lib/eina_rectangle.c568
-rw-r--r--libraries/eina/src/lib/eina_safety_checks.c90
-rw-r--r--libraries/eina/src/lib/eina_sched.c94
-rw-r--r--libraries/eina/src/lib/eina_share_common.c977
-rw-r--r--libraries/eina/src/lib/eina_share_common.h103
-rw-r--r--libraries/eina/src/lib/eina_simple_xml_parser.c1070
-rw-r--r--libraries/eina/src/lib/eina_str.c462
-rw-r--r--libraries/eina/src/lib/eina_strbuf.c202
-rw-r--r--libraries/eina/src/lib/eina_strbuf_common.c874
-rw-r--r--libraries/eina/src/lib/eina_strbuf_common.h120
-rw-r--r--libraries/eina/src/lib/eina_strbuf_template_c.x97
-rw-r--r--libraries/eina/src/lib/eina_stringshare.c751
-rw-r--r--libraries/eina/src/lib/eina_tiler.c1276
-rw-r--r--libraries/eina/src/lib/eina_unicode.c405
-rw-r--r--libraries/eina/src/lib/eina_ustrbuf.c74
-rw-r--r--libraries/eina/src/lib/eina_ustringshare.c132
-rw-r--r--libraries/eina/src/lib/eina_value.c47
-rw-r--r--libraries/eina/src/lib/eina_xattr.c292
50 files changed, 26206 insertions, 0 deletions
diff --git a/libraries/eina/src/lib/Makefile.am b/libraries/eina/src/lib/Makefile.am
new file mode 100644
index 0000000..0537a61
--- /dev/null
+++ b/libraries/eina/src/lib/Makefile.am
@@ -0,0 +1,171 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3AM_CPPFLAGS = \
4-I$(top_srcdir)/src/include \
5-I$(top_builddir)/src/include \
6-DPACKAGE_BIN_DIR=\"$(bindir)\" \
7-DPACKAGE_LIB_DIR=\"$(libdir)\" \
8-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
9@EINA_CPPFLAGS@ \
10@EFL_EINA_BUILD@
11
12base_sources = \
13eina_accessor.c \
14eina_array.c \
15eina_benchmark.c \
16eina_binbuf.c \
17eina_binshare.c \
18eina_convert.c \
19eina_counter.c \
20eina_cpu.c \
21eina_error.c \
22eina_fp.c \
23eina_hamster.c \
24eina_hash.c \
25eina_inlist.c \
26eina_iterator.c \
27eina_lalloc.c \
28eina_list.c \
29eina_log.c \
30eina_magic.c \
31eina_main.c \
32eina_matrixsparse.c \
33eina_mempool.c \
34eina_mmap.c \
35eina_module.c \
36eina_prefix.c \
37eina_quadtree.c \
38eina_rbtree.c \
39eina_rectangle.c \
40eina_safety_checks.c \
41eina_sched.c \
42eina_share_common.c \
43eina_simple_xml_parser.c \
44eina_str.c \
45eina_strbuf.c \
46eina_strbuf_common.c \
47eina_stringshare.c \
48eina_tiler.c \
49eina_unicode.c \
50eina_ustrbuf.c \
51eina_ustringshare.c \
52eina_value.c \
53eina_xattr.c
54
55# Will be back for developper after 1.1
56# eina_object.c
57
58if EINA_HAVE_WIN32
59base_sources += eina_file_win32.c
60else
61base_sources += eina_file.c
62endif
63
64EXTRA_DIST = \
65eina_share_common.h \
66eina_private.h \
67eina_strbuf_common.h \
68eina_strbuf_template_c.x \
69eina_binbuf_template_c.x
70
71
72
73if EINA_STATIC_BUILD_BUDDY
74base_sources += $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c
75endif
76
77if EINA_STATIC_BUILD_CHAINED_POOL
78base_sources += $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
79endif
80
81if EINA_STATIC_BUILD_EMEMOA_FIXED
82base_sources += $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c
83endif
84
85if EINA_STATIC_BUILD_EMEMOA_UNKNOWN
86base_sources += $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c
87endif
88
89if EINA_STATIC_BUILD_FIXED_BITMAP
90base_sources += $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
91endif
92
93if EINA_STATIC_BUILD_ONE_BIG
94base_sources += $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c
95endif
96
97if EINA_STATIC_BUILD_PASS_THROUGH
98base_sources += $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
99endif
100
101lib_LTLIBRARIES = libeina.la
102
103if EINA_AMALGAMATION
104nodist_libeina_la_SOURCES = eina_amalgamation.c
105
106eina_amalgamation.c: $(base_sources) Makefile
107 -rm -f eina_amalgamation.c
108
109 @echo "#ifdef HAVE_CONFIG_H" >> eina_amalgamation.c
110 @echo "#include \"config.h\"" >> eina_amalgamation.c
111 @echo "#endif" >> eina_amalgamation.c
112
113 @echo "#ifdef HAVE_ALLOCA_H" >> eina_amalgamation.c
114 @echo "# include <alloca.h>" >> eina_amalgamation.c
115 @echo "#elif defined __GNUC__" >> eina_amalgamation.c
116 @echo "# define alloca __builtin_alloca" >> eina_amalgamation.c
117 @echo "#elif defined _AIX" >> eina_amalgamation.c
118 @echo "# define alloca __alloca" >> eina_amalgamation.c
119 @echo "#elif defined _MSC_VER" >> eina_amalgamation.c
120 @echo "# include <malloc.h>" >> eina_amalgamation.c
121 @echo "# define alloca _alloca" >> eina_amalgamation.c
122 @echo "#else" >> eina_amalgamation.c
123 @echo "# include <stddef.h>" >> eina_amalgamation.c
124 @echo "# ifdef __cplusplus" >> eina_amalgamation.c
125 @echo "#extern \"C\"" >> eina_amalgamation.c
126 @echo "# endif" >> eina_amalgamation.c
127 @echo "#void *alloca (size_t);" >> eina_amalgamation.c
128 @echo "#endif" >> eina_amalgamation.c
129
130 @echo "#include <stdio.h>" >> eina_amalgamation.c
131 @echo "#include <stdlib.h>" >> eina_amalgamation.c
132 @echo "#include <string.h>" >> eina_amalgamation.c
133 @echo "#include <dlfcn.h>" >> eina_amalgamation.c
134 @echo "#include <sys/types.h>" >> eina_amalgamation.c
135 @echo "#include <dirent.h>" >> eina_amalgamation.c
136 @echo "#include <assert.h>" >> eina_amalgamation.c
137 @echo "#include <errno.h>" >> eina_amalgamation.c
138 @echo "#include <fnmatch.h>" >> eina_amalgamation.c
139
140 @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c
141 @echo "# include <Evil.h>" >> eina_amalgamation.c
142 @echo "#endif" >> eina_amalgamation.c
143
144 @echo "#include \"eina_config.h\"" >> eina_amalgamation.c
145 @echo "#include \"eina_private.h\"" >> eina_amalgamation.c
146 @echo "#include \"eina_safety_checks.h\"" >> eina_amalgamation.c
147 @echo "#include \"Eina.h\"" >> eina_amalgamation.c
148 @echo "#include \"eina_strbuf_common.h\"" >> eina_amalgamation.c
149 @echo "#include \"eina_share_common.h\"" >> eina_amalgamation.c
150
151 @for f in $(base_sources); do \
152 if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \
153 file="$(srcdir)/$$f" ; \
154 else \
155 file="$$f" ; \
156 fi ; \
157 echo "/* file: $$file */" >> eina_amalgamation.c; \
158 grep -v -e '^# *include \+.\(config\|eina_[a-z_]\+\|Evil\|stdio\|stdlib\|string\|dlfcn\|dirent\|assert\|errno\|fnmatch\)[.]h.*' $$file >> eina_amalgamation.c; \
159 done
160 @echo "eina_amalgamation.c generated"
161
162else
163libeina_la_SOURCES = $(base_sources)
164endif
165
166libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@
167libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@
168libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@
169
170clean-local:
171 rm -rf *.gcno eina_amalgamation.c
diff --git a/libraries/eina/src/lib/Makefile.in b/libraries/eina/src/lib/Makefile.in
new file mode 100644
index 0000000..359aba0
--- /dev/null
+++ b/libraries/eina/src/lib/Makefile.in
@@ -0,0 +1,1226 @@
1# Makefile.in generated by automake 1.11.1 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
6# Inc.
7# This Makefile.in is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
13# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14# PARTICULAR PURPOSE.
15
16@SET_MAKE@
17
18VPATH = @srcdir@
19pkgdatadir = $(datadir)/@PACKAGE@
20pkgincludedir = $(includedir)/@PACKAGE@
21pkglibdir = $(libdir)/@PACKAGE@
22pkglibexecdir = $(libexecdir)/@PACKAGE@
23am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
24install_sh_DATA = $(install_sh) -c -m 644
25install_sh_PROGRAM = $(install_sh) -c
26install_sh_SCRIPT = $(install_sh) -c
27INSTALL_HEADER = $(INSTALL_DATA)
28transform = $(program_transform_name)
29NORMAL_INSTALL = :
30PRE_INSTALL = :
31POST_INSTALL = :
32NORMAL_UNINSTALL = :
33PRE_UNINSTALL = :
34POST_UNINSTALL = :
35build_triplet = @build@
36host_triplet = @host@
37
38# Will be back for developper after 1.1
39# eina_object.c
40@EINA_HAVE_WIN32_TRUE@am__append_1 = eina_file_win32.c
41@EINA_HAVE_WIN32_FALSE@am__append_2 = eina_file.c
42@EINA_STATIC_BUILD_BUDDY_TRUE@am__append_3 = $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c
43@EINA_STATIC_BUILD_CHAINED_POOL_TRUE@am__append_4 = $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
44@EINA_STATIC_BUILD_EMEMOA_FIXED_TRUE@am__append_5 = $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c
45@EINA_STATIC_BUILD_EMEMOA_UNKNOWN_TRUE@am__append_6 = $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c
46@EINA_STATIC_BUILD_FIXED_BITMAP_TRUE@am__append_7 = $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
47@EINA_STATIC_BUILD_ONE_BIG_TRUE@am__append_8 = $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c
48@EINA_STATIC_BUILD_PASS_THROUGH_TRUE@am__append_9 = $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
49subdir = src/lib
50DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
51ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
52am__aclocal_m4_deps = $(top_srcdir)/m4/efl_attribute.m4 \
53 $(top_srcdir)/m4/efl_benchmark.m4 \
54 $(top_srcdir)/m4/efl_compiler_flag.m4 \
55 $(top_srcdir)/m4/efl_coverage.m4 $(top_srcdir)/m4/efl_cpu.m4 \
56 $(top_srcdir)/m4/efl_doxygen.m4 \
57 $(top_srcdir)/m4/efl_examples.m4 \
58 $(top_srcdir)/m4/efl_fnmatch.m4 \
59 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \
60 $(top_srcdir)/m4/efl_threads.m4 \
61 $(top_srcdir)/m4/efl_voltron.m4 $(top_srcdir)/m4/eina_bench.m4 \
62 $(top_srcdir)/m4/eina_check.m4 $(top_srcdir)/m4/libtool.m4 \
63 $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
64 $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
65 $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
66am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
67 $(ACLOCAL_M4)
68mkinstalldirs = $(install_sh) -d
69CONFIG_HEADER = $(top_builddir)/config.h
70CONFIG_CLEAN_FILES =
71CONFIG_CLEAN_VPATH_FILES =
72am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
73am__vpath_adj = case $$p in \
74 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
75 *) f=$$p;; \
76 esac;
77am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
78am__install_max = 40
79am__nobase_strip_setup = \
80 srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
81am__nobase_strip = \
82 for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
83am__nobase_list = $(am__nobase_strip_setup); \
84 for p in $$list; do echo "$$p $$p"; done | \
85 sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
86 $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
87 if (++n[$$2] == $(am__install_max)) \
88 { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
89 END { for (dir in files) print dir, files[dir] }'
90am__base_list = \
91 sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
92 sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
93am__installdirs = "$(DESTDIR)$(libdir)"
94LTLIBRARIES = $(lib_LTLIBRARIES)
95libeina_la_DEPENDENCIES =
96am__libeina_la_SOURCES_DIST = eina_accessor.c eina_array.c \
97 eina_benchmark.c eina_binbuf.c eina_binshare.c eina_convert.c \
98 eina_counter.c eina_cpu.c eina_error.c eina_fp.c \
99 eina_hamster.c eina_hash.c eina_inlist.c eina_iterator.c \
100 eina_lalloc.c eina_list.c eina_log.c eina_magic.c eina_main.c \
101 eina_matrixsparse.c eina_mempool.c eina_mmap.c eina_module.c \
102 eina_prefix.c eina_quadtree.c eina_rbtree.c eina_rectangle.c \
103 eina_safety_checks.c eina_sched.c eina_share_common.c \
104 eina_simple_xml_parser.c eina_str.c eina_strbuf.c \
105 eina_strbuf_common.c eina_stringshare.c eina_tiler.c \
106 eina_unicode.c eina_ustrbuf.c eina_ustringshare.c eina_value.c \
107 eina_xattr.c eina_file_win32.c eina_file.c \
108 $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c \
109 $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c \
110 $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c \
111 $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c \
112 $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c \
113 $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c \
114 $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
115@EINA_HAVE_WIN32_TRUE@am__objects_1 = libeina_la-eina_file_win32.lo
116@EINA_HAVE_WIN32_FALSE@am__objects_2 = libeina_la-eina_file.lo
117@EINA_STATIC_BUILD_BUDDY_TRUE@am__objects_3 = \
118@EINA_STATIC_BUILD_BUDDY_TRUE@ libeina_la-eina_buddy.lo
119@EINA_STATIC_BUILD_CHAINED_POOL_TRUE@am__objects_4 = libeina_la-eina_chained_mempool.lo
120@EINA_STATIC_BUILD_EMEMOA_FIXED_TRUE@am__objects_5 = libeina_la-eina_ememoa_fixed.lo
121@EINA_STATIC_BUILD_EMEMOA_UNKNOWN_TRUE@am__objects_6 = libeina_la-eina_ememoa_unknown.lo
122@EINA_STATIC_BUILD_FIXED_BITMAP_TRUE@am__objects_7 = libeina_la-eina_fixed_bitmap.lo
123@EINA_STATIC_BUILD_ONE_BIG_TRUE@am__objects_8 = \
124@EINA_STATIC_BUILD_ONE_BIG_TRUE@ libeina_la-eina_one_big.lo
125@EINA_STATIC_BUILD_PASS_THROUGH_TRUE@am__objects_9 = libeina_la-eina_pass_through.lo
126am__objects_10 = libeina_la-eina_accessor.lo libeina_la-eina_array.lo \
127 libeina_la-eina_benchmark.lo libeina_la-eina_binbuf.lo \
128 libeina_la-eina_binshare.lo libeina_la-eina_convert.lo \
129 libeina_la-eina_counter.lo libeina_la-eina_cpu.lo \
130 libeina_la-eina_error.lo libeina_la-eina_fp.lo \
131 libeina_la-eina_hamster.lo libeina_la-eina_hash.lo \
132 libeina_la-eina_inlist.lo libeina_la-eina_iterator.lo \
133 libeina_la-eina_lalloc.lo libeina_la-eina_list.lo \
134 libeina_la-eina_log.lo libeina_la-eina_magic.lo \
135 libeina_la-eina_main.lo libeina_la-eina_matrixsparse.lo \
136 libeina_la-eina_mempool.lo libeina_la-eina_mmap.lo \
137 libeina_la-eina_module.lo libeina_la-eina_prefix.lo \
138 libeina_la-eina_quadtree.lo libeina_la-eina_rbtree.lo \
139 libeina_la-eina_rectangle.lo libeina_la-eina_safety_checks.lo \
140 libeina_la-eina_sched.lo libeina_la-eina_share_common.lo \
141 libeina_la-eina_simple_xml_parser.lo libeina_la-eina_str.lo \
142 libeina_la-eina_strbuf.lo libeina_la-eina_strbuf_common.lo \
143 libeina_la-eina_stringshare.lo libeina_la-eina_tiler.lo \
144 libeina_la-eina_unicode.lo libeina_la-eina_ustrbuf.lo \
145 libeina_la-eina_ustringshare.lo libeina_la-eina_value.lo \
146 libeina_la-eina_xattr.lo $(am__objects_1) $(am__objects_2) \
147 $(am__objects_3) $(am__objects_4) $(am__objects_5) \
148 $(am__objects_6) $(am__objects_7) $(am__objects_8) \
149 $(am__objects_9)
150@EINA_AMALGAMATION_FALSE@am_libeina_la_OBJECTS = $(am__objects_10)
151@EINA_AMALGAMATION_TRUE@nodist_libeina_la_OBJECTS = \
152@EINA_AMALGAMATION_TRUE@ libeina_la-eina_amalgamation.lo
153libeina_la_OBJECTS = $(am_libeina_la_OBJECTS) \
154 $(nodist_libeina_la_OBJECTS)
155AM_V_lt = $(am__v_lt_$(V))
156am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
157am__v_lt_0 = --silent
158libeina_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
159 $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libeina_la_CFLAGS) \
160 $(CFLAGS) $(libeina_la_LDFLAGS) $(LDFLAGS) -o $@
161DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
162depcomp = $(SHELL) $(top_srcdir)/depcomp
163am__depfiles_maybe = depfiles
164am__mv = mv -f
165COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
166 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
167LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
168 $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
169 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
170 $(AM_CFLAGS) $(CFLAGS)
171AM_V_CC = $(am__v_CC_$(V))
172am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
173am__v_CC_0 = @echo " CC " $@;
174AM_V_at = $(am__v_at_$(V))
175am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
176am__v_at_0 = @
177CCLD = $(CC)
178LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
179 $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
180 $(AM_LDFLAGS) $(LDFLAGS) -o $@
181AM_V_CCLD = $(am__v_CCLD_$(V))
182am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
183am__v_CCLD_0 = @echo " CCLD " $@;
184AM_V_GEN = $(am__v_GEN_$(V))
185am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
186am__v_GEN_0 = @echo " GEN " $@;
187SOURCES = $(libeina_la_SOURCES) $(nodist_libeina_la_SOURCES)
188DIST_SOURCES = $(am__libeina_la_SOURCES_DIST)
189ETAGS = etags
190CTAGS = ctags
191DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
192ACLOCAL = @ACLOCAL@
193ALLOCA = @ALLOCA@
194AMTAR = @AMTAR@
195AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
196AR = @AR@
197AS = @AS@
198AUTOCONF = @AUTOCONF@
199AUTOHEADER = @AUTOHEADER@
200AUTOMAKE = @AUTOMAKE@
201AWK = @AWK@
202CC = @CC@
203CCDEPMODE = @CCDEPMODE@
204CFLAGS = @CFLAGS@
205CHECK_CFLAGS = @CHECK_CFLAGS@
206CHECK_LIBS = @CHECK_LIBS@
207CPP = @CPP@
208CPPFLAGS = @CPPFLAGS@
209CXX = @CXX@
210CXXCPP = @CXXCPP@
211CXXDEPMODE = @CXXDEPMODE@
212CXXFLAGS = @CXXFLAGS@
213CYGPATH_W = @CYGPATH_W@
214DEFS = @DEFS@
215DEPDIR = @DEPDIR@
216DLLTOOL = @DLLTOOL@
217DSYMUTIL = @DSYMUTIL@
218DUMPBIN = @DUMPBIN@
219ECHO_C = @ECHO_C@
220ECHO_N = @ECHO_N@
221ECHO_T = @ECHO_T@
222ECORE_EVAS_CFLAGS = @ECORE_EVAS_CFLAGS@
223ECORE_EVAS_LIBS = @ECORE_EVAS_LIBS@
224EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@
225EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@
226EFL_EINA_BUILD = @EFL_EINA_BUILD@
227EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@
228EFL_PTHREAD_CFLAGS = @EFL_PTHREAD_CFLAGS@
229EFL_PTHREAD_LIBS = @EFL_PTHREAD_LIBS@
230EFL_SIMD_FLAGS = @EFL_SIMD_FLAGS@
231EGREP = @EGREP@
232EINA_CFLAGS = @EINA_CFLAGS@
233EINA_CONFIGURE_DEFAULT_MEMPOOL = @EINA_CONFIGURE_DEFAULT_MEMPOOL@
234EINA_CONFIGURE_HAVE_DEBUG_THREADS = @EINA_CONFIGURE_HAVE_DEBUG_THREADS@
235EINA_CONFIGURE_HAVE_INTTYPES_H = @EINA_CONFIGURE_HAVE_INTTYPES_H@
236EINA_CONFIGURE_HAVE_ON_OFF_THREADS = @EINA_CONFIGURE_HAVE_ON_OFF_THREADS@
237EINA_CONFIGURE_HAVE_STDINT_H = @EINA_CONFIGURE_HAVE_STDINT_H@
238EINA_CONFIGURE_HAVE_THREADS = @EINA_CONFIGURE_HAVE_THREADS@
239EINA_CONFIGURE_MAGIC_DEBUG = @EINA_CONFIGURE_MAGIC_DEBUG@
240EINA_CONFIGURE_SAFETY_CHECKS = @EINA_CONFIGURE_SAFETY_CHECKS@
241EINA_CPPFLAGS = @EINA_CPPFLAGS@
242EINA_LIBS = @EINA_LIBS@
243EINA_SIZEOF_WCHAR_T = @EINA_SIZEOF_WCHAR_T@
244EMEMOA_CFLAGS = @EMEMOA_CFLAGS@
245EMEMOA_LIBS = @EMEMOA_LIBS@
246ESCAPE_CFLAGS = @ESCAPE_CFLAGS@
247ESCAPE_LIBS = @ESCAPE_LIBS@
248EVIL_CFLAGS = @EVIL_CFLAGS@
249EVIL_LIBS = @EVIL_LIBS@
250EXEEXT = @EXEEXT@
251FGREP = @FGREP@
252GLIB_CFLAGS = @GLIB_CFLAGS@
253GLIB_LIBS = @GLIB_LIBS@
254GREP = @GREP@
255INSTALL = @INSTALL@
256INSTALL_DATA = @INSTALL_DATA@
257INSTALL_PROGRAM = @INSTALL_PROGRAM@
258INSTALL_SCRIPT = @INSTALL_SCRIPT@
259INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
260LD = @LD@
261LDFLAGS = @LDFLAGS@
262LIBOBJS = @LIBOBJS@
263LIBS = @LIBS@
264LIBTOOL = @LIBTOOL@
265LIPO = @LIPO@
266LN_S = @LN_S@
267LTLIBOBJS = @LTLIBOBJS@
268MAKEINFO = @MAKEINFO@
269MKDIR_P = @MKDIR_P@
270MODULE_ARCH = @MODULE_ARCH@
271NM = @NM@
272NMEDIT = @NMEDIT@
273OBJDUMP = @OBJDUMP@
274OBJEXT = @OBJEXT@
275OTOOL = @OTOOL@
276OTOOL64 = @OTOOL64@
277PACKAGE = @PACKAGE@
278PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
279PACKAGE_NAME = @PACKAGE_NAME@
280PACKAGE_STRING = @PACKAGE_STRING@
281PACKAGE_TARNAME = @PACKAGE_TARNAME@
282PACKAGE_URL = @PACKAGE_URL@
283PACKAGE_VERSION = @PACKAGE_VERSION@
284PATH_SEPARATOR = @PATH_SEPARATOR@
285PKG_CONFIG = @PKG_CONFIG@
286PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
287PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
288RANLIB = @RANLIB@
289SED = @SED@
290SET_MAKE = @SET_MAKE@
291SHELL = @SHELL@
292STRIP = @STRIP@
293VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
294VALGRIND_LIBS = @VALGRIND_LIBS@
295VERSION = @VERSION@
296VMAJ = @VMAJ@
297abs_builddir = @abs_builddir@
298abs_srcdir = @abs_srcdir@
299abs_top_builddir = @abs_top_builddir@
300abs_top_srcdir = @abs_top_srcdir@
301ac_ct_CC = @ac_ct_CC@
302ac_ct_CXX = @ac_ct_CXX@
303ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
304am__include = @am__include@
305am__leading_dot = @am__leading_dot@
306am__quote = @am__quote@
307am__tar = @am__tar@
308am__untar = @am__untar@
309bindir = @bindir@
310build = @build@
311build_alias = @build_alias@
312build_cpu = @build_cpu@
313build_os = @build_os@
314build_vendor = @build_vendor@
315builddir = @builddir@
316datadir = @datadir@
317datarootdir = @datarootdir@
318dlopen_libs = @dlopen_libs@
319docdir = @docdir@
320dvidir = @dvidir@
321efl_doxygen = @efl_doxygen@
322efl_have_doxygen = @efl_have_doxygen@
323exec_prefix = @exec_prefix@
324have_lcov = @have_lcov@
325host = @host@
326host_alias = @host_alias@
327host_cpu = @host_cpu@
328host_os = @host_os@
329host_vendor = @host_vendor@
330htmldir = @htmldir@
331iconv_libs = @iconv_libs@
332includedir = @includedir@
333infodir = @infodir@
334install_sh = @install_sh@
335libdir = @libdir@
336libexecdir = @libexecdir@
337localedir = @localedir@
338localstatedir = @localstatedir@
339lt_ECHO = @lt_ECHO@
340lt_enable_auto_import = @lt_enable_auto_import@
341mandir = @mandir@
342mkdir_p = @mkdir_p@
343oldincludedir = @oldincludedir@
344pdfdir = @pdfdir@
345pkgconfig_requires_private = @pkgconfig_requires_private@
346prefix = @prefix@
347program_transform_name = @program_transform_name@
348psdir = @psdir@
349release_info = @release_info@
350requirement_eina = @requirement_eina@
351rt_libs = @rt_libs@
352sbindir = @sbindir@
353sharedstatedir = @sharedstatedir@
354srcdir = @srcdir@
355sysconfdir = @sysconfdir@
356target_alias = @target_alias@
357top_build_prefix = @top_build_prefix@
358top_builddir = @top_builddir@
359top_srcdir = @top_srcdir@
360version_info = @version_info@
361MAINTAINERCLEANFILES = Makefile.in
362AM_CPPFLAGS = \
363-I$(top_srcdir)/src/include \
364-I$(top_builddir)/src/include \
365-DPACKAGE_BIN_DIR=\"$(bindir)\" \
366-DPACKAGE_LIB_DIR=\"$(libdir)\" \
367-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
368@EINA_CPPFLAGS@ \
369@EFL_EINA_BUILD@
370
371base_sources = eina_accessor.c eina_array.c eina_benchmark.c \
372 eina_binbuf.c eina_binshare.c eina_convert.c eina_counter.c \
373 eina_cpu.c eina_error.c eina_fp.c eina_hamster.c eina_hash.c \
374 eina_inlist.c eina_iterator.c eina_lalloc.c eina_list.c \
375 eina_log.c eina_magic.c eina_main.c eina_matrixsparse.c \
376 eina_mempool.c eina_mmap.c eina_module.c eina_prefix.c \
377 eina_quadtree.c eina_rbtree.c eina_rectangle.c \
378 eina_safety_checks.c eina_sched.c eina_share_common.c \
379 eina_simple_xml_parser.c eina_str.c eina_strbuf.c \
380 eina_strbuf_common.c eina_stringshare.c eina_tiler.c \
381 eina_unicode.c eina_ustrbuf.c eina_ustringshare.c eina_value.c \
382 eina_xattr.c $(am__append_1) $(am__append_2) $(am__append_3) \
383 $(am__append_4) $(am__append_5) $(am__append_6) \
384 $(am__append_7) $(am__append_8) $(am__append_9)
385EXTRA_DIST = \
386eina_share_common.h \
387eina_private.h \
388eina_strbuf_common.h \
389eina_strbuf_template_c.x \
390eina_binbuf_template_c.x
391
392lib_LTLIBRARIES = libeina.la
393@EINA_AMALGAMATION_TRUE@nodist_libeina_la_SOURCES = eina_amalgamation.c
394@EINA_AMALGAMATION_FALSE@libeina_la_SOURCES = $(base_sources)
395libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@
396libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@
397libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@
398all: all-am
399
400.SUFFIXES:
401.SUFFIXES: .c .lo .o .obj
402$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
403 @for dep in $?; do \
404 case '$(am__configure_deps)' in \
405 *$$dep*) \
406 ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
407 && { if test -f $@; then exit 0; else break; fi; }; \
408 exit 1;; \
409 esac; \
410 done; \
411 echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/Makefile'; \
412 $(am__cd) $(top_srcdir) && \
413 $(AUTOMAKE) --gnu src/lib/Makefile
414.PRECIOUS: Makefile
415Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
416 @case '$?' in \
417 *config.status*) \
418 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
419 *) \
420 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
421 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
422 esac;
423
424$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
425 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
426
427$(top_srcdir)/configure: $(am__configure_deps)
428 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
429$(ACLOCAL_M4): $(am__aclocal_m4_deps)
430 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
431$(am__aclocal_m4_deps):
432install-libLTLIBRARIES: $(lib_LTLIBRARIES)
433 @$(NORMAL_INSTALL)
434 test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
435 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
436 list2=; for p in $$list; do \
437 if test -f $$p; then \
438 list2="$$list2 $$p"; \
439 else :; fi; \
440 done; \
441 test -z "$$list2" || { \
442 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
443 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
444 }
445
446uninstall-libLTLIBRARIES:
447 @$(NORMAL_UNINSTALL)
448 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
449 for p in $$list; do \
450 $(am__strip_dir) \
451 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
452 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
453 done
454
455clean-libLTLIBRARIES:
456 -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
457 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
458 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
459 test "$$dir" != "$$p" || dir=.; \
460 echo "rm -f \"$${dir}/so_locations\""; \
461 rm -f "$${dir}/so_locations"; \
462 done
463libeina.la: $(libeina_la_OBJECTS) $(libeina_la_DEPENDENCIES)
464 $(AM_V_CCLD)$(libeina_la_LINK) -rpath $(libdir) $(libeina_la_OBJECTS) $(libeina_la_LIBADD) $(LIBS)
465
466mostlyclean-compile:
467 -rm -f *.$(OBJEXT)
468
469distclean-compile:
470 -rm -f *.tab.c
471
472@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_accessor.Plo@am__quote@
473@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_amalgamation.Plo@am__quote@
474@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_array.Plo@am__quote@
475@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_benchmark.Plo@am__quote@
476@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_binbuf.Plo@am__quote@
477@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_binshare.Plo@am__quote@
478@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_buddy.Plo@am__quote@
479@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_chained_mempool.Plo@am__quote@
480@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_convert.Plo@am__quote@
481@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_counter.Plo@am__quote@
482@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_cpu.Plo@am__quote@
483@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ememoa_fixed.Plo@am__quote@
484@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ememoa_unknown.Plo@am__quote@
485@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_error.Plo@am__quote@
486@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_file.Plo@am__quote@
487@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_file_win32.Plo@am__quote@
488@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_fixed_bitmap.Plo@am__quote@
489@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_fp.Plo@am__quote@
490@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hamster.Plo@am__quote@
491@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hash.Plo@am__quote@
492@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_inlist.Plo@am__quote@
493@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_iterator.Plo@am__quote@
494@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_lalloc.Plo@am__quote@
495@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_list.Plo@am__quote@
496@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_log.Plo@am__quote@
497@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_magic.Plo@am__quote@
498@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_main.Plo@am__quote@
499@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_matrixsparse.Plo@am__quote@
500@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_mempool.Plo@am__quote@
501@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_mmap.Plo@am__quote@
502@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_module.Plo@am__quote@
503@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_one_big.Plo@am__quote@
504@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_pass_through.Plo@am__quote@
505@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_prefix.Plo@am__quote@
506@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_quadtree.Plo@am__quote@
507@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_rbtree.Plo@am__quote@
508@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_rectangle.Plo@am__quote@
509@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_safety_checks.Plo@am__quote@
510@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_sched.Plo@am__quote@
511@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_share_common.Plo@am__quote@
512@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_simple_xml_parser.Plo@am__quote@
513@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_str.Plo@am__quote@
514@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_strbuf.Plo@am__quote@
515@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_strbuf_common.Plo@am__quote@
516@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_stringshare.Plo@am__quote@
517@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_tiler.Plo@am__quote@
518@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_unicode.Plo@am__quote@
519@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ustrbuf.Plo@am__quote@
520@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ustringshare.Plo@am__quote@
521@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_value.Plo@am__quote@
522@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_xattr.Plo@am__quote@
523
524.c.o:
525@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
526@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
527@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
528@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
529@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
530@am__fastdepCC_FALSE@ $(COMPILE) -c $<
531
532.c.obj:
533@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
534@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
535@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
536@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
537@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
538@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
539
540.c.lo:
541@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
542@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
543@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
544@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
545@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
546@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
547
548libeina_la-eina_accessor.lo: eina_accessor.c
549@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_accessor.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_accessor.Tpo -c -o libeina_la-eina_accessor.lo `test -f 'eina_accessor.c' || echo '$(srcdir)/'`eina_accessor.c
550@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_accessor.Tpo $(DEPDIR)/libeina_la-eina_accessor.Plo
551@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
552@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_accessor.c' object='libeina_la-eina_accessor.lo' libtool=yes @AMDEPBACKSLASH@
553@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
554@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_accessor.lo `test -f 'eina_accessor.c' || echo '$(srcdir)/'`eina_accessor.c
555
556libeina_la-eina_array.lo: eina_array.c
557@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_array.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_array.Tpo -c -o libeina_la-eina_array.lo `test -f 'eina_array.c' || echo '$(srcdir)/'`eina_array.c
558@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_array.Tpo $(DEPDIR)/libeina_la-eina_array.Plo
559@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
560@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_array.c' object='libeina_la-eina_array.lo' libtool=yes @AMDEPBACKSLASH@
561@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
562@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_array.lo `test -f 'eina_array.c' || echo '$(srcdir)/'`eina_array.c
563
564libeina_la-eina_benchmark.lo: eina_benchmark.c
565@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_benchmark.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_benchmark.Tpo -c -o libeina_la-eina_benchmark.lo `test -f 'eina_benchmark.c' || echo '$(srcdir)/'`eina_benchmark.c
566@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_benchmark.Tpo $(DEPDIR)/libeina_la-eina_benchmark.Plo
567@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
568@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_benchmark.c' object='libeina_la-eina_benchmark.lo' libtool=yes @AMDEPBACKSLASH@
569@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
570@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_benchmark.lo `test -f 'eina_benchmark.c' || echo '$(srcdir)/'`eina_benchmark.c
571
572libeina_la-eina_binbuf.lo: eina_binbuf.c
573@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_binbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_binbuf.Tpo -c -o libeina_la-eina_binbuf.lo `test -f 'eina_binbuf.c' || echo '$(srcdir)/'`eina_binbuf.c
574@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_binbuf.Tpo $(DEPDIR)/libeina_la-eina_binbuf.Plo
575@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
576@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_binbuf.c' object='libeina_la-eina_binbuf.lo' libtool=yes @AMDEPBACKSLASH@
577@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
578@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_binbuf.lo `test -f 'eina_binbuf.c' || echo '$(srcdir)/'`eina_binbuf.c
579
580libeina_la-eina_binshare.lo: eina_binshare.c
581@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_binshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_binshare.Tpo -c -o libeina_la-eina_binshare.lo `test -f 'eina_binshare.c' || echo '$(srcdir)/'`eina_binshare.c
582@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_binshare.Tpo $(DEPDIR)/libeina_la-eina_binshare.Plo
583@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
584@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_binshare.c' object='libeina_la-eina_binshare.lo' libtool=yes @AMDEPBACKSLASH@
585@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
586@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_binshare.lo `test -f 'eina_binshare.c' || echo '$(srcdir)/'`eina_binshare.c
587
588libeina_la-eina_convert.lo: eina_convert.c
589@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_convert.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_convert.Tpo -c -o libeina_la-eina_convert.lo `test -f 'eina_convert.c' || echo '$(srcdir)/'`eina_convert.c
590@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_convert.Tpo $(DEPDIR)/libeina_la-eina_convert.Plo
591@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
592@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_convert.c' object='libeina_la-eina_convert.lo' libtool=yes @AMDEPBACKSLASH@
593@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
594@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_convert.lo `test -f 'eina_convert.c' || echo '$(srcdir)/'`eina_convert.c
595
596libeina_la-eina_counter.lo: eina_counter.c
597@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_counter.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_counter.Tpo -c -o libeina_la-eina_counter.lo `test -f 'eina_counter.c' || echo '$(srcdir)/'`eina_counter.c
598@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_counter.Tpo $(DEPDIR)/libeina_la-eina_counter.Plo
599@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
600@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_counter.c' object='libeina_la-eina_counter.lo' libtool=yes @AMDEPBACKSLASH@
601@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
602@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_counter.lo `test -f 'eina_counter.c' || echo '$(srcdir)/'`eina_counter.c
603
604libeina_la-eina_cpu.lo: eina_cpu.c
605@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_cpu.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_cpu.Tpo -c -o libeina_la-eina_cpu.lo `test -f 'eina_cpu.c' || echo '$(srcdir)/'`eina_cpu.c
606@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_cpu.Tpo $(DEPDIR)/libeina_la-eina_cpu.Plo
607@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
608@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_cpu.c' object='libeina_la-eina_cpu.lo' libtool=yes @AMDEPBACKSLASH@
609@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
610@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_cpu.lo `test -f 'eina_cpu.c' || echo '$(srcdir)/'`eina_cpu.c
611
612libeina_la-eina_error.lo: eina_error.c
613@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_error.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_error.Tpo -c -o libeina_la-eina_error.lo `test -f 'eina_error.c' || echo '$(srcdir)/'`eina_error.c
614@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_error.Tpo $(DEPDIR)/libeina_la-eina_error.Plo
615@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
616@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_error.c' object='libeina_la-eina_error.lo' libtool=yes @AMDEPBACKSLASH@
617@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
618@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_error.lo `test -f 'eina_error.c' || echo '$(srcdir)/'`eina_error.c
619
620libeina_la-eina_fp.lo: eina_fp.c
621@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_fp.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_fp.Tpo -c -o libeina_la-eina_fp.lo `test -f 'eina_fp.c' || echo '$(srcdir)/'`eina_fp.c
622@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_fp.Tpo $(DEPDIR)/libeina_la-eina_fp.Plo
623@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
624@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_fp.c' object='libeina_la-eina_fp.lo' libtool=yes @AMDEPBACKSLASH@
625@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
626@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_fp.lo `test -f 'eina_fp.c' || echo '$(srcdir)/'`eina_fp.c
627
628libeina_la-eina_hamster.lo: eina_hamster.c
629@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_hamster.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_hamster.Tpo -c -o libeina_la-eina_hamster.lo `test -f 'eina_hamster.c' || echo '$(srcdir)/'`eina_hamster.c
630@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_hamster.Tpo $(DEPDIR)/libeina_la-eina_hamster.Plo
631@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
632@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_hamster.c' object='libeina_la-eina_hamster.lo' libtool=yes @AMDEPBACKSLASH@
633@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
634@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_hamster.lo `test -f 'eina_hamster.c' || echo '$(srcdir)/'`eina_hamster.c
635
636libeina_la-eina_hash.lo: eina_hash.c
637@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_hash.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_hash.Tpo -c -o libeina_la-eina_hash.lo `test -f 'eina_hash.c' || echo '$(srcdir)/'`eina_hash.c
638@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_hash.Tpo $(DEPDIR)/libeina_la-eina_hash.Plo
639@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
640@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_hash.c' object='libeina_la-eina_hash.lo' libtool=yes @AMDEPBACKSLASH@
641@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
642@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_hash.lo `test -f 'eina_hash.c' || echo '$(srcdir)/'`eina_hash.c
643
644libeina_la-eina_inlist.lo: eina_inlist.c
645@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_inlist.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_inlist.Tpo -c -o libeina_la-eina_inlist.lo `test -f 'eina_inlist.c' || echo '$(srcdir)/'`eina_inlist.c
646@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_inlist.Tpo $(DEPDIR)/libeina_la-eina_inlist.Plo
647@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
648@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_inlist.c' object='libeina_la-eina_inlist.lo' libtool=yes @AMDEPBACKSLASH@
649@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
650@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_inlist.lo `test -f 'eina_inlist.c' || echo '$(srcdir)/'`eina_inlist.c
651
652libeina_la-eina_iterator.lo: eina_iterator.c
653@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_iterator.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_iterator.Tpo -c -o libeina_la-eina_iterator.lo `test -f 'eina_iterator.c' || echo '$(srcdir)/'`eina_iterator.c
654@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_iterator.Tpo $(DEPDIR)/libeina_la-eina_iterator.Plo
655@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
656@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_iterator.c' object='libeina_la-eina_iterator.lo' libtool=yes @AMDEPBACKSLASH@
657@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
658@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_iterator.lo `test -f 'eina_iterator.c' || echo '$(srcdir)/'`eina_iterator.c
659
660libeina_la-eina_lalloc.lo: eina_lalloc.c
661@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_lalloc.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_lalloc.Tpo -c -o libeina_la-eina_lalloc.lo `test -f 'eina_lalloc.c' || echo '$(srcdir)/'`eina_lalloc.c
662@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_lalloc.Tpo $(DEPDIR)/libeina_la-eina_lalloc.Plo
663@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
664@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_lalloc.c' object='libeina_la-eina_lalloc.lo' libtool=yes @AMDEPBACKSLASH@
665@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
666@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_lalloc.lo `test -f 'eina_lalloc.c' || echo '$(srcdir)/'`eina_lalloc.c
667
668libeina_la-eina_list.lo: eina_list.c
669@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_list.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_list.Tpo -c -o libeina_la-eina_list.lo `test -f 'eina_list.c' || echo '$(srcdir)/'`eina_list.c
670@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_list.Tpo $(DEPDIR)/libeina_la-eina_list.Plo
671@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
672@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_list.c' object='libeina_la-eina_list.lo' libtool=yes @AMDEPBACKSLASH@
673@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
674@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_list.lo `test -f 'eina_list.c' || echo '$(srcdir)/'`eina_list.c
675
676libeina_la-eina_log.lo: eina_log.c
677@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_log.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_log.Tpo -c -o libeina_la-eina_log.lo `test -f 'eina_log.c' || echo '$(srcdir)/'`eina_log.c
678@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_log.Tpo $(DEPDIR)/libeina_la-eina_log.Plo
679@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
680@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_log.c' object='libeina_la-eina_log.lo' libtool=yes @AMDEPBACKSLASH@
681@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
682@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_log.lo `test -f 'eina_log.c' || echo '$(srcdir)/'`eina_log.c
683
684libeina_la-eina_magic.lo: eina_magic.c
685@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_magic.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_magic.Tpo -c -o libeina_la-eina_magic.lo `test -f 'eina_magic.c' || echo '$(srcdir)/'`eina_magic.c
686@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_magic.Tpo $(DEPDIR)/libeina_la-eina_magic.Plo
687@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
688@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_magic.c' object='libeina_la-eina_magic.lo' libtool=yes @AMDEPBACKSLASH@
689@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
690@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_magic.lo `test -f 'eina_magic.c' || echo '$(srcdir)/'`eina_magic.c
691
692libeina_la-eina_main.lo: eina_main.c
693@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_main.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_main.Tpo -c -o libeina_la-eina_main.lo `test -f 'eina_main.c' || echo '$(srcdir)/'`eina_main.c
694@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_main.Tpo $(DEPDIR)/libeina_la-eina_main.Plo
695@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
696@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_main.c' object='libeina_la-eina_main.lo' libtool=yes @AMDEPBACKSLASH@
697@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
698@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_main.lo `test -f 'eina_main.c' || echo '$(srcdir)/'`eina_main.c
699
700libeina_la-eina_matrixsparse.lo: eina_matrixsparse.c
701@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_matrixsparse.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_matrixsparse.Tpo -c -o libeina_la-eina_matrixsparse.lo `test -f 'eina_matrixsparse.c' || echo '$(srcdir)/'`eina_matrixsparse.c
702@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_matrixsparse.Tpo $(DEPDIR)/libeina_la-eina_matrixsparse.Plo
703@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
704@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_matrixsparse.c' object='libeina_la-eina_matrixsparse.lo' libtool=yes @AMDEPBACKSLASH@
705@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
706@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_matrixsparse.lo `test -f 'eina_matrixsparse.c' || echo '$(srcdir)/'`eina_matrixsparse.c
707
708libeina_la-eina_mempool.lo: eina_mempool.c
709@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_mempool.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_mempool.Tpo -c -o libeina_la-eina_mempool.lo `test -f 'eina_mempool.c' || echo '$(srcdir)/'`eina_mempool.c
710@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_mempool.Tpo $(DEPDIR)/libeina_la-eina_mempool.Plo
711@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
712@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_mempool.c' object='libeina_la-eina_mempool.lo' libtool=yes @AMDEPBACKSLASH@
713@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
714@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_mempool.lo `test -f 'eina_mempool.c' || echo '$(srcdir)/'`eina_mempool.c
715
716libeina_la-eina_mmap.lo: eina_mmap.c
717@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_mmap.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_mmap.Tpo -c -o libeina_la-eina_mmap.lo `test -f 'eina_mmap.c' || echo '$(srcdir)/'`eina_mmap.c
718@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_mmap.Tpo $(DEPDIR)/libeina_la-eina_mmap.Plo
719@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
720@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_mmap.c' object='libeina_la-eina_mmap.lo' libtool=yes @AMDEPBACKSLASH@
721@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
722@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_mmap.lo `test -f 'eina_mmap.c' || echo '$(srcdir)/'`eina_mmap.c
723
724libeina_la-eina_module.lo: eina_module.c
725@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_module.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_module.Tpo -c -o libeina_la-eina_module.lo `test -f 'eina_module.c' || echo '$(srcdir)/'`eina_module.c
726@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_module.Tpo $(DEPDIR)/libeina_la-eina_module.Plo
727@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
728@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_module.c' object='libeina_la-eina_module.lo' libtool=yes @AMDEPBACKSLASH@
729@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
730@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_module.lo `test -f 'eina_module.c' || echo '$(srcdir)/'`eina_module.c
731
732libeina_la-eina_prefix.lo: eina_prefix.c
733@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_prefix.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_prefix.Tpo -c -o libeina_la-eina_prefix.lo `test -f 'eina_prefix.c' || echo '$(srcdir)/'`eina_prefix.c
734@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_prefix.Tpo $(DEPDIR)/libeina_la-eina_prefix.Plo
735@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
736@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_prefix.c' object='libeina_la-eina_prefix.lo' libtool=yes @AMDEPBACKSLASH@
737@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
738@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_prefix.lo `test -f 'eina_prefix.c' || echo '$(srcdir)/'`eina_prefix.c
739
740libeina_la-eina_quadtree.lo: eina_quadtree.c
741@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_quadtree.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_quadtree.Tpo -c -o libeina_la-eina_quadtree.lo `test -f 'eina_quadtree.c' || echo '$(srcdir)/'`eina_quadtree.c
742@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_quadtree.Tpo $(DEPDIR)/libeina_la-eina_quadtree.Plo
743@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
744@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_quadtree.c' object='libeina_la-eina_quadtree.lo' libtool=yes @AMDEPBACKSLASH@
745@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
746@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_quadtree.lo `test -f 'eina_quadtree.c' || echo '$(srcdir)/'`eina_quadtree.c
747
748libeina_la-eina_rbtree.lo: eina_rbtree.c
749@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_rbtree.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_rbtree.Tpo -c -o libeina_la-eina_rbtree.lo `test -f 'eina_rbtree.c' || echo '$(srcdir)/'`eina_rbtree.c
750@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_rbtree.Tpo $(DEPDIR)/libeina_la-eina_rbtree.Plo
751@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
752@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_rbtree.c' object='libeina_la-eina_rbtree.lo' libtool=yes @AMDEPBACKSLASH@
753@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
754@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_rbtree.lo `test -f 'eina_rbtree.c' || echo '$(srcdir)/'`eina_rbtree.c
755
756libeina_la-eina_rectangle.lo: eina_rectangle.c
757@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_rectangle.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_rectangle.Tpo -c -o libeina_la-eina_rectangle.lo `test -f 'eina_rectangle.c' || echo '$(srcdir)/'`eina_rectangle.c
758@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_rectangle.Tpo $(DEPDIR)/libeina_la-eina_rectangle.Plo
759@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
760@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_rectangle.c' object='libeina_la-eina_rectangle.lo' libtool=yes @AMDEPBACKSLASH@
761@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
762@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_rectangle.lo `test -f 'eina_rectangle.c' || echo '$(srcdir)/'`eina_rectangle.c
763
764libeina_la-eina_safety_checks.lo: eina_safety_checks.c
765@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_safety_checks.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_safety_checks.Tpo -c -o libeina_la-eina_safety_checks.lo `test -f 'eina_safety_checks.c' || echo '$(srcdir)/'`eina_safety_checks.c
766@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_safety_checks.Tpo $(DEPDIR)/libeina_la-eina_safety_checks.Plo
767@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
768@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_safety_checks.c' object='libeina_la-eina_safety_checks.lo' libtool=yes @AMDEPBACKSLASH@
769@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
770@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_safety_checks.lo `test -f 'eina_safety_checks.c' || echo '$(srcdir)/'`eina_safety_checks.c
771
772libeina_la-eina_sched.lo: eina_sched.c
773@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_sched.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_sched.Tpo -c -o libeina_la-eina_sched.lo `test -f 'eina_sched.c' || echo '$(srcdir)/'`eina_sched.c
774@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_sched.Tpo $(DEPDIR)/libeina_la-eina_sched.Plo
775@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
776@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_sched.c' object='libeina_la-eina_sched.lo' libtool=yes @AMDEPBACKSLASH@
777@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
778@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_sched.lo `test -f 'eina_sched.c' || echo '$(srcdir)/'`eina_sched.c
779
780libeina_la-eina_share_common.lo: eina_share_common.c
781@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_share_common.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_share_common.Tpo -c -o libeina_la-eina_share_common.lo `test -f 'eina_share_common.c' || echo '$(srcdir)/'`eina_share_common.c
782@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_share_common.Tpo $(DEPDIR)/libeina_la-eina_share_common.Plo
783@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
784@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_share_common.c' object='libeina_la-eina_share_common.lo' libtool=yes @AMDEPBACKSLASH@
785@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
786@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_share_common.lo `test -f 'eina_share_common.c' || echo '$(srcdir)/'`eina_share_common.c
787
788libeina_la-eina_simple_xml_parser.lo: eina_simple_xml_parser.c
789@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_simple_xml_parser.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_simple_xml_parser.Tpo -c -o libeina_la-eina_simple_xml_parser.lo `test -f 'eina_simple_xml_parser.c' || echo '$(srcdir)/'`eina_simple_xml_parser.c
790@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_simple_xml_parser.Tpo $(DEPDIR)/libeina_la-eina_simple_xml_parser.Plo
791@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
792@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_simple_xml_parser.c' object='libeina_la-eina_simple_xml_parser.lo' libtool=yes @AMDEPBACKSLASH@
793@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
794@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_simple_xml_parser.lo `test -f 'eina_simple_xml_parser.c' || echo '$(srcdir)/'`eina_simple_xml_parser.c
795
796libeina_la-eina_str.lo: eina_str.c
797@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_str.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_str.Tpo -c -o libeina_la-eina_str.lo `test -f 'eina_str.c' || echo '$(srcdir)/'`eina_str.c
798@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_str.Tpo $(DEPDIR)/libeina_la-eina_str.Plo
799@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
800@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_str.c' object='libeina_la-eina_str.lo' libtool=yes @AMDEPBACKSLASH@
801@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
802@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_str.lo `test -f 'eina_str.c' || echo '$(srcdir)/'`eina_str.c
803
804libeina_la-eina_strbuf.lo: eina_strbuf.c
805@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_strbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_strbuf.Tpo -c -o libeina_la-eina_strbuf.lo `test -f 'eina_strbuf.c' || echo '$(srcdir)/'`eina_strbuf.c
806@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_strbuf.Tpo $(DEPDIR)/libeina_la-eina_strbuf.Plo
807@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
808@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_strbuf.c' object='libeina_la-eina_strbuf.lo' libtool=yes @AMDEPBACKSLASH@
809@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
810@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_strbuf.lo `test -f 'eina_strbuf.c' || echo '$(srcdir)/'`eina_strbuf.c
811
812libeina_la-eina_strbuf_common.lo: eina_strbuf_common.c
813@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_strbuf_common.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_strbuf_common.Tpo -c -o libeina_la-eina_strbuf_common.lo `test -f 'eina_strbuf_common.c' || echo '$(srcdir)/'`eina_strbuf_common.c
814@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_strbuf_common.Tpo $(DEPDIR)/libeina_la-eina_strbuf_common.Plo
815@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
816@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_strbuf_common.c' object='libeina_la-eina_strbuf_common.lo' libtool=yes @AMDEPBACKSLASH@
817@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
818@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_strbuf_common.lo `test -f 'eina_strbuf_common.c' || echo '$(srcdir)/'`eina_strbuf_common.c
819
820libeina_la-eina_stringshare.lo: eina_stringshare.c
821@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_stringshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_stringshare.Tpo -c -o libeina_la-eina_stringshare.lo `test -f 'eina_stringshare.c' || echo '$(srcdir)/'`eina_stringshare.c
822@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_stringshare.Tpo $(DEPDIR)/libeina_la-eina_stringshare.Plo
823@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
824@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_stringshare.c' object='libeina_la-eina_stringshare.lo' libtool=yes @AMDEPBACKSLASH@
825@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
826@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_stringshare.lo `test -f 'eina_stringshare.c' || echo '$(srcdir)/'`eina_stringshare.c
827
828libeina_la-eina_tiler.lo: eina_tiler.c
829@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_tiler.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_tiler.Tpo -c -o libeina_la-eina_tiler.lo `test -f 'eina_tiler.c' || echo '$(srcdir)/'`eina_tiler.c
830@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_tiler.Tpo $(DEPDIR)/libeina_la-eina_tiler.Plo
831@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
832@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_tiler.c' object='libeina_la-eina_tiler.lo' libtool=yes @AMDEPBACKSLASH@
833@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
834@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_tiler.lo `test -f 'eina_tiler.c' || echo '$(srcdir)/'`eina_tiler.c
835
836libeina_la-eina_unicode.lo: eina_unicode.c
837@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_unicode.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_unicode.Tpo -c -o libeina_la-eina_unicode.lo `test -f 'eina_unicode.c' || echo '$(srcdir)/'`eina_unicode.c
838@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_unicode.Tpo $(DEPDIR)/libeina_la-eina_unicode.Plo
839@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
840@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_unicode.c' object='libeina_la-eina_unicode.lo' libtool=yes @AMDEPBACKSLASH@
841@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
842@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_unicode.lo `test -f 'eina_unicode.c' || echo '$(srcdir)/'`eina_unicode.c
843
844libeina_la-eina_ustrbuf.lo: eina_ustrbuf.c
845@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_ustrbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ustrbuf.Tpo -c -o libeina_la-eina_ustrbuf.lo `test -f 'eina_ustrbuf.c' || echo '$(srcdir)/'`eina_ustrbuf.c
846@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ustrbuf.Tpo $(DEPDIR)/libeina_la-eina_ustrbuf.Plo
847@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
848@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_ustrbuf.c' object='libeina_la-eina_ustrbuf.lo' libtool=yes @AMDEPBACKSLASH@
849@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
850@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_ustrbuf.lo `test -f 'eina_ustrbuf.c' || echo '$(srcdir)/'`eina_ustrbuf.c
851
852libeina_la-eina_ustringshare.lo: eina_ustringshare.c
853@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_ustringshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ustringshare.Tpo -c -o libeina_la-eina_ustringshare.lo `test -f 'eina_ustringshare.c' || echo '$(srcdir)/'`eina_ustringshare.c
854@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ustringshare.Tpo $(DEPDIR)/libeina_la-eina_ustringshare.Plo
855@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
856@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_ustringshare.c' object='libeina_la-eina_ustringshare.lo' libtool=yes @AMDEPBACKSLASH@
857@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
858@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_ustringshare.lo `test -f 'eina_ustringshare.c' || echo '$(srcdir)/'`eina_ustringshare.c
859
860libeina_la-eina_value.lo: eina_value.c
861@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_value.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_value.Tpo -c -o libeina_la-eina_value.lo `test -f 'eina_value.c' || echo '$(srcdir)/'`eina_value.c
862@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_value.Tpo $(DEPDIR)/libeina_la-eina_value.Plo
863@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
864@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_value.c' object='libeina_la-eina_value.lo' libtool=yes @AMDEPBACKSLASH@
865@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
866@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_value.lo `test -f 'eina_value.c' || echo '$(srcdir)/'`eina_value.c
867
868libeina_la-eina_xattr.lo: eina_xattr.c
869@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_xattr.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_xattr.Tpo -c -o libeina_la-eina_xattr.lo `test -f 'eina_xattr.c' || echo '$(srcdir)/'`eina_xattr.c
870@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_xattr.Tpo $(DEPDIR)/libeina_la-eina_xattr.Plo
871@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
872@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_xattr.c' object='libeina_la-eina_xattr.lo' libtool=yes @AMDEPBACKSLASH@
873@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
874@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_xattr.lo `test -f 'eina_xattr.c' || echo '$(srcdir)/'`eina_xattr.c
875
876libeina_la-eina_file_win32.lo: eina_file_win32.c
877@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_file_win32.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_file_win32.Tpo -c -o libeina_la-eina_file_win32.lo `test -f 'eina_file_win32.c' || echo '$(srcdir)/'`eina_file_win32.c
878@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_file_win32.Tpo $(DEPDIR)/libeina_la-eina_file_win32.Plo
879@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
880@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_file_win32.c' object='libeina_la-eina_file_win32.lo' libtool=yes @AMDEPBACKSLASH@
881@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
882@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_file_win32.lo `test -f 'eina_file_win32.c' || echo '$(srcdir)/'`eina_file_win32.c
883
884libeina_la-eina_file.lo: eina_file.c
885@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_file.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_file.Tpo -c -o libeina_la-eina_file.lo `test -f 'eina_file.c' || echo '$(srcdir)/'`eina_file.c
886@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_file.Tpo $(DEPDIR)/libeina_la-eina_file.Plo
887@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
888@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_file.c' object='libeina_la-eina_file.lo' libtool=yes @AMDEPBACKSLASH@
889@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
890@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_file.lo `test -f 'eina_file.c' || echo '$(srcdir)/'`eina_file.c
891
892libeina_la-eina_buddy.lo: $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c
893@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_buddy.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_buddy.Tpo -c -o libeina_la-eina_buddy.lo `test -f '$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c
894@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_buddy.Tpo $(DEPDIR)/libeina_la-eina_buddy.Plo
895@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
896@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' object='libeina_la-eina_buddy.lo' libtool=yes @AMDEPBACKSLASH@
897@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
898@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_buddy.lo `test -f '$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c
899
900libeina_la-eina_chained_mempool.lo: $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
901@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_chained_mempool.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_chained_mempool.Tpo -c -o libeina_la-eina_chained_mempool.lo `test -f '$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
902@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_chained_mempool.Tpo $(DEPDIR)/libeina_la-eina_chained_mempool.Plo
903@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
904@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' object='libeina_la-eina_chained_mempool.lo' libtool=yes @AMDEPBACKSLASH@
905@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
906@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_chained_mempool.lo `test -f '$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
907
908libeina_la-eina_ememoa_fixed.lo: $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c
909@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_ememoa_fixed.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ememoa_fixed.Tpo -c -o libeina_la-eina_ememoa_fixed.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c
910@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ememoa_fixed.Tpo $(DEPDIR)/libeina_la-eina_ememoa_fixed.Plo
911@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
912@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' object='libeina_la-eina_ememoa_fixed.lo' libtool=yes @AMDEPBACKSLASH@
913@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
914@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_ememoa_fixed.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c
915
916libeina_la-eina_ememoa_unknown.lo: $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c
917@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_ememoa_unknown.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ememoa_unknown.Tpo -c -o libeina_la-eina_ememoa_unknown.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c
918@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ememoa_unknown.Tpo $(DEPDIR)/libeina_la-eina_ememoa_unknown.Plo
919@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
920@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' object='libeina_la-eina_ememoa_unknown.lo' libtool=yes @AMDEPBACKSLASH@
921@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
922@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_ememoa_unknown.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c
923
924libeina_la-eina_fixed_bitmap.lo: $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
925@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_fixed_bitmap.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_fixed_bitmap.Tpo -c -o libeina_la-eina_fixed_bitmap.lo `test -f '$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
926@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_fixed_bitmap.Tpo $(DEPDIR)/libeina_la-eina_fixed_bitmap.Plo
927@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
928@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' object='libeina_la-eina_fixed_bitmap.lo' libtool=yes @AMDEPBACKSLASH@
929@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
930@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_fixed_bitmap.lo `test -f '$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
931
932libeina_la-eina_one_big.lo: $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c
933@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_one_big.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_one_big.Tpo -c -o libeina_la-eina_one_big.lo `test -f '$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c
934@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_one_big.Tpo $(DEPDIR)/libeina_la-eina_one_big.Plo
935@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
936@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' object='libeina_la-eina_one_big.lo' libtool=yes @AMDEPBACKSLASH@
937@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
938@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_one_big.lo `test -f '$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c
939
940libeina_la-eina_pass_through.lo: $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
941@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_pass_through.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_pass_through.Tpo -c -o libeina_la-eina_pass_through.lo `test -f '$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
942@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_pass_through.Tpo $(DEPDIR)/libeina_la-eina_pass_through.Plo
943@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
944@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' object='libeina_la-eina_pass_through.lo' libtool=yes @AMDEPBACKSLASH@
945@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
946@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_pass_through.lo `test -f '$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c
947
948libeina_la-eina_amalgamation.lo: eina_amalgamation.c
949@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_amalgamation.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_amalgamation.Tpo -c -o libeina_la-eina_amalgamation.lo `test -f 'eina_amalgamation.c' || echo '$(srcdir)/'`eina_amalgamation.c
950@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_amalgamation.Tpo $(DEPDIR)/libeina_la-eina_amalgamation.Plo
951@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
952@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_amalgamation.c' object='libeina_la-eina_amalgamation.lo' libtool=yes @AMDEPBACKSLASH@
953@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
954@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_amalgamation.lo `test -f 'eina_amalgamation.c' || echo '$(srcdir)/'`eina_amalgamation.c
955
956mostlyclean-libtool:
957 -rm -f *.lo
958
959clean-libtool:
960 -rm -rf .libs _libs
961
962ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
963 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
964 unique=`for i in $$list; do \
965 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
966 done | \
967 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
968 END { if (nonempty) { for (i in files) print i; }; }'`; \
969 mkid -fID $$unique
970tags: TAGS
971
972TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
973 $(TAGS_FILES) $(LISP)
974 set x; \
975 here=`pwd`; \
976 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
977 unique=`for i in $$list; do \
978 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
979 done | \
980 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
981 END { if (nonempty) { for (i in files) print i; }; }'`; \
982 shift; \
983 if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
984 test -n "$$unique" || unique=$$empty_fix; \
985 if test $$# -gt 0; then \
986 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
987 "$$@" $$unique; \
988 else \
989 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
990 $$unique; \
991 fi; \
992 fi
993ctags: CTAGS
994CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
995 $(TAGS_FILES) $(LISP)
996 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
997 unique=`for i in $$list; do \
998 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
999 done | \
1000 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
1001 END { if (nonempty) { for (i in files) print i; }; }'`; \
1002 test -z "$(CTAGS_ARGS)$$unique" \
1003 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
1004 $$unique
1005
1006GTAGS:
1007 here=`$(am__cd) $(top_builddir) && pwd` \
1008 && $(am__cd) $(top_srcdir) \
1009 && gtags -i $(GTAGS_ARGS) "$$here"
1010
1011distclean-tags:
1012 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
1013
1014distdir: $(DISTFILES)
1015 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
1016 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
1017 list='$(DISTFILES)'; \
1018 dist_files=`for file in $$list; do echo $$file; done | \
1019 sed -e "s|^$$srcdirstrip/||;t" \
1020 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
1021 case $$dist_files in \
1022 */*) $(MKDIR_P) `echo "$$dist_files" | \
1023 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
1024 sort -u` ;; \
1025 esac; \
1026 for file in $$dist_files; do \
1027 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
1028 if test -d $$d/$$file; then \
1029 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
1030 if test -d "$(distdir)/$$file"; then \
1031 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
1032 fi; \
1033 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
1034 cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
1035 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
1036 fi; \
1037 cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
1038 else \
1039 test -f "$(distdir)/$$file" \
1040 || cp -p $$d/$$file "$(distdir)/$$file" \
1041 || exit 1; \
1042 fi; \
1043 done
1044check-am: all-am
1045check: check-am
1046all-am: Makefile $(LTLIBRARIES)
1047installdirs:
1048 for dir in "$(DESTDIR)$(libdir)"; do \
1049 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
1050 done
1051install: install-am
1052install-exec: install-exec-am
1053install-data: install-data-am
1054uninstall: uninstall-am
1055
1056install-am: all-am
1057 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
1058
1059installcheck: installcheck-am
1060install-strip:
1061 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
1062 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
1063 `test -z '$(STRIP)' || \
1064 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
1065mostlyclean-generic:
1066
1067clean-generic:
1068
1069distclean-generic:
1070 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
1071 -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
1072
1073maintainer-clean-generic:
1074 @echo "This command is intended for maintainers to use"
1075 @echo "it deletes files that may require special tools to rebuild."
1076 -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
1077clean: clean-am
1078
1079clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
1080 mostlyclean-am
1081
1082distclean: distclean-am
1083 -rm -rf ./$(DEPDIR)
1084 -rm -f Makefile
1085distclean-am: clean-am distclean-compile distclean-generic \
1086 distclean-tags
1087
1088dvi: dvi-am
1089
1090dvi-am:
1091
1092html: html-am
1093
1094html-am:
1095
1096info: info-am
1097
1098info-am:
1099
1100install-data-am:
1101
1102install-dvi: install-dvi-am
1103
1104install-dvi-am:
1105
1106install-exec-am: install-libLTLIBRARIES
1107
1108install-html: install-html-am
1109
1110install-html-am:
1111
1112install-info: install-info-am
1113
1114install-info-am:
1115
1116install-man:
1117
1118install-pdf: install-pdf-am
1119
1120install-pdf-am:
1121
1122install-ps: install-ps-am
1123
1124install-ps-am:
1125
1126installcheck-am:
1127
1128maintainer-clean: maintainer-clean-am
1129 -rm -rf ./$(DEPDIR)
1130 -rm -f Makefile
1131maintainer-clean-am: distclean-am maintainer-clean-generic
1132
1133mostlyclean: mostlyclean-am
1134
1135mostlyclean-am: mostlyclean-compile mostlyclean-generic \
1136 mostlyclean-libtool
1137
1138pdf: pdf-am
1139
1140pdf-am:
1141
1142ps: ps-am
1143
1144ps-am:
1145
1146uninstall-am: uninstall-libLTLIBRARIES
1147
1148.MAKE: install-am install-strip
1149
1150.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
1151 clean-libLTLIBRARIES clean-libtool clean-local ctags distclean \
1152 distclean-compile distclean-generic distclean-libtool \
1153 distclean-tags distdir dvi dvi-am html html-am info info-am \
1154 install install-am install-data install-data-am install-dvi \
1155 install-dvi-am install-exec install-exec-am install-html \
1156 install-html-am install-info install-info-am \
1157 install-libLTLIBRARIES install-man install-pdf install-pdf-am \
1158 install-ps install-ps-am install-strip installcheck \
1159 installcheck-am installdirs maintainer-clean \
1160 maintainer-clean-generic mostlyclean mostlyclean-compile \
1161 mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
1162 tags uninstall uninstall-am uninstall-libLTLIBRARIES
1163
1164
1165@EINA_AMALGAMATION_TRUE@eina_amalgamation.c: $(base_sources) Makefile
1166@EINA_AMALGAMATION_TRUE@ -rm -f eina_amalgamation.c
1167
1168@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_CONFIG_H" >> eina_amalgamation.c
1169@EINA_AMALGAMATION_TRUE@ @echo "#include \"config.h\"" >> eina_amalgamation.c
1170@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c
1171
1172@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_ALLOCA_H" >> eina_amalgamation.c
1173@EINA_AMALGAMATION_TRUE@ @echo "# include <alloca.h>" >> eina_amalgamation.c
1174@EINA_AMALGAMATION_TRUE@ @echo "#elif defined __GNUC__" >> eina_amalgamation.c
1175@EINA_AMALGAMATION_TRUE@ @echo "# define alloca __builtin_alloca" >> eina_amalgamation.c
1176@EINA_AMALGAMATION_TRUE@ @echo "#elif defined _AIX" >> eina_amalgamation.c
1177@EINA_AMALGAMATION_TRUE@ @echo "# define alloca __alloca" >> eina_amalgamation.c
1178@EINA_AMALGAMATION_TRUE@ @echo "#elif defined _MSC_VER" >> eina_amalgamation.c
1179@EINA_AMALGAMATION_TRUE@ @echo "# include <malloc.h>" >> eina_amalgamation.c
1180@EINA_AMALGAMATION_TRUE@ @echo "# define alloca _alloca" >> eina_amalgamation.c
1181@EINA_AMALGAMATION_TRUE@ @echo "#else" >> eina_amalgamation.c
1182@EINA_AMALGAMATION_TRUE@ @echo "# include <stddef.h>" >> eina_amalgamation.c
1183@EINA_AMALGAMATION_TRUE@ @echo "# ifdef __cplusplus" >> eina_amalgamation.c
1184@EINA_AMALGAMATION_TRUE@ @echo "#extern \"C\"" >> eina_amalgamation.c
1185@EINA_AMALGAMATION_TRUE@ @echo "# endif" >> eina_amalgamation.c
1186@EINA_AMALGAMATION_TRUE@ @echo "#void *alloca (size_t);" >> eina_amalgamation.c
1187@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c
1188
1189@EINA_AMALGAMATION_TRUE@ @echo "#include <stdio.h>" >> eina_amalgamation.c
1190@EINA_AMALGAMATION_TRUE@ @echo "#include <stdlib.h>" >> eina_amalgamation.c
1191@EINA_AMALGAMATION_TRUE@ @echo "#include <string.h>" >> eina_amalgamation.c
1192@EINA_AMALGAMATION_TRUE@ @echo "#include <dlfcn.h>" >> eina_amalgamation.c
1193@EINA_AMALGAMATION_TRUE@ @echo "#include <sys/types.h>" >> eina_amalgamation.c
1194@EINA_AMALGAMATION_TRUE@ @echo "#include <dirent.h>" >> eina_amalgamation.c
1195@EINA_AMALGAMATION_TRUE@ @echo "#include <assert.h>" >> eina_amalgamation.c
1196@EINA_AMALGAMATION_TRUE@ @echo "#include <errno.h>" >> eina_amalgamation.c
1197@EINA_AMALGAMATION_TRUE@ @echo "#include <fnmatch.h>" >> eina_amalgamation.c
1198
1199@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c
1200@EINA_AMALGAMATION_TRUE@ @echo "# include <Evil.h>" >> eina_amalgamation.c
1201@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c
1202
1203@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_config.h\"" >> eina_amalgamation.c
1204@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_private.h\"" >> eina_amalgamation.c
1205@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_safety_checks.h\"" >> eina_amalgamation.c
1206@EINA_AMALGAMATION_TRUE@ @echo "#include \"Eina.h\"" >> eina_amalgamation.c
1207@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_strbuf_common.h\"" >> eina_amalgamation.c
1208@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_share_common.h\"" >> eina_amalgamation.c
1209
1210@EINA_AMALGAMATION_TRUE@ @for f in $(base_sources); do \
1211@EINA_AMALGAMATION_TRUE@ if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \
1212@EINA_AMALGAMATION_TRUE@ file="$(srcdir)/$$f" ; \
1213@EINA_AMALGAMATION_TRUE@ else \
1214@EINA_AMALGAMATION_TRUE@ file="$$f" ; \
1215@EINA_AMALGAMATION_TRUE@ fi ; \
1216@EINA_AMALGAMATION_TRUE@ echo "/* file: $$file */" >> eina_amalgamation.c; \
1217@EINA_AMALGAMATION_TRUE@ grep -v -e '^# *include \+.\(config\|eina_[a-z_]\+\|Evil\|stdio\|stdlib\|string\|dlfcn\|dirent\|assert\|errno\|fnmatch\)[.]h.*' $$file >> eina_amalgamation.c; \
1218@EINA_AMALGAMATION_TRUE@ done
1219@EINA_AMALGAMATION_TRUE@ @echo "eina_amalgamation.c generated"
1220
1221clean-local:
1222 rm -rf *.gcno eina_amalgamation.c
1223
1224# Tell versions [3.59,3.63) of GNU make to not export all variables.
1225# Otherwise a system limit (for SysV at least) may be exceeded.
1226.NOEXPORT:
diff --git a/libraries/eina/src/lib/eina_accessor.c b/libraries/eina/src/lib/eina_accessor.c
new file mode 100644
index 0000000..aec44ef
--- /dev/null
+++ b/libraries/eina/src/lib/eina_accessor.c
@@ -0,0 +1,176 @@
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 EINA_MAGIC_CHECK_ACCESSOR(accessor);
99 EINA_SAFETY_ON_NULL_RETURN(accessor);
100 EINA_SAFETY_ON_NULL_RETURN(accessor->free);
101 accessor->free(accessor);
102}
103
104EAPI void *
105eina_accessor_container_get(Eina_Accessor *accessor)
106{
107 EINA_MAGIC_CHECK_ACCESSOR(accessor);
108 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, NULL);
109 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_container, NULL);
110 return accessor->get_container(accessor);
111}
112
113EAPI Eina_Bool
114eina_accessor_data_get(Eina_Accessor *accessor,
115 unsigned int position,
116 void **data)
117{
118 EINA_MAGIC_CHECK_ACCESSOR(accessor);
119 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
120 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_at, EINA_FALSE);
121 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
122 return accessor->get_at(accessor, position, data);
123}
124
125EAPI void
126eina_accessor_over(Eina_Accessor *accessor,
127 Eina_Each_Cb cb,
128 unsigned int start,
129 unsigned int end,
130 const void *fdata)
131{
132 const void *container;
133 void *data;
134 unsigned int i;
135
136 EINA_MAGIC_CHECK_ACCESSOR(accessor);
137 EINA_SAFETY_ON_NULL_RETURN(accessor);
138 EINA_SAFETY_ON_NULL_RETURN(accessor->get_container);
139 EINA_SAFETY_ON_NULL_RETURN(accessor->get_at);
140 EINA_SAFETY_ON_NULL_RETURN(cb);
141 EINA_SAFETY_ON_FALSE_RETURN(start < end);
142
143 if (!eina_accessor_lock(accessor))
144 return ;
145
146 container = accessor->get_container(accessor);
147 for (i = start; i < end && accessor->get_at(accessor, i, &data) == EINA_TRUE;
148 ++i)
149 if (cb(container, data, (void *)fdata) != EINA_TRUE)
150 goto on_exit;
151
152 on_exit:
153 (void) eina_accessor_unlock(accessor);
154}
155
156EAPI Eina_Bool
157eina_accessor_lock(Eina_Accessor *accessor)
158{
159 EINA_MAGIC_CHECK_ACCESSOR(accessor);
160 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
161
162 if (accessor->lock)
163 return accessor->lock(accessor);
164 return EINA_TRUE;
165}
166
167EAPI Eina_Bool
168eina_accessor_unlock(Eina_Accessor *accessor)
169{
170 EINA_MAGIC_CHECK_ACCESSOR(accessor);
171 EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
172
173 if (accessor->unlock)
174 return accessor->unlock(accessor);
175 return EINA_TRUE;
176}
diff --git a/libraries/eina/src/lib/eina_array.c b/libraries/eina/src/lib/eina_array.c
new file mode 100644
index 0000000..5a850ac
--- /dev/null
+++ b/libraries/eina/src/lib/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_get(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_get(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/libraries/eina/src/lib/eina_benchmark.c b/libraries/eina/src/lib/eina_benchmark.c
new file mode 100644
index 0000000..1ba2a00
--- /dev/null
+++ b/libraries/eina/src/lib/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/libraries/eina/src/lib/eina_binbuf.c b/libraries/eina/src/lib/eina_binbuf.c
new file mode 100644
index 0000000..3cbebd1
--- /dev/null
+++ b/libraries/eina/src/lib/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/libraries/eina/src/lib/eina_binbuf_template_c.x b/libraries/eina/src/lib/eina_binbuf_template_c.x
new file mode 100644
index 0000000..613a715
--- /dev/null
+++ b/libraries/eina/src/lib/eina_binbuf_template_c.x
@@ -0,0 +1,144 @@
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 void
69_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf)
70{
71 EINA_MAGIC_CHECK_STRBUF(buf);
72 EINA_MAGIC_SET(buf, EINA_MAGIC_NONE);
73 eina_strbuf_common_free(buf);
74}
75
76EAPI void
77_FUNC_EXPAND(reset)(_STRBUF_STRUCT_NAME *buf)
78{
79 EINA_MAGIC_CHECK_STRBUF(buf);
80 eina_strbuf_common_reset(_STRBUF_CSIZE, buf);
81}
82
83EAPI Eina_Bool
84_FUNC_EXPAND(append_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length)
85{
86 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
87 return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, (const void *) str, length);
88}
89
90EAPI Eina_Bool
91_FUNC_EXPAND(insert_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length, size_t pos)
92{
93 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
94 return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, (const void *) str, length, pos);
95}
96
97EAPI Eina_Bool
98_FUNC_EXPAND(append_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c)
99{
100 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
101 return eina_strbuf_common_append_char(_STRBUF_CSIZE, buf, (const void *) &c);
102}
103
104EAPI Eina_Bool
105_FUNC_EXPAND(insert_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c, size_t pos)
106{
107 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
108 return eina_strbuf_common_insert_char(_STRBUF_CSIZE, buf, (const void *) &c, pos);
109}
110
111EAPI Eina_Bool
112_FUNC_EXPAND(remove)(_STRBUF_STRUCT_NAME *buf, size_t start, size_t end)
113{
114 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
115 return eina_strbuf_common_remove(_STRBUF_CSIZE, buf, start, end);
116}
117
118EAPI const _STRBUF_DATA_TYPE *
119_FUNC_EXPAND(string_get)(const _STRBUF_STRUCT_NAME *buf)
120{
121 EINA_MAGIC_CHECK_STRBUF(buf, NULL);
122 return (const _STRBUF_DATA_TYPE *) eina_strbuf_common_string_get(buf);
123}
124
125EAPI _STRBUF_DATA_TYPE *
126_FUNC_EXPAND(string_steal)(_STRBUF_STRUCT_NAME *buf)
127{
128 EINA_MAGIC_CHECK_STRBUF(buf, NULL);
129 return (_STRBUF_DATA_TYPE *) eina_strbuf_common_string_steal(_STRBUF_CSIZE, buf);
130}
131
132EAPI void
133_FUNC_EXPAND(string_free)(_STRBUF_STRUCT_NAME *buf)
134{
135 EINA_MAGIC_CHECK_STRBUF(buf);
136 eina_strbuf_common_string_free(_STRBUF_CSIZE, buf);
137}
138
139EAPI size_t
140_FUNC_EXPAND(length_get)(const _STRBUF_STRUCT_NAME *buf)
141{
142 EINA_MAGIC_CHECK_STRBUF(buf, 0);
143 return eina_strbuf_common_length_get(buf);
144}
diff --git a/libraries/eina/src/lib/eina_binshare.c b/libraries/eina/src/lib/eina_binshare.c
new file mode 100644
index 0000000..68a82fc
--- /dev/null
+++ b/libraries/eina/src/lib/eina_binshare.c
@@ -0,0 +1,127 @@
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#include "eina_share_common.h"
25#include "eina_unicode.h"
26#include "eina_private.h"
27#include "eina_binshare.h"
28
29/*============================================================================*
30 * Local *
31 *============================================================================*/
32
33/**
34 * @cond LOCAL
35 */
36
37/* The actual share */
38static Eina_Share *binshare_share;
39static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node";
40
41/**
42 * @endcond
43 */
44
45
46/*============================================================================*
47* Global *
48*============================================================================*/
49
50/**
51 * @internal
52 * @brief Initialize the share_common module.
53 *
54 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
55 *
56 * This function sets up the share_common module of Eina. It is called by
57 * eina_init().
58 *
59 * @see eina_init()
60 */
61EAPI Eina_Bool
62eina_binshare_init(void)
63{
64 return eina_share_common_init(&binshare_share,
65 EINA_MAGIC_BINSHARE_NODE,
66 EINA_MAGIC_BINSHARE_NODE_STR);
67}
68
69/**
70 * @internal
71 * @brief Shut down the share_common module.
72 *
73 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
74 *
75 * This function shuts down the share_common module set up by
76 * eina_share_common_init(). It is called by eina_shutdown().
77 *
78 * @see eina_shutdown()
79 */
80EAPI Eina_Bool
81eina_binshare_shutdown(void)
82{
83 Eina_Bool ret;
84 ret = eina_share_common_shutdown(&binshare_share);
85 return ret;
86}
87
88
89/*============================================================================*
90 * API *
91 *============================================================================*/
92
93EAPI void
94eina_binshare_del(const void *obj)
95{
96 if (!obj)
97 return;
98
99 eina_share_common_del(binshare_share, obj);
100}
101
102EAPI const void *
103eina_binshare_add_length(const void *obj, unsigned int olen)
104{
105 return eina_share_common_add_length(binshare_share,
106 obj,
107 (olen) * sizeof(char),
108 0);
109}
110
111EAPI const void *
112eina_binshare_ref(const void *obj)
113{
114 return eina_share_common_ref(binshare_share, obj);
115}
116
117EAPI int
118eina_binshare_length(const void *obj)
119{
120 return eina_share_common_length(binshare_share, obj);
121}
122
123EAPI void
124eina_binshare_dump(void)
125{
126 eina_share_common_dump(binshare_share, NULL, 0);
127}
diff --git a/libraries/eina/src/lib/eina_convert.c b/libraries/eina/src/lib/eina_convert.c
new file mode 100644
index 0000000..63b6654
--- /dev/null
+++ b/libraries/eina/src/lib/eina_convert.c
@@ -0,0 +1,483 @@
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,
117 * #EINA_ERROR_CONVERT_P_NOT_FOUND and
118 * #EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH.
119 *
120 * @see eina_init()
121 */
122Eina_Bool
123eina_convert_init(void)
124{
125 _eina_convert_log_dom = eina_log_domain_register("eina_convert",
126 EINA_LOG_COLOR_DEFAULT);
127 if (_eina_convert_log_dom < 0)
128 {
129 EINA_LOG_ERR("Could not register log domain: eina_convert");
130 return EINA_FALSE;
131 }
132
133#define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
134 EEMR(EINA_ERROR_CONVERT_0X_NOT_FOUND);
135 EEMR(EINA_ERROR_CONVERT_P_NOT_FOUND);
136 EEMR(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
137#undef EEMR
138
139 return EINA_TRUE;
140}
141
142/**
143 * @internal
144 * @brief Shut down the convert module.
145 *
146 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
147 *
148 * This function shuts down the convert module set up by
149 * eina_convert_init(). It is called by eina_shutdown().
150 *
151 * @see eina_shutdown()
152 */
153Eina_Bool
154eina_convert_shutdown(void)
155{
156 eina_log_domain_unregister(_eina_convert_log_dom);
157 _eina_convert_log_dom = -1;
158 return EINA_TRUE;
159}
160
161/*============================================================================*
162* API *
163*============================================================================*/
164
165/*
166 * Come from the second edition of The C Programming Language ("K&R2") on page 64
167 */
168
169EAPI int
170eina_convert_itoa(int n, char *s)
171{
172 int i = 0;
173 int r = 0;
174
175 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
176
177 if (n < 0)
178 {
179 n = -n;
180 *s++ = '-';
181 r = 1;
182 }
183
184 do {
185 s[i++] = n % 10 + '0';
186 } while ((n /= 10) > 0);
187
188 s[i] = '\0';
189
190 reverse(s, i);
191
192 return i + r;
193}
194
195EAPI int
196eina_convert_xtoa(unsigned int n, char *s)
197{
198 int i;
199
200 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
201
202 i = 0;
203 do {
204 s[i++] = look_up_table[n & 0xF];
205 } while ((n >>= 4) > 0);
206
207 s[i] = '\0';
208
209 reverse(s, i);
210
211 return i;
212}
213
214EAPI Eina_Bool
215eina_convert_atod(const char *src, int length, long long *m, long *e)
216{
217 const char *str = src;
218 long long mantisse;
219 long exponent;
220 int nbr_decimals = 0;
221 int sign = 1;
222
223 EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
226
227 if (length <= 0)
228 goto on_length_error;
229
230 /* Compute the mantisse. */
231 if (*str == '-')
232 {
233 sign = -1;
234 str++;
235 length--;
236 }
237
238 if (length <= 2)
239 goto on_length_error;
240
241 if (strncmp(str, "0x", 2))
242 {
243 eina_error_set(EINA_ERROR_CONVERT_0X_NOT_FOUND);
244 DBG("'0x' not found in '%s'", src);
245 return EINA_FALSE;
246 }
247
248 str += 2;
249 length -= 2;
250
251 mantisse = HEXA_TO_INT(*str);
252
253 str++;
254 length--; if (length <= 0)
255 goto on_length_error;
256
257 if (*str == '.')
258 for (str++, length--;
259 length > 0 && *str != 'p';
260 ++str, --length, ++nbr_decimals)
261 {
262 mantisse <<= 4;
263 mantisse += HEXA_TO_INT(*str);
264 }
265
266 if (sign < 0)
267 mantisse = -mantisse;
268
269 /* Compute the exponent. */
270 if (*str != 'p')
271 {
272 eina_error_set(EINA_ERROR_CONVERT_P_NOT_FOUND);
273 DBG("'p' not found in '%s'", src);
274 return EINA_FALSE;
275 }
276
277 sign = +1;
278
279 str++;
280 length--; if (length <= 0)
281 goto on_length_error;
282
283 if (strchr("-+", *str))
284 {
285 sign = (*str == '-') ? -1 : +1;
286
287 str++; length--;
288 }
289
290 for (exponent = 0; length > 0 && *str != '\0'; ++str, --length)
291 {
292 exponent *= 10;
293 exponent += *str - '0';
294 }
295
296 if (length < 0)
297 goto on_length_error;
298
299 if (sign < 0)
300 exponent = -exponent;
301
302 *m = mantisse;
303 *e = exponent - (nbr_decimals << 2);
304
305 return EINA_TRUE;
306
307on_length_error:
308 eina_error_set(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
309 return EINA_FALSE;
310}
311
312EAPI int
313eina_convert_dtoa(double d, char *des)
314{
315 int length = 0;
316 int p;
317 int i;
318
319 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
320
321 if (d < 0.0)
322 {
323 *(des++) = '-';
324 d = -d;
325 length++;
326 }
327
328 d = frexp(d, &p);
329
330 if (p)
331 {
332 d *= 2;
333 p -= 1;
334 }
335
336 *(des++) = '0';
337 *(des++) = 'x';
338 *(des++) = look_up_table[(size_t)d];
339 *(des++) = '.';
340 length += 4;
341
342 for (i = 0; i < 16; i++, length++)
343 {
344 d -= floor(d);
345 d *= 16;
346 *(des++) = look_up_table[(size_t)d];
347 }
348
349 while (*(des - 1) == '0')
350 {
351 des--;
352 length--;
353 }
354
355 if (*(des - 1) == '.')
356 {
357 des--;
358 length--;
359 }
360
361 *(des++) = 'p';
362 if (p < 0)
363 {
364 *(des++) = '-';
365 p = -p;
366 }
367 else
368 *(des++) = '+';
369
370 length += 2;
371
372 return length + eina_convert_itoa(p, des);
373}
374
375EAPI int
376eina_convert_fptoa(Eina_F32p32 fp, char *des)
377{
378 int length = 0;
379 int p = 0;
380 int i;
381
382 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
383
384 if (fp == 0)
385 {
386 memcpy(des, "0x0p+0", 7);
387 return 7;
388 }
389
390 if (fp < 0)
391 {
392 *(des++) = '-';
393 fp = -fp;
394 length++;
395 }
396
397 /* fp >= 1 */
398 if (fp >= 0x0000000100000000LL)
399 while (fp >= 0x0000000100000000LL)
400 {
401 p++;
402 /* fp /= 2 */
403 fp >>= 1;
404 } /* fp < 0.5 */
405 else if (fp < 0x80000000)
406 while (fp < 0x80000000)
407 {
408 p--;
409 /* fp *= 2 */
410 fp <<= 1;
411 }
412
413 if (p)
414 {
415 p--;
416 /* fp *= 2 */
417 fp <<= 1;
418 }
419
420 *(des++) = '0';
421 *(des++) = 'x';
422 *(des++) = look_up_table[fp >> 32];
423 *(des++) = '.';
424 length += 4;
425
426 for (i = 0; i < 16; i++, length++)
427 {
428 fp &= 0x00000000ffffffffLL;
429 fp <<= 4; /* fp *= 16 */
430 *(des++) = look_up_table[fp >> 32];
431 }
432
433 while (*(des - 1) == '0')
434 {
435 des--;
436 length--;
437 }
438
439 if (*(des - 1) == '.')
440 {
441 des--;
442 length--;
443 }
444
445 *(des++) = 'p';
446 if (p < 0)
447 {
448 *(des++) = '-';
449 p = -p;
450 }
451 else
452 *(des++) = '+';
453
454 length += 2;
455
456 return length + eina_convert_itoa(p, des);
457}
458
459EAPI Eina_Bool
460eina_convert_atofp(const char *src, int length, Eina_F32p32 *fp)
461{
462 long long m;
463 long e;
464
465 if (!eina_convert_atod(src, length, &m, &e))
466 return EINA_FALSE;
467
468 if (!fp)
469 return EINA_TRUE;
470
471 e += 32;
472
473 if (e > 0)
474 *fp = m << e;
475 else
476 *fp = m >> -e;
477
478 return EINA_TRUE;
479}
480
481/**
482 * @}
483 */
diff --git a/libraries/eina/src/lib/eina_counter.c b/libraries/eina/src/lib/eina_counter.c
new file mode 100644
index 0000000..6ca9417
--- /dev/null
+++ b/libraries/eina/src/lib/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/libraries/eina/src/lib/eina_cpu.c b/libraries/eina/src/lib/eina_cpu.c
new file mode 100644
index 0000000..8af550d
--- /dev/null
+++ b/libraries/eina/src/lib/eina_cpu.c
@@ -0,0 +1,207 @@
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 (__SUNPRO_C) || 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 <stdio.h>
46#include <string.h>
47#include <errno.h>
48
49#include "eina_cpu.h"
50
51/*============================================================================*
52* Local *
53*============================================================================*/
54
55/* FIXME this ifdefs should be replaced */
56#if defined(__i386__) || defined(__x86_64__)
57/* We save ebx and restore it to be PIC compatible */
58static inline void _x86_cpuid(int op, int *a, int *b, int *c, int *d)
59{
60 asm volatile (
61#if defined(__x86_64__)
62 "pushq %%rbx \n\t" /* save %ebx */
63#else
64 "pushl %%ebx \n\t" /* save %ebx */
65#endif
66 "cpuid \n\t"
67 "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */
68#if defined(__x86_64__)
69 "popq %%rbx \n\t" /* restore the old %ebx */
70#else
71 "popl %%ebx \n\t" /* restore the old %ebx */
72#endif
73 : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
74 : "a" (op)
75 : "cc");
76}
77
78static
79void _x86_simd(Eina_Cpu_Features *features)
80{
81 int a, b, c, d;
82
83 _x86_cpuid(1, &a, &b, &c, &d);
84 /*
85 * edx
86 * 18 = PN (Processor Number)
87 * 19 = CLFlush (Cache Line Flush)
88 * 23 = MMX
89 * 25 = SSE
90 * 26 = SSE2
91 * 28 = HTT (Hyper Threading)
92 * ecx
93 * 0 = SSE3
94 */
95 if ((d >> 23) & 1)
96 *features |= EINA_CPU_MMX;
97
98 if ((d >> 25) & 1)
99 *features |= EINA_CPU_SSE;
100
101 if ((d >> 26) & 1)
102 *features |= EINA_CPU_SSE2;
103
104 if (c & 1)
105 *features |= EINA_CPU_SSE3;
106}
107#endif
108
109/*============================================================================*
110* Global *
111*============================================================================*/
112
113/*============================================================================*
114* API *
115*============================================================================*/
116
117/* FIXME the features checks should be called when this function is called?
118 * or make it static by doing eina_cpu_init() and return a local var
119 */
120/**
121 *
122 * @return
123 */
124EAPI Eina_Cpu_Features eina_cpu_features_get(void)
125{
126 Eina_Cpu_Features ecf = 0;
127#if defined(__i386__) || defined(__x86_64__)
128 _x86_simd(&ecf);
129#endif
130 return ecf;
131}
132
133EAPI int eina_cpu_count(void)
134{
135#ifdef EFL_HAVE_THREADS
136
137# if defined (_WIN32)
138 SYSTEM_INFO sysinfo;
139
140 GetSystemInfo(&sysinfo);
141 return sysinfo.dwNumberOfProcessors;
142
143# elif defined (__SUNPRO_C) || defined(__GNU__)
144 /*
145 * _SC_NPROCESSORS_ONLN: number of processors that are online, that
146 is available when sysconf is called. The number
147 of cpu can change by admins.
148 * _SC_NPROCESSORS_CONF: maximum number of processors that are available
149 to the current OS instance. That number can be
150 change after a reboot.
151 * _SC_NPROCESSORS_MAX : maximum number of processors that are on the
152 motherboard.
153 */
154 return sysconf(_SC_NPROCESSORS_ONLN);
155
156# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \
157 defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \
158 (defined (__MACH__) && defined (__APPLE__))
159
160 int mib[4];
161 int cpus;
162 size_t len = sizeof(cpus);
163
164 mib[0] = CTL_HW;
165#ifdef HW_AVAILCPU
166 mib[1] = HW_AVAILCPU;
167#else
168 mib[1] = HW_NCPU;
169#endif
170 sysctl(mib, 2, &cpus, &len, NULL, 0);
171 if (cpus < 1)
172 cpus = 1;
173
174 return cpus;
175
176# elif defined (__linux__) || defined(__GLIBC__)
177 cpu_set_t cpu;
178 int i;
179 static int cpus = 0;
180
181 if (cpus != 0)
182 return cpus;
183
184 CPU_ZERO(&cpu);
185 if (sched_getaffinity(0, sizeof(cpu), &cpu) != 0)
186 {
187 fprintf(stderr, "[Eina] could not get cpu affinity: %s\n",
188 strerror(errno));
189 return 1;
190 }
191
192 for (i = 0; i < TH_MAX; i++)
193 {
194 if (CPU_ISSET(i, &cpu))
195 cpus = i + 1;
196 else
197 break;
198 }
199 return cpus;
200
201# else
202# error "eina_cpu_count() error: Platform not supported"
203# endif
204#else
205 return 1;
206#endif
207}
diff --git a/libraries/eina/src/lib/eina_error.c b/libraries/eina/src/lib/eina_error.c
new file mode 100644
index 0000000..428c414
--- /dev/null
+++ b/libraries/eina/src/lib/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/libraries/eina/src/lib/eina_file.c b/libraries/eina/src/lib/eina_file.c
new file mode 100644
index 0000000..84b9e78
--- /dev/null
+++ b/libraries/eina/src/lib/eina_file.c
@@ -0,0 +1,1187 @@
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 <string.h>
42#include <stddef.h>
43#include <dirent.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <unistd.h>
47#include <sys/mman.h>
48#include <fcntl.h>
49
50#define PATH_DELIM '/'
51
52#include "eina_config.h"
53#include "eina_private.h"
54
55/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
56#include "eina_safety_checks.h"
57#include "eina_file.h"
58#include "eina_stringshare.h"
59#include "eina_hash.h"
60#include "eina_list.h"
61#include "eina_lock.h"
62#include "eina_mmap.h"
63
64#ifdef HAVE_ESCAPE_H
65# include <Escape.h>
66#endif
67
68/*============================================================================*
69 * Local *
70 *============================================================================*/
71
72/**
73 * @cond LOCAL
74 */
75
76#ifndef EINA_LOG_COLOR_DEFAULT
77#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
78#endif
79
80#ifdef ERR
81#undef ERR
82#endif
83#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
84
85#ifdef WRN
86#undef WRN
87#endif
88#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
89
90#ifdef DBG
91#undef DBG
92#endif
93#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
94
95#define EINA_SMALL_PAGE 4096
96# define EINA_HUGE_PAGE 16 * 1024 * 1024
97
98typedef struct _Eina_File_Iterator Eina_File_Iterator;
99typedef struct _Eina_File_Map Eina_File_Map;
100
101struct _Eina_File_Iterator
102{
103 Eina_Iterator iterator;
104
105 DIR *dirp;
106 int length;
107
108 char dir[1];
109};
110
111struct _Eina_File
112{
113 const char *filename;
114
115 Eina_Hash *map;
116 Eina_Hash *rmap;
117 void *global_map;
118
119 Eina_Lock lock;
120
121 unsigned long long length;
122 time_t mtime;
123 ino_t inode;
124#ifdef _STAT_VER_LINUX
125 unsigned long int mtime_nsec;
126#endif
127
128 int refcount;
129 int global_refcount;
130
131 int fd;
132
133 Eina_Bool shared : 1;
134 Eina_Bool delete_me : 1;
135};
136
137struct _Eina_File_Map
138{
139 void *map;
140
141 unsigned long int offset;
142 unsigned long int length;
143
144 int refcount;
145
146 Eina_Bool hugetlb : 1;
147};
148
149static Eina_Hash *_eina_file_cache = NULL;
150static Eina_Lock _eina_file_lock_cache;
151
152static int _eina_file_log_dom = -1;
153
154/*
155 * This complex piece of code is needed due to possible race condition.
156 * The code and description of the issue can be found at :
157 * http://womble.decadent.org.uk/readdir_r-advisory.html
158 */
159static long
160_eina_name_max(DIR *dirp)
161{
162 long name_max;
163
164#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX)
165 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
166
167 if (name_max == -1)
168 {
169# if defined(NAME_MAX)
170 name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
171# else
172 name_max = PATH_MAX;
173# endif
174 }
175#else
176# if defined(NAME_MAX)
177 name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
178# else
179# ifdef _PC_NAME_MAX
180# warning "buffer size for readdir_r cannot be determined safely, best effort, but racy"
181 name_max = pathconf(dirp, _PC_NAME_MAX);
182# else
183# error "buffer size for readdir_r cannot be determined safely"
184# endif
185# endif
186#endif
187
188 return name_max;
189}
190
191static size_t
192_eina_dirent_buffer_size(DIR *dirp)
193{
194 long name_max = _eina_name_max(dirp);
195 size_t name_end;
196
197 name_end = (size_t) offsetof(struct dirent, d_name) + name_max + 1;
198
199 return (name_end > sizeof (struct dirent) ? name_end : sizeof (struct dirent));
200}
201
202static Eina_Bool
203_eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data)
204{
205 struct dirent *dp;
206 char *name;
207 size_t length;
208
209 dp = alloca(_eina_dirent_buffer_size(it->dirp));
210
211 do
212 {
213 if (readdir_r(it->dirp, dp, &dp))
214 return EINA_FALSE;
215 if (dp == NULL)
216 return EINA_FALSE;
217 }
218 while ((dp->d_name[0] == '.') &&
219 ((dp->d_name[1] == '\0') ||
220 ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
221
222#ifdef _DIRENT_HAVE_D_NAMLEN
223 length = dp->d_namlen;
224#else
225 length = strlen(dp->d_name);
226#endif
227 name = alloca(length + 2 + it->length);
228
229 memcpy(name, it->dir, it->length);
230 memcpy(name + it->length, "/", 1);
231 memcpy(name + it->length + 1, dp->d_name, length + 1);
232
233 *data = (char *)eina_stringshare_add(name);
234 return EINA_TRUE;
235}
236
237static DIR *
238_eina_file_ls_iterator_container(Eina_File_Iterator *it)
239{
240 return it->dirp;
241}
242
243static void
244_eina_file_ls_iterator_free(Eina_File_Iterator *it)
245{
246 closedir(it->dirp);
247
248 EINA_MAGIC_SET(&it->iterator, 0);
249 free(it);
250}
251
252typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
253struct _Eina_File_Direct_Iterator
254{
255 Eina_Iterator iterator;
256
257 DIR *dirp;
258 int length;
259
260 Eina_File_Direct_Info info;
261
262 char dir[1];
263};
264
265static Eina_Bool
266_eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
267{
268 struct dirent *dp;
269 size_t length;
270
271 dp = alloca(_eina_dirent_buffer_size(it->dirp));
272
273 do
274 {
275 if (readdir_r(it->dirp, dp, &dp))
276 return EINA_FALSE;
277 if (!dp)
278 return EINA_FALSE;
279
280#ifdef _DIRENT_HAVE_D_NAMLEN
281 length = dp->d_namlen;
282#else
283 length = strlen(dp->d_name);
284#endif
285 if (it->info.name_start + length + 1 >= EINA_PATH_MAX)
286 continue;
287 }
288 while ((dp->d_name[0] == '.') &&
289 ((dp->d_name[1] == '\0') ||
290 ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
291
292 memcpy(it->info.path + it->info.name_start, dp->d_name, length);
293 it->info.name_length = length;
294 it->info.path_length = it->info.name_start + length;
295 it->info.path[it->info.path_length] = '\0';
296
297#ifdef _DIRENT_HAVE_D_TYPE
298 switch (dp->d_type)
299 {
300 case DT_FIFO:
301 it->info.type = EINA_FILE_FIFO;
302 break;
303 case DT_CHR:
304 it->info.type = EINA_FILE_CHR;
305 break;
306 case DT_DIR:
307 it->info.type = EINA_FILE_DIR;
308 break;
309 case DT_BLK:
310 it->info.type = EINA_FILE_BLK;
311 break;
312 case DT_REG:
313 it->info.type = EINA_FILE_REG;
314 break;
315 case DT_LNK:
316 it->info.type = EINA_FILE_LNK;
317 break;
318 case DT_SOCK:
319 it->info.type = EINA_FILE_SOCK;
320 break;
321 case DT_WHT:
322 it->info.type = EINA_FILE_WHT;
323 break;
324 default:
325 it->info.type = EINA_FILE_UNKNOWN;
326 break;
327 }
328#else
329 it->info.type = EINA_FILE_UNKNOWN;
330#endif
331
332 *data = &it->info;
333 return EINA_TRUE;
334}
335
336static DIR *
337_eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
338{
339 return it->dirp;
340}
341
342static void
343_eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
344{
345 closedir(it->dirp);
346
347 EINA_MAGIC_SET(&it->iterator, 0);
348 free(it);
349}
350
351static Eina_Bool
352_eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
353{
354 struct stat st;
355
356 if (!_eina_file_direct_ls_iterator_next(it, data))
357 return EINA_FALSE;
358
359 if (it->info.type == EINA_FILE_UNKNOWN)
360 {
361#ifdef HAVE_FSTATAT
362 int fd;
363
364 fd = dirfd(it->dirp);
365 if (fstatat(fd, it->info.path + it->info.name_start, &st, 0))
366#else
367 if (stat(it->info.path, &st))
368#endif
369 it->info.type = EINA_FILE_UNKNOWN;
370 else
371 {
372 if (S_ISREG(st.st_mode))
373 it->info.type = EINA_FILE_REG;
374 else if (S_ISDIR(st.st_mode))
375 it->info.type = EINA_FILE_DIR;
376 else if (S_ISCHR(st.st_mode))
377 it->info.type = EINA_FILE_CHR;
378 else if (S_ISBLK(st.st_mode))
379 it->info.type = EINA_FILE_BLK;
380 else if (S_ISFIFO(st.st_mode))
381 it->info.type = EINA_FILE_FIFO;
382 else if (S_ISLNK(st.st_mode))
383 it->info.type = EINA_FILE_LNK;
384 else if (S_ISSOCK(st.st_mode))
385 it->info.type = EINA_FILE_SOCK;
386 else
387 it->info.type = EINA_FILE_UNKNOWN;
388 }
389 }
390
391 return EINA_TRUE;
392}
393
394static void
395_eina_file_real_close(Eina_File *file)
396{
397 if (file->refcount != 0) return;
398
399 eina_hash_free(file->rmap);
400 eina_hash_free(file->map);
401
402 if (file->global_map != MAP_FAILED)
403 munmap(file->global_map, file->length);
404
405 close(file->fd);
406
407 free(file);
408}
409
410static void
411_eina_file_map_close(Eina_File_Map *map)
412{
413 munmap(map->map, map->length);
414 free(map);
415}
416
417static unsigned int
418_eina_file_map_key_length(const void *key __UNUSED__)
419{
420 return sizeof (unsigned long int) * 2;
421}
422
423static int
424_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__,
425 const unsigned long int *key2, int key2_length __UNUSED__)
426{
427 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
428 return key1[0] - key2[0];
429}
430
431static int
432_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__)
433{
434 return eina_hash_int64(&key[0], sizeof (unsigned long int))
435 ^ eina_hash_int64(&key[1], sizeof (unsigned long int));
436}
437
438#ifndef MAP_POPULATE
439static unsigned int
440_eina_file_map_populate(char *map, unsigned int size, Eina_Bool hugetlb)
441{
442 unsigned int r = 0xDEADBEEF;
443 unsigned int i;
444 unsigned int s;
445
446 s = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE;
447
448 for (i = 0; i < size; i += s)
449 r ^= map[i];
450
451 r ^= map[size];
452
453 return r;
454}
455#endif
456
457static int
458_eina_file_map_rule_apply(Eina_File_Populate rule, void *addr, unsigned long int size, Eina_Bool hugetlb)
459{
460 int tmp = 42;
461 int flag = MADV_RANDOM;
462
463 switch (rule)
464 {
465 case EINA_FILE_RANDOM: flag = MADV_RANDOM; break;
466 case EINA_FILE_SEQUENTIAL: flag = MADV_SEQUENTIAL; break;
467 case EINA_FILE_POPULATE: flag = MADV_WILLNEED; break;
468 case EINA_FILE_WILLNEED: flag = MADV_WILLNEED; break;
469 }
470
471 madvise(addr, size, flag);
472
473#ifndef MAP_POPULATE
474 if (rule == EINA_FILE_POPULATE)
475 tmp ^= _eina_file_map_populate(addr, size, hugetlb);
476#else
477 (void) hugetlb;
478#endif
479
480 return tmp;
481}
482
483static Eina_Bool
484_eina_file_timestamp_compare(Eina_File *f, struct stat *st)
485{
486 if (f->mtime != st->st_mtime) return EINA_FALSE;
487 if (f->length != (unsigned long long) st->st_size) return EINA_FALSE;
488 if (f->inode != st->st_ino) return EINA_FALSE;
489#ifdef _STAT_VER_LINUX
490# if (defined __USE_MISC && defined st_mtime)
491 if (f->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
492 return EINA_FALSE;
493# else
494 if (f->mtime_nsec != (unsigned long int)st->st_mtimensec)
495 return EINA_FALSE;
496# endif
497#endif
498 return EINA_TRUE;
499}
500
501static void
502slprintf(char *str, size_t size, const char *format, ...)
503{
504 va_list ap;
505
506 va_start(ap, format);
507
508 vsnprintf(str, size, format, ap);
509 str[size - 1] = 0;
510
511 va_end(ap);
512}
513
514static char*
515_eina_file_escape(const char* path, int* length)
516{
517 char *result = strdup(path ? path : "");
518 char *p = result;
519 char *q = result;
520 int len;
521
522 if (!result)
523 return NULL;
524
525 if (length) len = *length;
526 else len = strlen(result);
527
528 while ((p = strchr(p, '/')))
529 {
530 // remove double `/'
531 if (p[1] == '/')
532 {
533 memmove(p, p + 1, --len - (p - result));
534 result[len] = '\0';
535 }
536 else
537 if (p[1] == '.'
538 && p[2] == '.')
539 {
540 // remove `/../'
541 if (p[3] == '/')
542 {
543 char tmp;
544
545 len -= p + 3 - q;
546 memmove(q, p + 3, len - (q - result));
547 result[len] = '\0';
548 p = q;
549
550 /* Update q correctly. */
551 tmp = *p;
552 *p = '\0';
553 q = strrchr(result, '/');
554 if (!q) q = result;
555 *p = tmp;
556 }
557 else
558 // remove '/..$'
559 if (p[3] == '\0')
560 {
561 len -= p + 2 - q;
562 result[len] = '\0';
563 q = p;
564 ++p;
565 }
566 else
567 {
568 q = p;
569 ++p;
570 }
571 }
572 else
573 {
574 q = p;
575 ++p;
576 }
577 }
578
579 if (length)
580 *length = len;
581 return result;
582}
583
584Eina_Bool
585eina_file_init(void)
586{
587 _eina_file_log_dom = eina_log_domain_register("eina_file",
588 EINA_LOG_COLOR_DEFAULT);
589 if (_eina_file_log_dom < 0)
590 {
591 EINA_LOG_ERR("Could not register log domain: eina_file");
592 return EINA_FALSE;
593 }
594
595 _eina_file_cache = eina_hash_string_djb2_new(NULL);
596 if (!_eina_file_cache)
597 {
598 ERR("Could not create cache.");
599 eina_log_domain_unregister(_eina_file_log_dom);
600 _eina_file_log_dom = -1;
601 return EINA_FALSE;
602 }
603
604 eina_lock_new(&_eina_file_lock_cache);
605
606 return EINA_TRUE;
607}
608
609Eina_Bool
610eina_file_shutdown(void)
611{
612 if (eina_hash_population(_eina_file_cache) > 0)
613 {
614 Eina_Iterator *it;
615 const char *key;
616
617 it = eina_hash_iterator_key_new(_eina_file_cache);
618 EINA_ITERATOR_FOREACH(it, key)
619 ERR("File [%s] still open !", key);
620 eina_iterator_free(it);
621 }
622
623 eina_hash_free(_eina_file_cache);
624
625 eina_lock_free(&_eina_file_lock_cache);
626
627 eina_log_domain_unregister(_eina_file_log_dom);
628 _eina_file_log_dom = -1;
629 return EINA_TRUE;
630}
631
632/**
633 * @endcond
634 */
635
636/*============================================================================*
637 * Global *
638 *============================================================================*/
639
640/*============================================================================*
641 * API *
642 *============================================================================*/
643
644EAPI char *
645eina_file_path_sanitize(const char *path)
646{
647 char *result = NULL;
648 int len;
649
650 if (!path) return NULL;
651
652 len = strlen(path);
653
654 if (*path != '/')
655 {
656 char cwd[PATH_MAX];
657 char *tmp = NULL;
658
659 tmp = getcwd(cwd, PATH_MAX);
660 if (!tmp) return NULL;
661
662 len += strlen(cwd) + 2;
663 tmp = alloca(sizeof (char) * len);
664
665 slprintf(tmp, len, "%s/%s", cwd, path);
666
667 result = tmp;
668 }
669
670 return _eina_file_escape(result ? result : path, &len);
671}
672
673EAPI Eina_Bool
674eina_file_dir_list(const char *dir,
675 Eina_Bool recursive,
676 Eina_File_Dir_List_Cb cb,
677 void *data)
678{
679 Eina_File_Direct_Info *info;
680 Eina_Iterator *it;
681
682 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
683 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
684 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
685
686 it = eina_file_stat_ls(dir);
687 if (!it)
688 return EINA_FALSE;
689
690 EINA_ITERATOR_FOREACH(it, info)
691 {
692 cb(info->path + info->name_start, dir, data);
693
694 if (recursive == EINA_TRUE && info->type == EINA_FILE_DIR)
695 {
696 eina_file_dir_list(info->path, recursive, cb, data);
697 }
698 }
699
700 eina_iterator_free(it);
701
702 return EINA_TRUE;
703}
704
705EAPI Eina_Array *
706eina_file_split(char *path)
707{
708 Eina_Array *ea;
709 char *current;
710 size_t length;
711
712 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
713
714 ea = eina_array_new(16);
715
716 if (!ea)
717 return NULL;
718
719 for (current = strchr(path, PATH_DELIM);
720 current;
721 path = current + 1, current = strchr(path, PATH_DELIM))
722 {
723 length = current - path;
724
725 if (length <= 0)
726 continue;
727
728 eina_array_push(ea, path);
729 *current = '\0';
730 }
731
732 if (*path != '\0')
733 eina_array_push(ea, path);
734
735 return ea;
736}
737
738EAPI Eina_Iterator *
739eina_file_ls(const char *dir)
740{
741 Eina_File_Iterator *it;
742 size_t length;
743
744 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
745
746 length = strlen(dir);
747 if (length < 1)
748 return NULL;
749
750 it = calloc(1, sizeof (Eina_File_Iterator) + length);
751 if (!it)
752 return NULL;
753
754 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
755
756 it->dirp = opendir(dir);
757 if (!it->dirp)
758 {
759 free(it);
760 return NULL;
761 }
762
763 memcpy(it->dir, dir, length + 1);
764 if (dir[length - 1] != '/')
765 it->length = length;
766 else
767 it->length = length - 1;
768
769 it->iterator.version = EINA_ITERATOR_VERSION;
770 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_ls_iterator_next);
771 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
772 _eina_file_ls_iterator_container);
773 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free);
774
775 return &it->iterator;
776}
777
778EAPI Eina_Iterator *
779eina_file_direct_ls(const char *dir)
780{
781 Eina_File_Direct_Iterator *it;
782 size_t length;
783
784 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
785
786 length = strlen(dir);
787 if (length < 1)
788 return NULL;
789
790 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
791 if (!it)
792 return NULL;
793
794 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
795
796 it->dirp = opendir(dir);
797 if (!it->dirp)
798 {
799 free(it);
800 return NULL;
801 }
802
803 if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX)
804 {
805 _eina_file_direct_ls_iterator_free(it);
806 return NULL;
807 }
808
809 memcpy(it->dir, dir, length + 1);
810 it->length = length;
811
812 memcpy(it->info.path, dir, length);
813 if (dir[length - 1] == '/')
814 it->info.name_start = length;
815 else
816 {
817 it->info.path[length] = '/';
818 it->info.name_start = length + 1;
819 }
820
821 it->iterator.version = EINA_ITERATOR_VERSION;
822 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_direct_ls_iterator_next);
823 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
824 _eina_file_direct_ls_iterator_container);
825 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
826
827 return &it->iterator;
828}
829
830EAPI Eina_Iterator *
831eina_file_stat_ls(const char *dir)
832{
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_stat_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}
881
882EAPI Eina_File *
883eina_file_open(const char *path, Eina_Bool shared)
884{
885 Eina_File *file;
886 Eina_File *n;
887 char *filename;
888 struct stat file_stat;
889 int fd = -1;
890 int flags;
891
892 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
893
894 filename = eina_file_path_sanitize(path);
895 if (!filename) return NULL;
896
897 if (shared)
898#ifdef HAVE_SHMOPEN
899 fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
900#else
901 goto on_error;
902#endif
903 else
904 fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
905
906 if (fd < 0) goto on_error;
907
908#ifdef HAVE_EXECVP
909 flags = fcntl(fd, F_GETFD);
910 if (flags == -1)
911 goto on_error;
912
913 flags |= FD_CLOEXEC;
914 if (fcntl(fd, F_SETFD, flags) == -1)
915 goto on_error;
916#endif
917
918 if (fstat(fd, &file_stat))
919 goto on_error;
920
921 eina_lock_take(&_eina_file_lock_cache);
922
923 file = eina_hash_find(_eina_file_cache, filename);
924 if ((file) && _eina_file_timestamp_compare(file, &file_stat))
925 {
926 file->delete_me = EINA_TRUE;
927 eina_hash_del(_eina_file_cache, file->filename, file);
928 _eina_file_real_close(file);
929 file = NULL;
930 }
931
932 if (!file)
933 {
934 n = malloc(sizeof (Eina_File) + strlen(filename) + 1);
935 if (!n)
936 {
937 eina_lock_release(&_eina_file_lock_cache);
938 goto on_error;
939 }
940
941 n->filename = (char*) (n + 1);
942 strcpy((char*) n->filename, filename);
943 n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
944 EINA_KEY_CMP(_eina_file_map_key_cmp),
945 EINA_KEY_HASH(_eina_file_map_key_hash),
946 EINA_FREE_CB(_eina_file_map_close),
947 3);
948 n->rmap = eina_hash_pointer_new(NULL);
949 n->global_map = MAP_FAILED;
950 n->global_refcount = 0;
951 n->length = file_stat.st_size;
952 n->mtime = file_stat.st_mtime;
953#ifdef _STAT_VER_LINUX
954# if (defined __USE_MISC && defined st_mtime)
955 n->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
956# else
957 n->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
958# endif
959#endif
960 n->inode = file_stat.st_ino;
961 n->refcount = 0;
962 n->fd = fd;
963 n->shared = shared;
964 n->delete_me = EINA_FALSE;
965 eina_lock_new(&n->lock);
966 eina_hash_direct_add(_eina_file_cache, n->filename, n);
967 }
968 else
969 {
970 close(fd);
971 n = file;
972 }
973 eina_lock_take(&n->lock);
974 n->refcount++;
975 eina_lock_release(&n->lock);
976
977 eina_lock_release(&_eina_file_lock_cache);
978
979 free(filename);
980
981 return n;
982
983 on_error:
984 free(filename);
985 if (fd >= 0) close(fd);
986 return NULL;
987}
988
989EAPI void
990eina_file_close(Eina_File *file)
991{
992 EINA_SAFETY_ON_NULL_RETURN(file);
993
994 eina_lock_take(&file->lock);
995 file->refcount--;
996 eina_lock_release(&file->lock);
997
998 if (file->refcount != 0) return;
999 eina_lock_take(&_eina_file_lock_cache);
1000
1001 eina_hash_del(_eina_file_cache, file->filename, file);
1002 _eina_file_real_close(file);
1003
1004 eina_lock_release(&_eina_file_lock_cache);
1005}
1006
1007EAPI size_t
1008eina_file_size_get(Eina_File *file)
1009{
1010 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1011 return file->length;
1012}
1013
1014EAPI time_t
1015eina_file_mtime_get(Eina_File *file)
1016{
1017 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1018 return file->mtime;
1019}
1020
1021EAPI const char *
1022eina_file_filename_get(Eina_File *file)
1023{
1024 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1025 return file->filename;
1026}
1027
1028EAPI void *
1029eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
1030{
1031 int flags = MAP_SHARED;
1032 void *ret = NULL;
1033
1034 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1035
1036// bsd people will lack this feature
1037#ifdef MAP_POPULATE
1038 if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
1039#endif
1040#ifdef MAP_HUGETLB
1041 if (file->length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB;
1042#endif
1043
1044 eina_mmap_safety_enabled_set(EINA_TRUE);
1045 eina_lock_take(&file->lock);
1046 if (file->global_map == MAP_FAILED)
1047 file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
1048#ifdef MAP_HUGETLB
1049 if ((file->global_map == MAP_FAILED) && (flags & MAP_HUGETLB))
1050 {
1051 flags &= ~MAP_HUGETLB;
1052 file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
1053 }
1054#endif
1055
1056 if (file->global_map != MAP_FAILED)
1057 {
1058 Eina_Bool hugetlb = EINA_FALSE;
1059
1060#ifdef MAP_HUGETLB
1061 hugetlb = !!(flags & MAP_HUGETLB);
1062#endif
1063 _eina_file_map_rule_apply(rule, file->global_map, file->length, hugetlb);
1064 file->global_refcount++;
1065 ret = file->global_map;
1066 }
1067
1068 eina_lock_release(&file->lock);
1069 return ret;
1070}
1071
1072EAPI void *
1073eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
1074 unsigned long int offset, unsigned long int length)
1075{
1076 Eina_File_Map *map;
1077 unsigned long int key[2];
1078
1079 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1080
1081 if (offset > file->length)
1082 return NULL;
1083 if (offset + length > file->length)
1084 return NULL;
1085
1086 if (offset == 0 && length == file->length)
1087 return eina_file_map_all(file, rule);
1088
1089 key[0] = offset;
1090 key[1] = length;
1091
1092 eina_mmap_safety_enabled_set(EINA_TRUE);
1093 eina_lock_take(&file->lock);
1094
1095 map = eina_hash_find(file->map, &key);
1096 if (!map)
1097 {
1098 int flags = MAP_SHARED;
1099
1100// bsd people will lack this feature
1101#ifdef MAP_POPULATE
1102 if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
1103#endif
1104#ifdef MAP_HUGETLB
1105 if (length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB;
1106#endif
1107
1108 map = malloc(sizeof (Eina_File_Map));
1109 if (!map) goto on_error;
1110
1111 map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset);
1112#ifdef MAP_HUGETLB
1113 if (map->map == MAP_FAILED && (flags & MAP_HUGETLB))
1114 {
1115 flags &= ~MAP_HUGETLB;
1116 map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset);
1117 }
1118
1119 map->hugetlb = !!(flags & MAP_HUGETLB);
1120#else
1121 map->hugetlb = EINA_FALSE;
1122#endif
1123 map->offset = offset;
1124 map->length = length;
1125 map->refcount = 0;
1126
1127 if (map->map == MAP_FAILED) goto on_error;
1128
1129 eina_hash_add(file->map, &key, map);
1130 eina_hash_direct_add(file->rmap, map->map, map);
1131 }
1132
1133 map->refcount++;
1134
1135 _eina_file_map_rule_apply(rule, map->map, length, map->hugetlb);
1136
1137 eina_lock_release(&file->lock);
1138
1139 return map->map;
1140
1141 on_error:
1142 free(map);
1143 eina_lock_release(&file->lock);
1144
1145 return NULL;
1146}
1147
1148EAPI void
1149eina_file_map_free(Eina_File *file, void *map)
1150{
1151 EINA_SAFETY_ON_NULL_RETURN(file);
1152
1153 eina_lock_take(&file->lock);
1154
1155 if (file->global_map == map)
1156 {
1157 file->global_refcount--;
1158
1159 if (file->global_refcount > 0) goto on_exit;
1160
1161 munmap(file->global_map, file->length);
1162 file->global_map = MAP_FAILED;
1163 }
1164 else
1165 {
1166 Eina_File_Map *em;
1167 unsigned long int key[2];
1168
1169 em = eina_hash_find(file->rmap, &map);
1170 if (!em) return ;
1171
1172 em->refcount--;
1173
1174 if (em->refcount > 0) goto on_exit;
1175
1176 key[0] = em->offset;
1177 key[1] = em->length;
1178
1179 eina_hash_del(file->rmap, &map, em);
1180 eina_hash_del(file->map, &key, em);
1181 }
1182
1183 on_exit:
1184 eina_lock_release(&file->lock);
1185}
1186
1187
diff --git a/libraries/eina/src/lib/eina_file_win32.c b/libraries/eina/src/lib/eina_file_win32.c
new file mode 100644
index 0000000..1cd8665
--- /dev/null
+++ b/libraries/eina/src/lib/eina_file_win32.c
@@ -0,0 +1,1021 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2010 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#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#define WIN32_LEAN_AND_MEAN
41#include <windows.h>
42#undef WIN32_LEAN_AND_MEAN
43
44//#include <Evil.h>
45
46#include "eina_config.h"
47#include "eina_private.h"
48
49/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
50#include "eina_safety_checks.h"
51#include "eina_file.h"
52#include "eina_stringshare.h"
53#include "eina_hash.h"
54#include "eina_list.h"
55
56/*============================================================================*
57 * Local *
58 *============================================================================*/
59
60/**
61 * @cond LOCAL
62 */
63
64#ifndef EINA_LOG_COLOR_DEFAULT
65#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
66#endif
67
68#ifdef ERR
69#undef ERR
70#endif
71#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
72
73#ifdef WRN
74#undef WRN
75#endif
76#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
77
78#ifdef DBG
79#undef DBG
80#endif
81#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
82
83#ifdef MAP_FAILED
84# undef MAP_FAILED
85#endif
86#define MAP_FAILED ((void *)-1)
87
88typedef struct _Eina_File_Iterator Eina_File_Iterator;
89typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
90typedef struct _Eina_File_Map Eina_File_Map;
91
92struct _Eina_File_Iterator
93{
94 Eina_Iterator iterator;
95
96 WIN32_FIND_DATA data;
97 HANDLE handle;
98 size_t length;
99 Eina_Bool is_last : 1;
100
101 char dir[1];
102};
103
104struct _Eina_File_Direct_Iterator
105{
106 Eina_Iterator iterator;
107
108 WIN32_FIND_DATA data;
109 HANDLE handle;
110 size_t length;
111 Eina_Bool is_last : 1;
112
113 Eina_File_Direct_Info info;
114
115 char dir[1];
116};
117
118struct _Eina_File
119{
120 const char *filename;
121
122 Eina_Hash *map;
123 Eina_Hash *rmap;
124 void *global_map;
125
126 ULONGLONG length;
127 ULONGLONG mtime;
128
129 int refcount;
130 int global_refcount;
131
132 HANDLE handle;
133 HANDLE fm;
134
135 Eina_Bool shared : 1;
136 Eina_Bool delete_me : 1;
137};
138
139struct _Eina_File_Map
140{
141 void *map;
142
143 unsigned long int offset;
144 unsigned long int length;
145
146 int refcount;
147};
148
149static Eina_Hash *_eina_file_cache = NULL;
150static Eina_List *_eina_file_cache_lru = NULL;
151static Eina_List *_eina_file_cache_delete = NULL;
152
153static int _eina_file_log_dom = -1;
154
155static void
156_eina_file_win32_backslash_change(char *dir)
157{
158 char *tmp;
159
160 tmp = dir;
161 while (*tmp)
162 {
163 if (*tmp == '/') *tmp = '\\';
164 tmp++;
165 }
166}
167
168static Eina_Bool
169_eina_file_win32_is_dir(const char *dir)
170{
171#ifdef UNICODE
172 wchar_t *wdir = NULL;
173#endif
174 DWORD attr;
175
176 /* check if it's a directory */
177#ifdef UNICODE
178 wdir = evil_char_to_wchar(dir);
179 if (!wdir)
180 return EINA_FALSE;
181
182 attr = GetFileAttributes(wdir);
183 free(wdir);
184#else
185 attr = GetFileAttributes(dir);
186#endif
187
188 if (attr == 0xFFFFFFFF)
189 return EINA_FALSE;
190
191 if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
192 return EINA_FALSE;
193
194 return EINA_TRUE;
195}
196
197static char *
198_eina_file_win32_dir_new(const char *dir)
199{
200 char *new_dir;
201 size_t length;
202
203 length = strlen(dir);
204
205 new_dir = (char *)malloc(sizeof(char) * length + 5);
206 if (!new_dir)
207 return NULL;
208
209 memcpy(new_dir, dir, length);
210 memcpy(new_dir + length, "\\*.*", 5);
211 _eina_file_win32_backslash_change(new_dir);
212
213 return new_dir;
214}
215
216static HANDLE
217_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd)
218{
219 HANDLE h;
220#ifdef UNICODE
221 wchar_t *wdir = NULL;
222
223 wdir = evil_char_to_wchar(dir);
224 if (!wdir)
225 return NULL;
226
227 h = FindFirstFile(wdir, fd);
228 free(wdir);
229#else
230 h = FindFirstFile(dir, fd);
231#endif
232
233 if (!h)
234 return NULL;
235
236 while ((fd->cFileName[0] == '.') &&
237 ((fd->cFileName[1] == '\0') ||
238 ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0'))))
239 {
240 if (!FindNextFile(h, fd))
241 return NULL;
242 }
243
244 return h;
245}
246
247static Eina_Bool
248_eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data)
249{
250#ifdef UNICODE
251 wchar_t *old_name;
252#else
253 char *old_name;
254#endif
255 char *name;
256 char *cname;
257 size_t length;
258 Eina_Bool is_last;
259 Eina_Bool res = EINA_TRUE;
260
261 if (it->handle == INVALID_HANDLE_VALUE)
262 return EINA_FALSE;
263
264 is_last = it->is_last;
265#ifdef UNICODE
266 old_name = _wcsdup(it->data.cFileName);
267#else
268 old_name = _strdup(it->data.cFileName);
269#endif
270 if (!old_name)
271 return EINA_FALSE;
272
273 do {
274 if (!FindNextFile(it->handle, &it->data))
275 {
276 if (GetLastError() == ERROR_NO_MORE_FILES)
277 it->is_last = EINA_TRUE;
278 else
279 res = EINA_FALSE;
280 }
281 } while ((it->data.cFileName[0] == '.') &&
282 ((it->data.cFileName[1] == '\0') ||
283 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */
284
285#ifdef UNICODE
286 cname = evil_wchar_to_char(old_name);
287 if (!cname)
288 return EINA_FALSE;
289#else
290 cname = old_name;
291#endif
292
293 length = strlen(cname);
294 name = alloca(length + 2 + it->length);
295
296 memcpy(name, it->dir, it->length);
297 memcpy(name + it->length, "\\", 1);
298 memcpy(name + it->length + 1, cname, length + 1);
299
300 *data = (char *)eina_stringshare_add(name);
301
302#ifdef UNICODE
303 free(cname);
304#endif
305 free(old_name);
306
307 if (is_last)
308 res = EINA_FALSE;
309
310 return res;
311}
312
313static HANDLE
314_eina_file_win32_ls_iterator_container(Eina_File_Iterator *it)
315{
316 return it->handle;
317}
318
319static void
320_eina_file_win32_ls_iterator_free(Eina_File_Iterator *it)
321{
322 if (it->handle != INVALID_HANDLE_VALUE)
323 FindClose(it->handle);
324
325 EINA_MAGIC_SET(&it->iterator, 0);
326 free(it);
327}
328
329static Eina_Bool
330_eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
331{
332#ifdef UNICODE
333 wchar_t *old_name;
334#else
335 char *old_name;
336#endif
337 char *cname;
338 size_t length;
339 DWORD attr;
340 Eina_Bool is_last;
341 Eina_Bool res = EINA_TRUE;
342
343 if (it->handle == INVALID_HANDLE_VALUE)
344 return EINA_FALSE;
345
346 attr = it->data.dwFileAttributes;
347 is_last = it->is_last;
348#ifdef UNICODE
349 old_name = _wcsdup(it->data.cFileName);
350#else
351 old_name = _strdup(it->data.cFileName);
352#endif
353 if (!old_name)
354 return EINA_FALSE;
355
356 do {
357 if (!FindNextFile(it->handle, &it->data))
358 {
359 if (GetLastError() == ERROR_NO_MORE_FILES)
360 it->is_last = EINA_TRUE;
361 else
362 res = EINA_FALSE;
363 }
364
365#ifdef UNICODE
366 length = wcslen(old_name);
367#else
368 length = strlen(old_name);
369#endif
370 if (it->info.name_start + length + 1 >= PATH_MAX)
371 {
372 free(old_name);
373#ifdef UNICODE
374 old_name = _wcsdup(it->data.cFileName);
375#else
376 old_name = _strdup(it->data.cFileName);
377#endif
378 continue;
379 }
380
381 } while ((it->data.cFileName[0] == '.') &&
382 ((it->data.cFileName[1] == '\0') ||
383 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */
384
385#ifdef UNICODE
386 cname = evil_wchar_to_char(old_name);
387 if (!cname)
388 return EINA_FALSE;
389#else
390 cname = old_name;
391#endif
392
393 memcpy(it->info.path + it->info.name_start, cname, length);
394 it->info.name_length = length;
395 it->info.path_length = it->info.name_start + length;
396 it->info.path[it->info.path_length] = '\0';
397
398 if (attr & FILE_ATTRIBUTE_DIRECTORY)
399 it->info.type = EINA_FILE_DIR;
400 else if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
401 it->info.type = EINA_FILE_LNK;
402 else if (attr & (FILE_ATTRIBUTE_ARCHIVE |
403 FILE_ATTRIBUTE_COMPRESSED |
404 FILE_ATTRIBUTE_COMPRESSED |
405 FILE_ATTRIBUTE_HIDDEN |
406 FILE_ATTRIBUTE_NORMAL |
407 FILE_ATTRIBUTE_SPARSE_FILE |
408 FILE_ATTRIBUTE_TEMPORARY))
409 it->info.type = EINA_FILE_REG;
410 else
411 it->info.type = EINA_FILE_UNKNOWN;
412
413 *data = &it->info;
414
415#ifdef UNICODE
416 free(cname);
417#endif
418
419 free(old_name);
420
421 if (is_last)
422 res = EINA_FALSE;
423
424 return res;
425}
426
427static HANDLE
428_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
429{
430 return it->handle;
431}
432
433static void
434_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
435{
436 if (it->handle != INVALID_HANDLE_VALUE)
437 FindClose(it->handle);
438
439 EINA_MAGIC_SET(&it->iterator, 0);
440 free(it);
441}
442
443static void
444_eina_file_real_close(Eina_File *file)
445{
446 eina_hash_free(file->rmap);
447 eina_hash_free(file->map);
448
449 if (file->global_map != MAP_FAILED)
450 UnmapViewOfFile(file->global_map);
451
452 CloseHandle(file->fm);
453 CloseHandle(file->handle);
454
455 eina_stringshare_del(file->filename);
456
457 free(file);
458}
459
460static void
461_eina_file_map_close(Eina_File_Map *map)
462{
463 if (map->map != MAP_FAILED)
464 UnmapViewOfFile(map->map);
465 free(map);
466}
467
468static unsigned int
469_eina_file_map_key_length(const void *key __UNUSED__)
470{
471 return sizeof (unsigned long int) * 2;
472}
473
474static int
475_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__,
476 const unsigned long int *key2, int key2_length __UNUSED__)
477{
478 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
479 return key1[0] - key2[0];
480}
481
482static int
483_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__)
484{
485 return eina_hash_int64(&key[0], sizeof (unsigned long int))
486 ^ eina_hash_int64(&key[1], sizeof (unsigned long int));
487}
488
489Eina_Bool
490eina_file_init(void)
491{
492 _eina_file_log_dom = eina_log_domain_register("eina_file",
493 EINA_LOG_COLOR_DEFAULT);
494 if (_eina_file_log_dom < 0)
495 {
496 EINA_LOG_ERR("Could not register log domain: eina_file");
497 return EINA_FALSE;
498 }
499
500 _eina_file_cache = eina_hash_string_djb2_new(EINA_FREE_CB(_eina_file_real_close));
501 if (!_eina_file_cache)
502 {
503 ERR("Could not create cache.");
504 eina_log_domain_unregister(_eina_file_log_dom);
505 _eina_file_log_dom = -1;
506 return EINA_FALSE;
507 }
508
509 return EINA_TRUE;
510}
511
512Eina_Bool
513eina_file_shutdown(void)
514{
515 Eina_File *f;
516 Eina_List *l;
517
518 EINA_LIST_FREE(_eina_file_cache_delete, f)
519 _eina_file_real_close(f);
520
521 EINA_LIST_FOREACH(_eina_file_cache_lru, l, f)
522 eina_hash_del(_eina_file_cache, f->filename, f);
523
524 if (eina_hash_population(_eina_file_cache) > 0)
525 {
526 Eina_Iterator *it;
527 const char *key;
528
529 it = eina_hash_iterator_key_new(_eina_file_cache);
530 EINA_ITERATOR_FOREACH(it, key)
531 ERR("File [%s] still open !", key);
532 eina_iterator_free(it);
533 }
534
535 eina_hash_free(_eina_file_cache);
536
537 eina_log_domain_unregister(_eina_file_log_dom);
538 _eina_file_log_dom = -1;
539 return EINA_TRUE;
540}
541
542
543/**
544 * @endcond
545 */
546
547/*============================================================================*
548 * Global *
549 *============================================================================*/
550
551/*============================================================================*
552 * API *
553 *============================================================================*/
554
555EAPI Eina_Bool
556eina_file_dir_list(const char *dir,
557 Eina_Bool recursive,
558 Eina_File_Dir_List_Cb cb,
559 void *data)
560{
561 WIN32_FIND_DATA file;
562 HANDLE h;
563 char *new_dir;
564
565 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
566 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
567 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
568
569 if (!_eina_file_win32_is_dir(dir))
570 return EINA_FALSE;
571
572 new_dir = _eina_file_win32_dir_new(dir);
573 if (!new_dir)
574 return EINA_FALSE;
575
576 h = _eina_file_win32_first_file(new_dir, &file);
577
578 if (h == INVALID_HANDLE_VALUE)
579 return EINA_FALSE;
580
581 do
582 {
583 char *filename;
584
585# ifdef UNICODE
586 filename = evil_wchar_to_char(file.cFileName);
587# else
588 filename = file.cFileName;
589# endif /* ! UNICODE */
590 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
591 continue;
592
593 cb(filename, dir, data);
594
595 if (recursive == EINA_TRUE)
596 {
597 char *path;
598
599 path = alloca(strlen(dir) + strlen(filename) + 2);
600 strcpy(path, dir);
601 strcat(path, "/");
602 strcat(path, filename);
603
604 if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
605 continue;
606
607 eina_file_dir_list(path, recursive, cb, data);
608 }
609
610# ifdef UNICODE
611 free(filename);
612# endif /* UNICODE */
613
614 } while (FindNextFile(h, &file));
615 FindClose(h);
616
617 return EINA_TRUE;
618}
619
620EAPI Eina_Array *
621eina_file_split(char *path)
622{
623 Eina_Array *ea;
624 char *current;
625 size_t length;
626
627 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
628
629 ea = eina_array_new(16);
630
631 if (!ea)
632 return NULL;
633
634 for (current = strchr(path, '\\');
635 current;
636 path = current + 1, current = strchr(path, '\\'))
637 {
638 length = current - path;
639
640 if (length <= 0)
641 continue;
642
643 eina_array_push(ea, path);
644 *current = '\0';
645 }
646
647 if (*path != '\0')
648 eina_array_push(ea, path);
649
650 return ea;
651}
652
653EAPI Eina_Iterator *
654eina_file_ls(const char *dir)
655{
656 Eina_File_Iterator *it;
657 char *new_dir;
658 size_t length;
659
660 if (!dir || !*dir)
661 return NULL;
662
663 if (!_eina_file_win32_is_dir(dir))
664 return NULL;
665
666 length = strlen(dir);
667
668 it = calloc(1, sizeof (Eina_File_Iterator) + length);
669 if (!it)
670 return NULL;
671
672 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
673
674 new_dir = _eina_file_win32_dir_new(dir);
675 if (!new_dir)
676 goto free_it;
677
678 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
679 free(new_dir);
680 if (it->handle == INVALID_HANDLE_VALUE)
681 goto free_it;
682
683 memcpy(it->dir, dir, length + 1);
684 if (dir[length - 1] != '\\')
685 it->length = length;
686 else
687 it->length = length - 1;
688 _eina_file_win32_backslash_change(it->dir);
689
690 it->iterator.version = EINA_ITERATOR_VERSION;
691 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next);
692 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container);
693 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free);
694
695 return &it->iterator;
696
697 free_it:
698 free(it);
699
700 return NULL;
701}
702
703EAPI Eina_Iterator *
704eina_file_direct_ls(const char *dir)
705{
706 Eina_File_Direct_Iterator *it;
707 char *new_dir;
708 size_t length;
709
710 if (!dir || !*dir)
711 return NULL;
712
713 length = strlen(dir);
714
715 if (length + 12 + 2 >= MAX_PATH)
716 return NULL;
717
718 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
719 if (!it)
720 return NULL;
721
722 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
723
724 new_dir = _eina_file_win32_dir_new(dir);
725 if (!new_dir)
726 goto free_it;
727
728 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
729 free(new_dir);
730 if (it->handle == INVALID_HANDLE_VALUE)
731 goto free_it;
732
733 memcpy(it->dir, dir, length + 1);
734 it->length = length;
735 _eina_file_win32_backslash_change(it->dir);
736
737 memcpy(it->info.path, dir, length);
738 if (dir[length - 1] == '\\')
739 it->info.name_start = length;
740 else
741 {
742 it->info.path[length] = '\\';
743 it->info.name_start = length + 1;
744 }
745 _eina_file_win32_backslash_change(it->info.path);
746
747 it->iterator.version = EINA_ITERATOR_VERSION;
748 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next);
749 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container);
750 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free);
751
752 return &it->iterator;
753
754 free_it:
755 free(it);
756
757 return NULL;
758}
759
760EAPI Eina_Iterator *
761eina_file_stat_ls(const char *dir)
762{
763 return eina_file_direct_ls(dir);
764}
765
766EAPI Eina_File *
767eina_file_open(const char *filename, Eina_Bool shared)
768{
769 Eina_File *file;
770 Eina_File *n;
771 HANDLE handle;
772 HANDLE fm;
773 WIN32_FILE_ATTRIBUTE_DATA fad;
774 ULARGE_INTEGER length;
775 ULARGE_INTEGER mtime;
776 Eina_Bool create = EINA_FALSE;
777
778 /* FIXME: always open absolute path (need to fix filename according to current
779 directory) */
780
781 /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */
782#if 0
783 if (shared)
784 handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
785 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY,
786 NULL);
787 else
788#endif
789 handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
790 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY,
791 NULL);
792
793 if (handle == INVALID_HANDLE_VALUE)
794 return NULL;
795
796 fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL);
797 if (!fm)
798 goto close_handle;
799
800 if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad))
801 goto close_fm;
802
803 length.u.LowPart = fad.nFileSizeLow;
804 length.u.HighPart = fad.nFileSizeHigh;
805 mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime;
806 mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime;
807
808 file = eina_hash_find(_eina_file_cache, filename);
809 if (file &&
810 (file->mtime != mtime.QuadPart || file->length != length.QuadPart))
811 {
812 create = EINA_TRUE;
813
814 if (file->refcount == 0)
815 {
816 _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file);
817 eina_hash_del(_eina_file_cache, file->filename, file);
818
819 file = NULL;
820 }
821 else if (!file->delete_me)
822 {
823 file->delete_me = EINA_TRUE;
824 _eina_file_cache_delete = eina_list_prepend(_eina_file_cache_delete, file);
825 }
826 }
827
828 if (!file || create)
829 {
830 n = calloc(1, sizeof (Eina_File));
831 if (!n)
832 goto close_fm;
833
834 n->filename = eina_stringshare_add(filename);
835 n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
836 EINA_KEY_CMP(_eina_file_map_key_cmp),
837 EINA_KEY_HASH(_eina_file_map_key_hash),
838 EINA_FREE_CB(_eina_file_map_close),
839 3);
840 n->rmap = eina_hash_pointer_new(NULL);
841 n->global_map = MAP_FAILED;
842 n->length = length.QuadPart;
843 n->mtime = mtime.QuadPart;
844 n->refcount = 0;
845 n->handle = handle;
846 n->fm = fm;
847 n->shared = shared;
848 n->delete_me = EINA_FALSE;
849
850 eina_hash_set(_eina_file_cache, filename, n);
851 }
852 else
853 {
854 CloseHandle(fm);
855 CloseHandle(handle);
856
857 n = file;
858
859 if (n->refcount == 0)
860 _eina_file_cache_lru = eina_list_remove(_eina_file_cache_lru, n);
861 }
862
863 n->refcount++;
864
865 return n;
866
867 close_fm:
868 CloseHandle(fm);
869 close_handle:
870 CloseHandle(handle);
871
872 return NULL;
873}
874
875EAPI void
876eina_file_close(Eina_File *file)
877{
878 file->refcount--;
879
880 if (file->refcount != 0) return ;
881
882 if (file->delete_me)
883 {
884 _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, file);
885 _eina_file_real_close(file);
886 }
887 else
888 {
889 _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file);
890 }
891}
892
893EAPI size_t
894eina_file_size_get(Eina_File *file)
895{
896 return file->length;
897}
898
899EAPI time_t
900eina_file_mtime_get(Eina_File *file)
901{
902 return file->mtime;
903}
904
905EAPI const char *
906eina_file_filename_get(Eina_File *file)
907{
908 return file->filename;
909}
910
911EAPI void *
912eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__)
913{
914 if (file->global_map == MAP_FAILED)
915 {
916 void *data;
917
918 data = MapViewOfFile(file->fm, FILE_MAP_READ,
919 0, 0, file->length);
920 if (!data)
921 file->global_map = MAP_FAILED;
922 else
923 file->global_map = data;
924 }
925
926 if (file->global_map != MAP_FAILED)
927 {
928 file->global_refcount++;
929 return file->global_map;
930 }
931
932 return NULL;
933}
934
935EAPI void *
936eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
937 unsigned long int offset, unsigned long int length)
938{
939 Eina_File_Map *map;
940 unsigned long int key[2];
941
942 if (offset > file->length)
943 return NULL;
944 if (offset + length > file->length)
945 return NULL;
946
947 if (offset == 0 && length == file->length)
948 return eina_file_map_all(file, rule);
949
950 key[0] = offset;
951 key[1] = length;
952
953 map = eina_hash_find(file->map, &key);
954 if (!map)
955 {
956 void *data;
957
958 map = malloc(sizeof (Eina_File_Map));
959 if (!map) return NULL;
960
961 data = MapViewOfFile(file->fm, FILE_MAP_READ,
962 offset & 0xffff0000,
963 offset & 0x0000ffff,
964 length);
965 if (!data)
966 map->map = MAP_FAILED;
967 else
968 map->map = data;
969
970 map->offset = offset;
971 map->length = length;
972 map->refcount = 0;
973
974 if (map->map == MAP_FAILED)
975 {
976 free(map);
977 return NULL;
978 }
979
980 eina_hash_add(file->map, &key, map);
981 eina_hash_direct_add(file->rmap, map->map, map);
982 }
983
984 map->refcount++;
985
986 return map->map;
987}
988
989EAPI void
990eina_file_map_free(Eina_File *file, void *map)
991{
992 if (file->global_map == map)
993 {
994 file->global_refcount--;
995
996 if (file->global_refcount > 0) return ;
997
998 /* FIXME: are we sure that file->global_map != MAP_FAILED ? */
999 if (file->global_map != MAP_FAILED)
1000 UnmapViewOfFile(file->global_map);
1001 file->global_map = MAP_FAILED;
1002 }
1003 else
1004 {
1005 Eina_File_Map *em;
1006 unsigned long int key[2];
1007
1008 em = eina_hash_find(file->rmap, &map);
1009 if (!em) return ;
1010
1011 em->refcount--;
1012
1013 if (em->refcount > 0) return ;
1014
1015 key[0] = em->offset;
1016 key[1] = em->length;
1017
1018 eina_hash_del(file->rmap, &map, em);
1019 eina_hash_del(file->map, &key, em);
1020 }
1021}
diff --git a/libraries/eina/src/lib/eina_fp.c b/libraries/eina/src/lib/eina_fp.c
new file mode 100644
index 0000000..8984b49
--- /dev/null
+++ b/libraries/eina/src/lib/eina_fp.c
@@ -0,0 +1,532 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdio.h>
6#include <math.h>
7
8#include "eina_types.h"
9#include "eina_fp.h"
10
11#define MAX_PREC 1025
12static const Eina_F32p32 eina_trigo[MAX_PREC] =
13{
14 0x0000000100000000, 0x00000000ffffec43, 0x00000000ffffb10b,
15 0x00000000ffff4e5a, 0x00000000fffec42e, 0x00000000fffe1287,
16 0x00000000fffd3967, 0x00000000fffc38cd, 0x00000000fffb10b9,
17 0x00000000fff9c12c,
18 0x00000000fff84a25, 0x00000000fff6aba5, 0x00000000fff4e5ac,
19 0x00000000fff2f83b, 0x00000000fff0e351, 0x00000000ffeea6ef,
20 0x00000000ffec4316, 0x00000000ffe9b7c5, 0x00000000ffe704fe,
21 0x00000000ffe42ac0,
22 0x00000000ffe1290b, 0x00000000ffddffe2, 0x00000000ffdaaf43,
23 0x00000000ffd7372f, 0x00000000ffd397a8, 0x00000000ffcfd0ad,
24 0x00000000ffcbe23f, 0x00000000ffc7cc5f, 0x00000000ffc38f0d,
25 0x00000000ffbf2a4b,
26 0x00000000ffba9e17, 0x00000000ffb5ea75, 0x00000000ffb10f63,
27 0x00000000ffac0ce3, 0x00000000ffa6e2f6, 0x00000000ffa1919c,
28 0x00000000ff9c18d6, 0x00000000ff9678a6, 0x00000000ff90b10b,
29 0x00000000ff8ac208,
30 0x00000000ff84ab9c, 0x00000000ff7e6dc8, 0x00000000ff78088f,
31 0x00000000ff717bf0, 0x00000000ff6ac7ec, 0x00000000ff63ec85,
32 0x00000000ff5ce9bc, 0x00000000ff55bf92, 0x00000000ff4e6e08,
33 0x00000000ff46f51f,
34 0x00000000ff3f54d8, 0x00000000ff378d34, 0x00000000ff2f9e35,
35 0x00000000ff2787dc, 0x00000000ff1f4a2a, 0x00000000ff16e520,
36 0x00000000ff0e58c0, 0x00000000ff05a50a, 0x00000000fefcca01,
37 0x00000000fef3c7a6,
38 0x00000000feea9df9, 0x00000000fee14cfe, 0x00000000fed7d4b3,
39 0x00000000fece351d, 0x00000000fec46e3b, 0x00000000feba800f,
40 0x00000000feb06a9c, 0x00000000fea62de1, 0x00000000fe9bc9e2,
41 0x00000000fe913e9f,
42 0x00000000fe868c1b, 0x00000000fe7bb256, 0x00000000fe70b153,
43 0x00000000fe658913, 0x00000000fe5a3998, 0x00000000fe4ec2e4,
44 0x00000000fe4324f9, 0x00000000fe375fd7, 0x00000000fe2b7382,
45 0x00000000fe1f5ffa,
46 0x00000000fe132543, 0x00000000fe06c35d, 0x00000000fdfa3a4b,
47 0x00000000fded8a0e, 0x00000000fde0b2a8, 0x00000000fdd3b41c,
48 0x00000000fdc68e6c, 0x00000000fdb94199, 0x00000000fdabcda5,
49 0x00000000fd9e3294,
50 0x00000000fd907065, 0x00000000fd82871d, 0x00000000fd7476bd,
51 0x00000000fd663f46, 0x00000000fd57e0bd, 0x00000000fd495b21,
52 0x00000000fd3aae77, 0x00000000fd2bdabf, 0x00000000fd1cdffd,
53 0x00000000fd0dbe32,
54 0x00000000fcfe7562, 0x00000000fcef058e, 0x00000000fcdf6eb8,
55 0x00000000fccfb0e4, 0x00000000fcbfcc13, 0x00000000fcafc048,
56 0x00000000fc9f8d86, 0x00000000fc8f33ce, 0x00000000fc7eb325,
57 0x00000000fc6e0b8b,
58 0x00000000fc5d3d03, 0x00000000fc4c4791, 0x00000000fc3b2b37,
59 0x00000000fc29e7f7, 0x00000000fc187dd5, 0x00000000fc06ecd2,
60 0x00000000fbf534f2, 0x00000000fbe35637, 0x00000000fbd150a3,
61 0x00000000fbbf243b,
62 0x00000000fbacd100, 0x00000000fb9a56f6, 0x00000000fb87b61f,
63 0x00000000fb74ee7e, 0x00000000fb620016, 0x00000000fb4eeaea,
64 0x00000000fb3baefd, 0x00000000fb284c52, 0x00000000fb14c2eb,
65 0x00000000fb0112cd,
66 0x00000000faed3bf9, 0x00000000fad93e73, 0x00000000fac51a3f,
67 0x00000000fab0cf5e, 0x00000000fa9c5dd5, 0x00000000fa87c5a6,
68 0x00000000fa7306d5, 0x00000000fa5e2164, 0x00000000fa491558,
69 0x00000000fa33e2b3,
70 0x00000000fa1e8978, 0x00000000fa0909ab, 0x00000000f9f36350,
71 0x00000000f9dd9668, 0x00000000f9c7a2f9, 0x00000000f9b18905,
72 0x00000000f99b488f, 0x00000000f984e19c, 0x00000000f96e542e,
73 0x00000000f957a049,
74 0x00000000f940c5f1, 0x00000000f929c528, 0x00000000f9129df3,
75 0x00000000f8fb5056, 0x00000000f8e3dc53, 0x00000000f8cc41ee,
76 0x00000000f8b4812b, 0x00000000f89c9a0e, 0x00000000f8848c9b,
77 0x00000000f86c58d4,
78 0x00000000f853febe, 0x00000000f83b7e5d, 0x00000000f822d7b4,
79 0x00000000f80a0ac7, 0x00000000f7f1179a, 0x00000000f7d7fe31,
80 0x00000000f7bebe90, 0x00000000f7a558ba, 0x00000000f78bccb3,
81 0x00000000f7721a80,
82 0x00000000f7584225, 0x00000000f73e43a5, 0x00000000f7241f04,
83 0x00000000f709d446, 0x00000000f6ef6370, 0x00000000f6d4cc85,
84 0x00000000f6ba0f8a, 0x00000000f69f2c83, 0x00000000f6842374,
85 0x00000000f668f461,
86 0x00000000f64d9f4e, 0x00000000f632243f, 0x00000000f616833a,
87 0x00000000f5fabc41, 0x00000000f5decf59, 0x00000000f5c2bc87,
88 0x00000000f5a683cf, 0x00000000f58a2535, 0x00000000f56da0be,
89 0x00000000f550f66e,
90 0x00000000f5342649, 0x00000000f5173054, 0x00000000f4fa1494,
91 0x00000000f4dcd30c, 0x00000000f4bf6bc2, 0x00000000f4a1deb9,
92 0x00000000f4842bf7, 0x00000000f4665380, 0x00000000f4485559,
93 0x00000000f42a3186,
94 0x00000000f40be80c, 0x00000000f3ed78ef, 0x00000000f3cee434,
95 0x00000000f3b029e1, 0x00000000f39149f9, 0x00000000f3724482,
96 0x00000000f3531980, 0x00000000f333c8f8, 0x00000000f31452ef,
97 0x00000000f2f4b76a,
98 0x00000000f2d4f66d, 0x00000000f2b50ffe, 0x00000000f2950421,
99 0x00000000f274d2dc, 0x00000000f2547c33, 0x00000000f234002b,
100 0x00000000f2135eca, 0x00000000f1f29814, 0x00000000f1d1ac0e,
101 0x00000000f1b09abe,
102 0x00000000f18f6429, 0x00000000f16e0853, 0x00000000f14c8742,
103 0x00000000f12ae0fb, 0x00000000f1091583, 0x00000000f0e724e0,
104 0x00000000f0c50f17, 0x00000000f0a2d42c, 0x00000000f0807426,
105 0x00000000f05def09,
106 0x00000000f03b44db, 0x00000000f01875a1, 0x00000000eff58161,
107 0x00000000efd2681f, 0x00000000efaf29e2, 0x00000000ef8bc6af,
108 0x00000000ef683e8b, 0x00000000ef44917b, 0x00000000ef20bf86,
109 0x00000000eefcc8b1,
110 0x00000000eed8ad01, 0x00000000eeb46c7b, 0x00000000ee900727,
111 0x00000000ee6b7d08, 0x00000000ee46ce25, 0x00000000ee21fa83,
112 0x00000000edfd0228, 0x00000000edd7e51a, 0x00000000edb2a35f,
113 0x00000000ed8d3cfc,
114 0x00000000ed67b1f6, 0x00000000ed420255, 0x00000000ed1c2e1d,
115 0x00000000ecf63554, 0x00000000ecd01801, 0x00000000eca9d628,
116 0x00000000ec836fd1, 0x00000000ec5ce501, 0x00000000ec3635bd,
117 0x00000000ec0f620d,
118 0x00000000ebe869f5, 0x00000000ebc14d7d, 0x00000000eb9a0ca9,
119 0x00000000eb72a780, 0x00000000eb4b1e08, 0x00000000eb237047,
120 0x00000000eafb9e43, 0x00000000ead3a803, 0x00000000eaab8d8d,
121 0x00000000ea834ee6,
122 0x00000000ea5aec15, 0x00000000ea326520, 0x00000000ea09ba0d,
123 0x00000000e9e0eae4, 0x00000000e9b7f7a9, 0x00000000e98ee063,
124 0x00000000e965a51a, 0x00000000e93c45d2, 0x00000000e912c292,
125 0x00000000e8e91b61,
126 0x00000000e8bf5046, 0x00000000e8956146, 0x00000000e86b4e68,
127 0x00000000e84117b3, 0x00000000e816bd2d, 0x00000000e7ec3edc,
128 0x00000000e7c19cc8, 0x00000000e796d6f6, 0x00000000e76bed6e,
129 0x00000000e740e036,
130 0x00000000e715af54, 0x00000000e6ea5ad0, 0x00000000e6bee2af,
131 0x00000000e69346f9, 0x00000000e66787b5, 0x00000000e63ba4e9,
132 0x00000000e60f9e9b, 0x00000000e5e374d4, 0x00000000e5b72798,
133 0x00000000e58ab6f1,
134 0x00000000e55e22e3, 0x00000000e5316b76, 0x00000000e50490b1,
135 0x00000000e4d7929c, 0x00000000e4aa713c, 0x00000000e47d2c98,
136 0x00000000e44fc4b9, 0x00000000e42239a4, 0x00000000e3f48b61,
137 0x00000000e3c6b9f7,
138 0x00000000e398c56c, 0x00000000e36aadc9, 0x00000000e33c7314,
139 0x00000000e30e1554, 0x00000000e2df9490, 0x00000000e2b0f0d0,
140 0x00000000e2822a1a, 0x00000000e2534077, 0x00000000e22433ec,
141 0x00000000e1f50482,
142 0x00000000e1c5b240, 0x00000000e1963d2d, 0x00000000e166a550,
143 0x00000000e136eab0, 0x00000000e1070d56, 0x00000000e0d70d48,
144 0x00000000e0a6ea8e, 0x00000000e076a52f, 0x00000000e0463d33,
145 0x00000000e015b2a1,
146 0x00000000dfe50580, 0x00000000dfb435d9, 0x00000000df8343b2,
147 0x00000000df522f13, 0x00000000df20f804, 0x00000000deef9e8d,
148 0x00000000debe22b5, 0x00000000de8c8483, 0x00000000de5ac3ff,
149 0x00000000de28e131,
150 0x00000000ddf6dc21, 0x00000000ddc4b4d6, 0x00000000dd926b59,
151 0x00000000dd5fffb0, 0x00000000dd2d71e3, 0x00000000dcfac1fb,
152 0x00000000dcc7f000, 0x00000000dc94fbf8, 0x00000000dc61e5ec,
153 0x00000000dc2eade4,
154 0x00000000dbfb53e8, 0x00000000dbc7d7ff, 0x00000000db943a31,
155 0x00000000db607a88, 0x00000000db2c9909, 0x00000000daf895bf,
156 0x00000000dac470af, 0x00000000da9029e3, 0x00000000da5bc163,
157 0x00000000da273737,
158 0x00000000d9f28b66, 0x00000000d9bdbdf9, 0x00000000d988cef8,
159 0x00000000d953be6b, 0x00000000d91e8c5b, 0x00000000d8e938d0,
160 0x00000000d8b3c3d1, 0x00000000d87e2d67, 0x00000000d848759b,
161 0x00000000d8129c74,
162 0x00000000d7dca1fb, 0x00000000d7a68638, 0x00000000d7704934,
163 0x00000000d739eaf7, 0x00000000d7036b89, 0x00000000d6cccaf3,
164 0x00000000d696093d, 0x00000000d65f266f, 0x00000000d6282293,
165 0x00000000d5f0fdb0,
166 0x00000000d5b9b7d0, 0x00000000d58250fa, 0x00000000d54ac937,
167 0x00000000d513208f, 0x00000000d4db570c, 0x00000000d4a36cb6,
168 0x00000000d46b6195, 0x00000000d43335b3, 0x00000000d3fae917,
169 0x00000000d3c27bcb,
170 0x00000000d389edd7, 0x00000000d3513f43, 0x00000000d318701a,
171 0x00000000d2df8063, 0x00000000d2a67027, 0x00000000d26d3f6f,
172 0x00000000d233ee43, 0x00000000d1fa7cae, 0x00000000d1c0eab7,
173 0x00000000d1873867,
174 0x00000000d14d65c8, 0x00000000d11372e1, 0x00000000d0d95fbd,
175 0x00000000d09f2c64, 0x00000000d064d8df, 0x00000000d02a6537,
176 0x00000000cfefd176, 0x00000000cfb51da3, 0x00000000cf7a49c8,
177 0x00000000cf3f55ef,
178 0x00000000cf044220, 0x00000000cec90e64, 0x00000000ce8dbac5,
179 0x00000000ce52474c, 0x00000000ce16b401, 0x00000000cddb00ef,
180 0x00000000cd9f2e1e, 0x00000000cd633b97, 0x00000000cd272964,
181 0x00000000cceaf78e,
182 0x00000000ccaea61e, 0x00000000cc72351e, 0x00000000cc35a497,
183 0x00000000cbf8f492, 0x00000000cbbc2519, 0x00000000cb7f3634,
184 0x00000000cb4227ee, 0x00000000cb04fa50, 0x00000000cac7ad63,
185 0x00000000ca8a4131,
186 0x00000000ca4cb5c3, 0x00000000ca0f0b22, 0x00000000c9d14159,
187 0x00000000c9935870, 0x00000000c9555072, 0x00000000c9172967,
188 0x00000000c8d8e35a, 0x00000000c89a7e53, 0x00000000c85bfa5e,
189 0x00000000c81d5782,
190 0x00000000c7de95cb, 0x00000000c79fb541, 0x00000000c760b5ee,
191 0x00000000c72197dc, 0x00000000c6e25b15, 0x00000000c6a2ffa3,
192 0x00000000c663858f, 0x00000000c623ece2, 0x00000000c5e435a8,
193 0x00000000c5a45fe9,
194 0x00000000c5646bb0, 0x00000000c5245906, 0x00000000c4e427f6,
195 0x00000000c4a3d888, 0x00000000c4636ac8, 0x00000000c422debf,
196 0x00000000c3e23476, 0x00000000c3a16bf9, 0x00000000c3608550,
197 0x00000000c31f8087,
198 0x00000000c2de5da6, 0x00000000c29d1cb8, 0x00000000c25bbdc8,
199 0x00000000c21a40de, 0x00000000c1d8a606, 0x00000000c196ed49,
200 0x00000000c15516b2, 0x00000000c113224a, 0x00000000c0d1101d,
201 0x00000000c08ee033,
202 0x00000000c04c9297, 0x00000000c00a2754, 0x00000000bfc79e73,
203 0x00000000bf84f800, 0x00000000bf423404, 0x00000000beff5289,
204 0x00000000bebc539a, 0x00000000be793741, 0x00000000be35fd89,
205 0x00000000bdf2a67b,
206 0x00000000bdaf3223, 0x00000000bd6ba08b, 0x00000000bd27f1bc,
207 0x00000000bce425c2, 0x00000000bca03ca7, 0x00000000bc5c3676,
208 0x00000000bc181338, 0x00000000bbd3d2f9, 0x00000000bb8f75c3,
209 0x00000000bb4afba1,
210 0x00000000bb06649c, 0x00000000bac1b0c0, 0x00000000ba7ce018,
211 0x00000000ba37f2ad, 0x00000000b9f2e88b, 0x00000000b9adc1bc,
212 0x00000000b9687e4a, 0x00000000b9231e41, 0x00000000b8dda1ac,
213 0x00000000b8980894,
214 0x00000000b8525305, 0x00000000b80c8109, 0x00000000b7c692ac,
215 0x00000000b78087f7, 0x00000000b73a60f6, 0x00000000b6f41db4,
216 0x00000000b6adbe3a, 0x00000000b6674296, 0x00000000b620aad0,
217 0x00000000b5d9f6f4,
218 0x00000000b593270e, 0x00000000b54c3b27, 0x00000000b505334a,
219 0x00000000b4be0f84, 0x00000000b476cfde, 0x00000000b42f7464,
220 0x00000000b3e7fd20, 0x00000000b3a06a1e, 0x00000000b358bb69,
221 0x00000000b310f10c,
222 0x00000000b2c90b11, 0x00000000b2810985, 0x00000000b238ec71,
223 0x00000000b1f0b3e2, 0x00000000b1a85fe2, 0x00000000b15ff07c,
224 0x00000000b11765bc, 0x00000000b0cebfad, 0x00000000b085fe5a,
225 0x00000000b03d21ce,
226 0x00000000aff42a15, 0x00000000afab1739, 0x00000000af61e946,
227 0x00000000af18a048, 0x00000000aecf3c49, 0x00000000ae85bd55,
228 0x00000000ae3c2377, 0x00000000adf26ebb, 0x00000000ada89f2c,
229 0x00000000ad5eb4d5,
230 0x00000000ad14afc2, 0x00000000acca8ffd, 0x00000000ac805594,
231 0x00000000ac360090, 0x00000000abeb90fe, 0x00000000aba106e9,
232 0x00000000ab56625d, 0x00000000ab0ba364, 0x00000000aac0ca0b,
233 0x00000000aa75d65d,
234 0x00000000aa2ac865, 0x00000000a9dfa030, 0x00000000a9945dc9,
235 0x00000000a949013a, 0x00000000a8fd8a91, 0x00000000a8b1f9d8,
236 0x00000000a8664f1c, 0x00000000a81a8a68, 0x00000000a7ceabc7,
237 0x00000000a782b345,
238 0x00000000a736a0ef, 0x00000000a6ea74cf, 0x00000000a69e2ef2,
239 0x00000000a651cf63, 0x00000000a605562f, 0x00000000a5b8c360,
240 0x00000000a56c1702, 0x00000000a51f5123, 0x00000000a4d271cc,
241 0x00000000a485790b,
242 0x00000000a43866eb, 0x00000000a3eb3b77, 0x00000000a39df6bd,
243 0x00000000a35098c7, 0x00000000a30321a2, 0x00000000a2b5915a,
244 0x00000000a267e7fa, 0x00000000a21a258e, 0x00000000a1cc4a24,
245 0x00000000a17e55c5,
246 0x00000000a1304880, 0x00000000a0e2225f, 0x00000000a093e36f,
247 0x00000000a0458bbb, 0x000000009ff71b50, 0x000000009fa8923a,
248 0x000000009f59f086, 0x000000009f0b363e, 0x000000009ebc6370,
249 0x000000009e6d7827,
250 0x000000009e1e746f, 0x000000009dcf5856, 0x000000009d8023e6,
251 0x000000009d30d72d, 0x000000009ce17236, 0x000000009c91f50e,
252 0x000000009c425fc1, 0x000000009bf2b25b, 0x000000009ba2ece8,
253 0x000000009b530f76,
254 0x000000009b031a0f, 0x000000009ab30cc1, 0x000000009a62e797,
255 0x000000009a12aa9f, 0x0000000099c255e5, 0x000000009971e974,
256 0x000000009921655a, 0x0000000098d0c9a2, 0x0000000098801659,
257 0x00000000982f4b8d,
258 0x0000000097de6948, 0x00000000978d6f97, 0x00000000973c5e88,
259 0x0000000096eb3626, 0x000000009699f67f, 0x0000000096489f9e,
260 0x0000000095f73190, 0x0000000095a5ac61, 0x000000009554101f,
261 0x0000000095025cd6,
262 0x0000000094b09292, 0x00000000945eb161, 0x00000000940cb94e,
263 0x0000000093baaa66, 0x00000000936884b6, 0x000000009316484b,
264 0x0000000092c3f531, 0x0000000092718b75, 0x00000000921f0b24,
265 0x0000000091cc744b,
266 0x000000009179c6f5, 0x0000000091270331, 0x0000000090d4290a,
267 0x000000009081388e, 0x00000000902e31c8, 0x000000008fdb14c7,
268 0x000000008f87e197, 0x000000008f349845, 0x000000008ee138dd,
269 0x000000008e8dc36c,
270 0x000000008e3a3800, 0x000000008de696a5, 0x000000008d92df68,
271 0x000000008d3f1256, 0x000000008ceb2f7c, 0x000000008c9736e7,
272 0x000000008c4328a3, 0x000000008bef04bf, 0x000000008b9acb46,
273 0x000000008b467c45,
274 0x000000008af217cb, 0x000000008a9d9de3, 0x000000008a490e9b,
275 0x0000000089f469ff, 0x00000000899fb01e, 0x00000000894ae103,
276 0x0000000088f5fcbc, 0x0000000088a10357, 0x00000000884bf4df,
277 0x0000000087f6d163,
278 0x0000000087a198f0, 0x00000000874c4b92, 0x0000000086f6e956,
279 0x0000000086a1724b, 0x00000000864be67c, 0x0000000085f645f8,
280 0x0000000085a090cc, 0x00000000854ac704, 0x0000000084f4e8ad,
281 0x00000000849ef5d7,
282 0x000000008448ee8c, 0x0000000083f2d2db, 0x00000000839ca2d1,
283 0x0000000083465e7c, 0x0000000082f005e8, 0x0000000082999922,
284 0x0000000082431839, 0x0000000081ec833a, 0x000000008195da31,
285 0x00000000813f1d2d,
286 0x0000000080e84c3a, 0x0000000080916766, 0x00000000803a6ebf,
287 0x000000007fe36251, 0x000000007f8c422b, 0x000000007f350e59,
288 0x000000007eddc6ea, 0x000000007e866bea, 0x000000007e2efd67,
289 0x000000007dd77b6f,
290 0x000000007d7fe60f, 0x000000007d283d54, 0x000000007cd0814c,
291 0x000000007c78b205, 0x000000007c20cf8c, 0x000000007bc8d9ef,
292 0x000000007b70d13b, 0x000000007b18b57e, 0x000000007ac086c5,
293 0x000000007a68451f,
294 0x000000007a0ff098, 0x0000000079b7893e, 0x00000000795f0f1f,
295 0x0000000079068248, 0x0000000078ade2c8, 0x00000000785530ab,
296 0x0000000077fc6c01, 0x0000000077a394d5, 0x00000000774aab36,
297 0x0000000076f1af32,
298 0x000000007698a0d6, 0x00000000763f8030, 0x0000000075e64d4e,
299 0x00000000758d083e, 0x000000007533b10d, 0x0000000074da47c9,
300 0x000000007480cc80, 0x0000000074273f3f, 0x0000000073cda016,
301 0x000000007373ef10,
302 0x00000000731a2c3d, 0x0000000072c057aa, 0x0000000072667164,
303 0x00000000720c797a, 0x0000000071b26ffa, 0x00000000715854f2,
304 0x0000000070fe286e, 0x0000000070a3ea7e, 0x0000000070499b30,
305 0x000000006fef3a90,
306 0x000000006f94c8ae, 0x000000006f3a4596, 0x000000006edfb157,
307 0x000000006e850c00, 0x000000006e2a559d, 0x000000006dcf8e3d,
308 0x000000006d74b5ee, 0x000000006d19ccbe, 0x000000006cbed2bb,
309 0x000000006c63c7f3,
310 0x000000006c08ac74, 0x000000006bad804c, 0x000000006b524389,
311 0x000000006af6f639, 0x000000006a9b986b, 0x000000006a402a2c,
312 0x0000000069e4ab8a, 0x0000000069891c94, 0x00000000692d7d57,
313 0x0000000068d1cde3,
314 0x0000000068760e44, 0x00000000681a3e89, 0x0000000067be5ec1,
315 0x0000000067626ef9, 0x0000000067066f40, 0x0000000066aa5fa3,
316 0x00000000664e4032, 0x0000000065f210f9, 0x000000006595d209,
317 0x000000006539836d,
318 0x0000000064dd2536, 0x000000006480b770, 0x0000000064243a2b,
319 0x0000000063c7ad75, 0x00000000636b115c, 0x00000000630e65ed,
320 0x0000000062b1ab39, 0x000000006254e14c, 0x0000000061f80835,
321 0x00000000619b2002,
322 0x00000000613e28c2, 0x0000000060e12283, 0x0000000060840d54,
323 0x000000006026e943, 0x000000005fc9b65d, 0x000000005f6c74b2,
324 0x000000005f0f2450, 0x000000005eb1c545, 0x000000005e5457a0,
325 0x000000005df6db6f,
326 0x000000005d9950c0, 0x000000005d3bb7a3, 0x000000005cde1024,
327 0x000000005c805a54, 0x000000005c22963f, 0x000000005bc4c3f6,
328 0x000000005b66e385, 0x000000005b08f4fd, 0x000000005aaaf86a,
329 0x000000005a4ceddc,
330 0x0000000059eed561, 0x000000005990af08, 0x0000000059327adf,
331 0x0000000058d438f4, 0x000000005875e957, 0x0000000058178c16,
332 0x0000000057b9213f, 0x00000000575aa8e0, 0x0000000056fc230a,
333 0x00000000569d8fc9,
334 0x00000000563eef2d, 0x0000000055e04144, 0x000000005581861d,
335 0x000000005522bdc6, 0x0000000054c3e84e, 0x00000000546505c4,
336 0x0000000054061636, 0x0000000053a719b3, 0x000000005348104a,
337 0x0000000052e8fa09,
338 0x000000005289d6ff, 0x00000000522aa73a, 0x0000000051cb6aca,
339 0x00000000516c21bc, 0x00000000510ccc20, 0x0000000050ad6a05,
340 0x00000000504dfb78, 0x000000004fee808a, 0x000000004f8ef947,
341 0x000000004f2f65c0,
342 0x000000004ecfc603, 0x000000004e701a1f, 0x000000004e106222,
343 0x000000004db09e1b, 0x000000004d50ce19, 0x000000004cf0f22b,
344 0x000000004c910a5f, 0x000000004c3116c5, 0x000000004bd1176b,
345 0x000000004b710c5f,
346 0x000000004b10f5b2, 0x000000004ab0d371, 0x000000004a50a5ab,
347 0x0000000049f06c70, 0x00000000499027cd, 0x00000000492fd7d3,
348 0x0000000048cf7c8f, 0x00000000486f1611, 0x00000000480ea467,
349 0x0000000047ae27a1,
350 0x00000000474d9fcd, 0x0000000046ed0cfa, 0x00000000468c6f37,
351 0x00000000462bc693, 0x0000000045cb131c, 0x00000000456a54e3,
352 0x0000000045098bf5, 0x0000000044a8b861, 0x000000004447da37,
353 0x0000000043e6f186,
354 0x000000004385fe5c, 0x00000000432500c8, 0x0000000042c3f8d9,
355 0x000000004262e69f, 0x000000004201ca28, 0x0000000041a0a383,
356 0x00000000413f72bf, 0x0000000040de37eb, 0x00000000407cf317,
357 0x00000000401ba450,
358 0x000000003fba4ba7, 0x000000003f58e92a, 0x000000003ef77ce8,
359 0x000000003e9606f1, 0x000000003e348752, 0x000000003dd2fe1c,
360 0x000000003d716b5e, 0x000000003d0fcf25, 0x000000003cae2982,
361 0x000000003c4c7a83,
362 0x000000003beac238, 0x000000003b8900b0, 0x000000003b2735f9,
363 0x000000003ac56223, 0x000000003a63853d, 0x000000003a019f56,
364 0x00000000399fb07d, 0x00000000393db8c1, 0x0000000038dbb831,
365 0x000000003879aedd,
366 0x0000000038179cd3, 0x0000000037b58222, 0x0000000037535edb,
367 0x0000000036f1330b, 0x00000000368efec2, 0x00000000362cc20f,
368 0x0000000035ca7d02, 0x0000000035682fa9, 0x000000003505da14,
369 0x0000000034a37c51,
370 0x0000000034411671, 0x0000000033dea881, 0x00000000337c3292,
371 0x000000003319b4b3, 0x0000000032b72ef2, 0x000000003254a15e,
372 0x0000000031f20c08, 0x00000000318f6efe, 0x00000000312cca50,
373 0x0000000030ca1e0c,
374 0x0000000030676a43, 0x000000003004af02, 0x000000002fa1ec5a,
375 0x000000002f3f2259, 0x000000002edc510f, 0x000000002e79788b,
376 0x000000002e1698dc, 0x000000002db3b212, 0x000000002d50c43c,
377 0x000000002cedcf68,
378 0x000000002c8ad3a7, 0x000000002c27d108, 0x000000002bc4c799,
379 0x000000002b61b76b, 0x000000002afea08c, 0x000000002a9b830b,
380 0x000000002a385ef9, 0x0000000029d53464, 0x000000002972035b,
381 0x00000000290ecbee,
382 0x0000000028ab8e2c, 0x0000000028484a25, 0x0000000027e4ffe7,
383 0x000000002781af83, 0x00000000271e5906, 0x0000000026bafc82,
384 0x0000000026579a04, 0x0000000025f4319d, 0x000000002590c35c,
385 0x00000000252d4f4f,
386 0x0000000024c9d587, 0x0000000024665613, 0x000000002402d101,
387 0x00000000239f4662, 0x00000000233bb644, 0x0000000022d820b8,
388 0x00000000227485cc, 0x000000002210e590, 0x0000000021ad4013,
389 0x0000000021499565,
390 0x0000000020e5e594, 0x00000000208230b1, 0x00000000201e76ca,
391 0x000000001fbab7ef, 0x000000001f56f430, 0x000000001ef32b9b,
392 0x000000001e8f5e41, 0x000000001e2b8c30, 0x000000001dc7b578,
393 0x000000001d63da29,
394 0x000000001cfffa51, 0x000000001c9c1600, 0x000000001c382d46,
395 0x000000001bd44032, 0x000000001b704ed3, 0x000000001b0c5939,
396 0x000000001aa85f74, 0x000000001a446191, 0x0000000019e05fa2,
397 0x00000000197c59b5,
398 0x0000000019184fdb, 0x0000000018b44221, 0x0000000018503098,
399 0x0000000017ec1b50, 0x0000000017880257, 0x000000001723e5bd,
400 0x0000000016bfc591, 0x00000000165ba1e4, 0x0000000015f77ac3,
401 0x0000000015935040,
402 0x00000000152f2269, 0x0000000014caf14d, 0x000000001466bcfd,
403 0x0000000014028587, 0x00000000139e4afb, 0x00000000133a0d69,
404 0x0000000012d5cce0, 0x000000001271896f, 0x00000000120d4326,
405 0x0000000011a8fa15,
406 0x000000001144ae4a, 0x0000000010e05fd6, 0x00000000107c0ec7,
407 0x000000001017bb2d, 0x000000000fb36519, 0x000000000f4f0c98,
408 0x000000000eeab1bb, 0x000000000e865491, 0x000000000e21f52a,
409 0x000000000dbd9395,
410 0x000000000d592fe1, 0x000000000cf4ca1f, 0x000000000c90625c,
411 0x000000000c2bf8aa, 0x000000000bc78d18, 0x000000000b631fb4,
412 0x000000000afeb08f, 0x000000000a9a3fb8, 0x000000000a35cd3e,
413 0x0000000009d15931,
414 0x00000000096ce3a1, 0x0000000009086c9c, 0x0000000008a3f433,
415 0x00000000083f7a75, 0x0000000007daff71, 0x0000000007768337,
416 0x00000000071205d6, 0x0000000006ad875f, 0x00000000064907df,
417 0x0000000005e48768,
418 0x0000000005800608, 0x00000000051b83cf, 0x0000000004b700cc,
419 0x0000000004527d0f, 0x0000000003edf8a7, 0x00000000038973a4,
420 0x000000000324ee16, 0x0000000002c0680b, 0x00000000025be194,
421 0x0000000001f75ac0,
422 0x000000000192d39e, 0x00000000012e4c3e, 0x0000000000c9c4af,
423 0x0000000000653d02, 0x0000000000000000
424};
425
426EAPI Eina_F32p32
427eina_f32p32_cos(Eina_F32p32 a)
428{
429 Eina_F32p32 F32P32_2PI;
430 Eina_F32p32 F32P32_PI2;
431 Eina_F32p32 F32P32_3PI2;
432 Eina_F32p32 remainder_2PI;
433 Eina_F32p32 remainder_PI;
434 Eina_F32p32 interpol;
435 Eina_F32p32 result;
436 int idx;
437 int index2;
438
439 F32P32_2PI = EINA_F32P32_PI << 1;
440 F32P32_PI2 = EINA_F32P32_PI >> 1;
441 F32P32_3PI2 = EINA_F32P32_PI + F32P32_PI2;
442
443 /* Take advantage of cosinus symetrie. */
444 a = eina_fp32p32_llabs(a);
445
446 /* Find table entry in 0 to PI / 2 */
447 remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI;
448
449 /* Find which case from 0 to 2 * PI */
450 remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI;
451
452 interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
453 EINA_F32P32_PI);
454 idx = eina_f32p32_int_to(interpol);
455 if (idx >= MAX_PREC)
456 idx = 2 * MAX_PREC - (idx + 1);
457
458 index2 = idx + 1;
459 if (index2 == MAX_PREC)
460 index2 = idx - 1;
461
462 result = eina_f32p32_add(eina_trigo[idx],
463 eina_f32p32_mul(eina_f32p32_sub(eina_trigo[idx],
464 eina_trigo[index2]),
465 (Eina_F32p32)eina_f32p32_fracc_get(
466 interpol)));
467
468 if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2)
469 return result;
470 else if (F32P32_PI2 <= remainder_2PI && remainder_2PI < EINA_F32P32_PI)
471 return -result;
472 else if (EINA_F32P32_PI <= remainder_2PI && remainder_2PI < F32P32_3PI2)
473 return -result;
474 else /* if (F32P32_3PI2 <= remainder_2PI) */
475 return result;
476}
477
478EAPI Eina_F32p32
479eina_f32p32_sin(Eina_F32p32 a)
480{
481 Eina_F32p32 F32P32_2PI;
482 Eina_F32p32 F32P32_PI2;
483 Eina_F32p32 F32P32_3PI2;
484 Eina_F32p32 remainder_2PI;
485 Eina_F32p32 remainder_PI;
486 Eina_F32p32 interpol;
487 Eina_F32p32 result;
488 int idx;
489 int index2;
490
491 F32P32_2PI = EINA_F32P32_PI << 1;
492 F32P32_PI2 = EINA_F32P32_PI >> 1;
493 F32P32_3PI2 = EINA_F32P32_PI + F32P32_PI2;
494
495 /* We only have a table for cosinus, but sin(a) = cos(pi / 2 - a) */
496 a = eina_f32p32_sub(F32P32_PI2, a);
497
498 /* Take advantage of cosinus symetrie. */
499 a = eina_fp32p32_llabs(a);
500
501 /* Find table entry in 0 to PI / 2 */
502 remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI;
503
504 /* Find which case from 0 to 2 * PI */
505 remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI;
506
507 interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
508 EINA_F32P32_PI);
509 idx = eina_f32p32_int_to(interpol);
510 if (idx >= MAX_PREC)
511 idx = 2 * MAX_PREC - (idx + 1);
512
513 index2 = idx + 1;
514 if (index2 == MAX_PREC)
515 index2 = idx - 1;
516
517 result = eina_f32p32_add(eina_trigo[idx],
518 eina_f32p32_mul(eina_f32p32_sub(eina_trigo[idx],
519 eina_trigo[index2]),
520 (Eina_F32p32)eina_f32p32_fracc_get(
521 interpol)));
522
523 if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2)
524 return result;
525 else if (F32P32_PI2 <= remainder_2PI && remainder_2PI < EINA_F32P32_PI)
526 return -result;
527 else if (EINA_F32P32_PI <= remainder_2PI && remainder_2PI < F32P32_3PI2)
528 return -result;
529 else /* if (F32P32_3PI2 <= remainder_2PI) */
530 return result;
531}
532
diff --git a/libraries/eina/src/lib/eina_hamster.c b/libraries/eina/src/lib/eina_hamster.c
new file mode 100644
index 0000000..cebc10b
--- /dev/null
+++ b/libraries/eina/src/lib/eina_hamster.c
@@ -0,0 +1,113 @@
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#include <stdio.h>
24#include <string.h>
25
26#include "eina_config.h"
27#include "eina_types.h"
28#include "eina_hamster.h"
29
30/*============================================================================*
31* Local *
32*============================================================================*/
33
34/**
35 * @cond LOCAL
36 */
37
38const char *_eina_hamster_time = __TIME__;
39const char *_eina_hamster_date = __DATE__;
40static int _eina_hamsters = -1;
41
42/**
43 * @endcond
44 */
45
46/*============================================================================*
47* Global *
48*============================================================================*/
49
50/*============================================================================*
51* API *
52*============================================================================*/
53
54EAPI int
55eina_hamster_count(void)
56{
57 if (_eina_hamsters < 0)
58 {
59 int hrs = 0, min = 0, sec = 0;
60 char mon[8] = "";
61 int monnum = 0, day = 0, year = 0;
62 int fields;
63
64 fields = sscanf(_eina_hamster_time, "%02d:%02d:%02d", &hrs, &min, &sec);
65 if (fields == 3)
66 {
67 _eina_hamsters = (hrs * 60) + min;
68 fields = sscanf(_eina_hamster_date, "%s %d %d", mon, &day, &year);
69 if (fields == 3)
70 {
71 int i;
72 const char *mons[] =
73 {
74 "Jan",
75 "Feb",
76 "Mar",
77 "Apr",
78 "May",
79 "Jun",
80 "Jul",
81 "Aug",
82 "Sep",
83 "Oct",
84 "Nov",
85 "Dec"
86 };
87
88 for (i = 0; i < 12; i++)
89 {
90 if (!strcmp(mon, mons[i]))
91 {
92 monnum = i + 1;
93 break;
94 }
95 }
96 // alloc 60 for mins, 24 for hrs
97 // alloc 1-31 (32) for days, 1-12 (13) for months
98 // use year as-is, for 31 bits (signed) this gives us up to
99 // 3584 years, which is good enough imho. - 1500 years from
100 // now or so. :)
101 _eina_hamsters +=
102 (day + (monnum * 32) + (13 * 32 * year)) * (24 * 60);
103 }
104 }
105 }
106
107 // format: [rest - year][0-12 - month][0-31 - day][0-23 - hrs][0-59 - sec]
108 return _eina_hamsters;
109}
110
111/**
112 * @}
113 */
diff --git a/libraries/eina/src/lib/eina_hash.c b/libraries/eina/src/lib/eina_hash.c
new file mode 100644
index 0000000..5df20aa
--- /dev/null
+++ b/libraries/eina/src/lib/eina_hash.c
@@ -0,0 +1,1375 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri,
3 * Vincent Torri, Jorge Luis Zapata Muga, 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#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#ifdef HAVE_STDINT_H
29# include <stdint.h>
30#endif
31
32#ifdef _MSC_VER
33# include <Evil.h>
34#endif
35
36#include "eina_config.h"
37#include "eina_private.h"
38#include "eina_rbtree.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_hash.h"
44
45/*============================================================================*
46 * Local *
47 *============================================================================*/
48
49/**
50 * @cond LOCAL
51 */
52
53#define EINA_MAGIC_CHECK_HASH(d) \
54 do { \
55 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH)) { \
56 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH); } \
57 } while(0)
58
59#define EINA_MAGIC_CHECK_HASH_ITERATOR(d, ...) \
60 do { \
61 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH_ITERATOR)) \
62 { \
63 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH_ITERATOR); \
64 return __VA_ARGS__; \
65 } \
66 } while(0)
67
68#define EINA_HASH_BUCKET_SIZE 8
69#define EINA_HASH_SMALL_BUCKET_SIZE 5
70
71#define EINA_HASH_RBTREE_MASK 0xFFF
72
73typedef struct _Eina_Hash_Head Eina_Hash_Head;
74typedef struct _Eina_Hash_Element Eina_Hash_Element;
75typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data;
76typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash;
77typedef struct _Eina_Hash_Each Eina_Hash_Each;
78
79struct _Eina_Hash
80{
81 Eina_Key_Length key_length_cb;
82 Eina_Key_Cmp key_cmp_cb;
83 Eina_Key_Hash key_hash_cb;
84 Eina_Free_Cb data_free_cb;
85
86 Eina_Rbtree **buckets;
87 int size;
88 int mask;
89
90 int population;
91
92 EINA_MAGIC
93};
94
95struct _Eina_Hash_Head
96{
97 EINA_RBTREE;
98 int hash;
99
100 Eina_Rbtree *head;
101};
102
103struct _Eina_Hash_Element
104{
105 EINA_RBTREE;
106 Eina_Hash_Tuple tuple;
107 Eina_Bool begin : 1;
108};
109
110struct _Eina_Hash_Foreach_Data
111{
112 Eina_Hash_Foreach cb;
113 const void *fdata;
114};
115
116typedef void *(*Eina_Iterator_Get_Content_Callback)(Eina_Iterator_Hash *it);
117#define FUNC_ITERATOR_GET_CONTENT(Function) \
118 ((Eina_Iterator_Get_Content_Callback)Function)
119
120struct _Eina_Iterator_Hash
121{
122 Eina_Iterator iterator;
123
124 Eina_Iterator_Get_Content_Callback get_content;
125 const Eina_Hash *hash;
126
127 Eina_Iterator *current;
128 Eina_Iterator *list;
129 Eina_Hash_Head *hash_head;
130 Eina_Hash_Element *hash_element;
131 int bucket;
132
133 int index;
134
135 EINA_MAGIC
136};
137
138struct _Eina_Hash_Each
139{
140 Eina_Hash_Head *hash_head;
141 const Eina_Hash_Element *hash_element;
142 const void *data;
143};
144
145#undef get16bits
146#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
147 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
148# define get16bits(d) (*((const uint16_t *)(d)))
149#endif
150
151#if !defined (get16bits)
152# define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
153 + (uint32_t)(((const uint8_t *)(d))[0]))
154#endif
155
156static inline int
157_eina_hash_hash_rbtree_cmp_hash(const Eina_Hash_Head *hash_head,
158 const int *hash,
159 __UNUSED__ int key_length,
160 __UNUSED__ void *data)
161{
162 return hash_head->hash - *hash;
163}
164
165static Eina_Rbtree_Direction
166_eina_hash_hash_rbtree_cmp_node(const Eina_Hash_Head *left,
167 const Eina_Hash_Head *right,
168 __UNUSED__ void *data)
169{
170 if (left->hash - right->hash < 0)
171 return EINA_RBTREE_LEFT;
172
173 return EINA_RBTREE_RIGHT;
174}
175
176static inline int
177_eina_hash_key_rbtree_cmp_key_data(const Eina_Hash_Element *hash_element,
178 const Eina_Hash_Tuple *tuple,
179 __UNUSED__ unsigned int key_length,
180 Eina_Key_Cmp cmp)
181{
182 int result;
183
184 result = cmp(hash_element->tuple.key,
185 hash_element->tuple.key_length,
186 tuple->key,
187 tuple->key_length);
188
189 if (result == 0 && tuple->data && tuple->data != hash_element->tuple.data)
190 return 1;
191
192 return result;
193}
194
195static Eina_Rbtree_Direction
196_eina_hash_key_rbtree_cmp_node(const Eina_Hash_Element *left,
197 const Eina_Hash_Element *right,
198 Eina_Key_Cmp cmp)
199{
200 int result;
201
202 result = cmp(left->tuple.key, left->tuple.key_length,
203 right->tuple.key, right->tuple.key_length);
204
205 if (result < 0)
206 return EINA_RBTREE_LEFT;
207
208 return EINA_RBTREE_RIGHT;
209}
210
211static inline Eina_Bool
212eina_hash_add_alloc_by_hash(Eina_Hash *hash,
213 const void *key, int key_length, int alloc_length,
214 int key_hash,
215 const void *data)
216{
217 Eina_Hash_Element *new_hash_element = NULL;
218 Eina_Hash_Head *hash_head;
219 Eina_Error error = 0;
220 int hash_num;
221
222 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
223 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
225 EINA_MAGIC_CHECK_HASH(hash);
226
227 error = EINA_ERROR_OUT_OF_MEMORY;
228
229 /* Apply eina mask to hash. */
230 hash_num = key_hash & hash->mask;
231 key_hash &= EINA_HASH_RBTREE_MASK;
232
233 if (!hash->buckets)
234 {
235 hash->buckets = calloc(sizeof (Eina_Rbtree *), hash->size);
236 if (!hash->buckets) goto on_error;
237
238 hash_head = NULL;
239 }
240 else
241 /* Look up for head node. */
242 hash_head = (Eina_Hash_Head *)
243 eina_rbtree_inline_lookup(hash->buckets[hash_num],
244 &key_hash, 0,
245 EINA_RBTREE_CMP_KEY_CB(
246 _eina_hash_hash_rbtree_cmp_hash),
247 NULL);
248
249 if (!hash_head)
250 {
251 /* If not found allocate it and an element. */
252 hash_head = malloc(sizeof(Eina_Hash_Head) + sizeof(Eina_Hash_Element)
253 + alloc_length);
254 if (!hash_head)
255 goto on_error;
256
257 hash_head->hash = key_hash;
258 hash_head->head = NULL;
259
260 hash->buckets[hash_num] =
261 eina_rbtree_inline_insert(hash->buckets[hash_num],
262 EINA_RBTREE_GET(hash_head),
263 EINA_RBTREE_CMP_NODE_CB(
264 _eina_hash_hash_rbtree_cmp_node),
265 NULL);
266
267 new_hash_element = (Eina_Hash_Element *)(hash_head + 1);
268 new_hash_element->begin = EINA_TRUE;
269 }
270
271 if (!new_hash_element)
272 {
273 /*
274 Alloc a new element
275 (No more lookup as we expect to support more than one item for one key).
276 */
277 new_hash_element = malloc(sizeof (Eina_Hash_Element) + alloc_length);
278 if (!new_hash_element)
279 goto on_error;
280
281 new_hash_element->begin = EINA_FALSE;
282 }
283
284 /* Setup the element */
285 new_hash_element->tuple.key_length = key_length;
286 new_hash_element->tuple.data = (void *)data;
287 if (alloc_length > 0)
288 {
289 new_hash_element->tuple.key = (char *)(new_hash_element + 1);
290 memcpy((char *)new_hash_element->tuple.key, key, alloc_length);
291 }
292 else
293 new_hash_element->tuple.key = key;
294
295 /* add the new element to the hash. */
296 hash_head->head = eina_rbtree_inline_insert(hash_head->head,
297 EINA_RBTREE_GET(new_hash_element),
298 EINA_RBTREE_CMP_NODE_CB(
299 _eina_hash_key_rbtree_cmp_node),
300 (const void *)hash->key_cmp_cb);
301 hash->population++;
302 return EINA_TRUE;
303
304on_error:
305 eina_error_set(error);
306 return EINA_FALSE;
307}
308
309static Eina_Bool
310_eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container,
311 const Eina_Hash_Head *hash_head,
312 Eina_Hash_Each *data)
313{
314 Eina_Iterator *it;
315 Eina_Hash_Element *hash_element;
316 Eina_Bool found = EINA_TRUE;
317
318 it = eina_rbtree_iterator_prefix(hash_head->head);
319 EINA_ITERATOR_FOREACH(it, hash_element)
320 {
321 if (hash_element->tuple.data == data->data)
322 {
323 data->hash_element = hash_element;
324 data->hash_head = (Eina_Hash_Head *)hash_head;
325 found = EINA_FALSE;
326 break;
327 }
328 }
329
330 eina_iterator_free(it);
331 return found;
332}
333
334static inline Eina_Hash_Element *
335_eina_hash_find_by_hash(const Eina_Hash *hash,
336 Eina_Hash_Tuple *tuple,
337 int key_hash,
338 Eina_Hash_Head **hash_head)
339{
340 Eina_Hash_Element *hash_element;
341 int rb_hash = key_hash & EINA_HASH_RBTREE_MASK;
342
343 key_hash &= hash->mask;
344
345 if (!hash->buckets)
346 return NULL;
347
348 *hash_head = (Eina_Hash_Head *)
349 eina_rbtree_inline_lookup(hash->buckets[key_hash],
350 &rb_hash, 0,
351 EINA_RBTREE_CMP_KEY_CB(
352 _eina_hash_hash_rbtree_cmp_hash),
353 NULL);
354 if (!*hash_head)
355 return NULL;
356
357 hash_element = (Eina_Hash_Element *)
358 eina_rbtree_inline_lookup((*hash_head)->head,
359 tuple, 0,
360 EINA_RBTREE_CMP_KEY_CB(
361 _eina_hash_key_rbtree_cmp_key_data),
362 (const void *)hash->key_cmp_cb);
363
364 return hash_element;
365}
366
367static inline Eina_Hash_Element *
368_eina_hash_find_by_data(const Eina_Hash *hash,
369 const void *data,
370 int *key_hash,
371 Eina_Hash_Head **hash_head)
372{
373 Eina_Hash_Each each;
374 Eina_Iterator *it;
375 int hash_num;
376
377 if (!hash->buckets)
378 return NULL;
379
380 each.hash_element = NULL;
381 each.data = data;
382
383 for (hash_num = 0; hash_num < hash->size; hash_num++)
384 {
385 if (!hash->buckets[hash_num])
386 continue;
387
388 it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]);
389 eina_iterator_foreach(it, EINA_EACH_CB(_eina_hash_rbtree_each), &each);
390 eina_iterator_free(it);
391
392 if (each.hash_element)
393 {
394 *key_hash = hash_num;
395 *hash_head = each.hash_head;
396 return (Eina_Hash_Element *)each.hash_element;
397 }
398 }
399
400 return NULL;
401}
402
403static void
404_eina_hash_el_free(Eina_Hash_Element *hash_element, Eina_Hash *hash)
405{
406 if (hash->data_free_cb)
407 hash->data_free_cb(hash_element->tuple.data);
408
409 if (hash_element->begin == EINA_FALSE)
410 free(hash_element);
411}
412
413static void
414_eina_hash_head_free(Eina_Hash_Head *hash_head, Eina_Hash *hash)
415{
416 eina_rbtree_delete(hash_head->head, EINA_RBTREE_FREE_CB(_eina_hash_el_free), hash);
417 free(hash_head);
418}
419
420static Eina_Bool
421_eina_hash_del_by_hash_el(Eina_Hash *hash,
422 Eina_Hash_Element *hash_element,
423 Eina_Hash_Head *hash_head,
424 int key_hash)
425{
426 hash_head->head = eina_rbtree_inline_remove(hash_head->head, EINA_RBTREE_GET(
427 hash_element), EINA_RBTREE_CMP_NODE_CB(
428 _eina_hash_key_rbtree_cmp_node),
429 (const void *)hash->key_cmp_cb);
430 _eina_hash_el_free(hash_element, hash);
431
432 if (!hash_head->head)
433 {
434 key_hash &= hash->mask;
435
436 hash->buckets[key_hash] =
437 eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(
438 hash_head),
439 EINA_RBTREE_CMP_NODE_CB(
440 _eina_hash_hash_rbtree_cmp_node), NULL);
441 free(hash_head);
442 }
443
444 hash->population--;
445 if (hash->population == 0)
446 {
447 free(hash->buckets);
448 hash->buckets = NULL;
449 }
450
451 return EINA_TRUE;
452}
453
454static Eina_Bool
455_eina_hash_del_by_key_hash(Eina_Hash *hash,
456 const void *key,
457 int key_length,
458 int key_hash,
459 const void *data)
460{
461 Eina_Hash_Element *hash_element;
462 Eina_Hash_Head *hash_head;
463 Eina_Hash_Tuple tuple;
464
465 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
466 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
467 EINA_MAGIC_CHECK_HASH(hash);
468
469 if (!hash->buckets)
470 return EINA_FALSE;
471
472 tuple.key = (void *)key;
473 tuple.key_length = key_length;
474 tuple.data = (void *)data;
475
476 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
477 if (!hash_element)
478 return EINA_FALSE;
479
480 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
481}
482
483static Eina_Bool
484_eina_hash_del_by_key(Eina_Hash *hash, const void *key, const void *data)
485{
486 int key_length, key_hash;
487
488 EINA_MAGIC_CHECK_HASH(hash);
489 if (!hash)
490 return EINA_FALSE;
491
492 if (!key)
493 return EINA_FALSE;
494
495 if (!hash->buckets)
496 return EINA_FALSE;
497
498 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
499 key_hash = hash->key_hash_cb(key, key_length);
500 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
501}
502
503static unsigned int
504_eina_string_key_length(const char *key)
505{
506 if (!key)
507 return 0;
508
509 return (int)strlen(key) + 1;
510}
511
512static int
513_eina_string_key_cmp(const char *key1, __UNUSED__ int key1_length,
514 const char *key2, __UNUSED__ int key2_length)
515{
516 return strcmp(key1, key2);
517}
518
519static int
520_eina_stringshared_key_cmp(const char *key1, __UNUSED__ int key1_length,
521 const char *key2, __UNUSED__ int key2_length)
522{
523 return key1 - key2;
524}
525
526static unsigned int
527_eina_int32_key_length(__UNUSED__ const uint32_t *key)
528{
529 return 4;
530}
531
532static int
533_eina_int32_key_cmp(const uint32_t *key1, __UNUSED__ int key1_length,
534 const uint32_t *key2, __UNUSED__ int key2_length)
535{
536 return *key1 - *key2;
537}
538
539static unsigned int
540_eina_int64_key_length(__UNUSED__ const uint32_t *key)
541{
542 return 8;
543}
544
545static int
546_eina_int64_key_cmp(const uint64_t *key1, __UNUSED__ int key1_length,
547 const uint64_t *key2, __UNUSED__ int key2_length)
548{
549 return *key1 - *key2;
550}
551
552static Eina_Bool
553_eina_foreach_cb(const Eina_Hash *hash,
554 Eina_Hash_Tuple *data,
555 Eina_Hash_Foreach_Data *fdata)
556{
557 return fdata->cb((Eina_Hash *)hash,
558 data->key,
559 data->data,
560 (void *)fdata->fdata);
561}
562
563static void *
564_eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
565{
566 Eina_Hash_Element *stuff;
567
568 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
569
570 stuff = it->hash_element;
571
572 if (!stuff)
573 return NULL;
574
575 return stuff->tuple.data;
576}
577
578static void *
579_eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
580{
581 Eina_Hash_Element *stuff;
582
583 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
584
585 stuff = it->hash_element;
586
587 if (!stuff)
588 return NULL;
589
590 return (void *)stuff->tuple.key;
591}
592
593static Eina_Hash_Tuple *
594_eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it)
595{
596 Eina_Hash_Element *stuff;
597
598 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
599
600 stuff = it->hash_element;
601
602 if (!stuff)
603 return NULL;
604
605 return &stuff->tuple;
606}
607
608static Eina_Bool
609_eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
610{
611 Eina_Bool ok;
612 int bucket;
613
614 if (!(it->index < it->hash->population))
615 return EINA_FALSE;
616
617 if (!it->current)
618 {
619 ok = EINA_FALSE;
620 bucket = 0;
621 it->index = -1;
622 }
623 else
624 {
625 ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element);
626 if (!ok)
627 {
628 eina_iterator_free(it->list);
629 it->list = NULL;
630
631 ok = eina_iterator_next(it->current, (void **)(void*)&it->hash_head);
632 if (!ok)
633 {
634 eina_iterator_free(it->current);
635 it->current = NULL;
636 it->bucket++;
637 }
638 else
639 {
640 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
641 ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element);
642 }
643 }
644
645 bucket = it->bucket;
646 }
647
648 if (ok == EINA_FALSE)
649 {
650 while (bucket < it->hash->size)
651 {
652 if (it->hash->buckets[bucket])
653 {
654 it->current =
655 eina_rbtree_iterator_prefix(it->hash->buckets[bucket]);
656 ok = eina_iterator_next(it->current, (void **)(void*)&it->hash_head);
657 if (ok)
658 break;
659
660 eina_iterator_free(it->current);
661 it->current = NULL;
662 }
663
664 ++bucket;
665 }
666 if (it->list)
667 eina_iterator_free(it->list);
668
669 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
670 ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element);
671 if (bucket == it->hash->size)
672 ok = EINA_FALSE;
673 }
674
675 it->index++;
676 it->bucket = bucket;
677
678 if (ok)
679 *data = it->get_content(it);
680
681 return ok;
682}
683
684static void *
685_eina_hash_iterator_get_container(Eina_Iterator_Hash *it)
686{
687 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
688 return (void *)it->hash;
689}
690
691static void
692_eina_hash_iterator_free(Eina_Iterator_Hash *it)
693{
694 EINA_MAGIC_CHECK_HASH_ITERATOR(it);
695 if (it->current)
696 eina_iterator_free(it->current);
697
698 if (it->list)
699 eina_iterator_free(it->list);
700
701 free(it);
702}
703
704/**
705 * @endcond
706 */
707
708/*============================================================================*
709 * Global *
710 *============================================================================*/
711
712/*============================================================================*
713 * API *
714 *============================================================================*/
715
716EAPI void
717eina_hash_free_cb_set(Eina_Hash *hash, Eina_Free_Cb data_free_cb)
718{
719 EINA_MAGIC_CHECK_HASH(hash);
720 EINA_SAFETY_ON_NULL_RETURN(hash);
721
722 hash->data_free_cb = data_free_cb;
723}
724
725EAPI Eina_Hash *
726eina_hash_new(Eina_Key_Length key_length_cb,
727 Eina_Key_Cmp key_cmp_cb,
728 Eina_Key_Hash key_hash_cb,
729 Eina_Free_Cb data_free_cb,
730 int buckets_power_size)
731{
732 /* FIXME: Use mempool. */
733 Eina_Hash *new;
734
735 eina_error_set(0);
736 EINA_SAFETY_ON_NULL_RETURN_VAL(key_cmp_cb, NULL);
737 EINA_SAFETY_ON_NULL_RETURN_VAL(key_hash_cb, NULL);
738 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size <= 2, NULL);
739 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size >= 17, NULL);
740
741 new = malloc(sizeof (Eina_Hash));
742 if (!new)
743 goto on_error;
744
745 EINA_MAGIC_SET(new, EINA_MAGIC_HASH);
746
747 new->key_length_cb = key_length_cb;
748 new->key_cmp_cb = key_cmp_cb;
749 new->key_hash_cb = key_hash_cb;
750 new->data_free_cb = data_free_cb;
751 new->buckets = NULL;
752 new->population = 0;
753
754 new->size = 1 << buckets_power_size;
755 new->mask = new->size - 1;
756
757 return new;
758
759on_error:
760 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
761 return NULL;
762}
763
764EAPI Eina_Hash *
765eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb)
766{
767 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
768 EINA_KEY_CMP(_eina_string_key_cmp),
769 EINA_KEY_HASH(eina_hash_djb2),
770 data_free_cb,
771 EINA_HASH_BUCKET_SIZE);
772}
773
774EAPI Eina_Hash *
775eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
776{
777 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
778 EINA_KEY_CMP(_eina_string_key_cmp),
779 EINA_KEY_HASH(eina_hash_superfast),
780 data_free_cb,
781 EINA_HASH_BUCKET_SIZE);
782}
783
784EAPI Eina_Hash *
785eina_hash_string_small_new(Eina_Free_Cb data_free_cb)
786{
787 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
788 EINA_KEY_CMP(_eina_string_key_cmp),
789 EINA_KEY_HASH(eina_hash_superfast),
790 data_free_cb,
791 EINA_HASH_SMALL_BUCKET_SIZE);
792}
793
794EAPI Eina_Hash *
795eina_hash_int32_new(Eina_Free_Cb data_free_cb)
796{
797 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
798 EINA_KEY_CMP(_eina_int32_key_cmp),
799 EINA_KEY_HASH(eina_hash_int32),
800 data_free_cb,
801 EINA_HASH_BUCKET_SIZE);
802}
803
804EAPI Eina_Hash *
805eina_hash_int64_new(Eina_Free_Cb data_free_cb)
806{
807 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
808 EINA_KEY_CMP(_eina_int64_key_cmp),
809 EINA_KEY_HASH(eina_hash_int64),
810 data_free_cb,
811 EINA_HASH_BUCKET_SIZE);
812}
813
814EAPI Eina_Hash *
815eina_hash_pointer_new(Eina_Free_Cb data_free_cb)
816{
817#ifdef __LP64__
818 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
819 EINA_KEY_CMP(_eina_int64_key_cmp),
820 EINA_KEY_HASH(eina_hash_int64),
821 data_free_cb,
822 EINA_HASH_BUCKET_SIZE);
823#else
824 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
825 EINA_KEY_CMP(_eina_int32_key_cmp),
826 EINA_KEY_HASH(eina_hash_int32),
827 data_free_cb,
828 EINA_HASH_BUCKET_SIZE);
829#endif
830}
831
832EAPI Eina_Hash *
833eina_hash_stringshared_new(Eina_Free_Cb data_free_cb)
834{
835 return eina_hash_new(NULL,
836 EINA_KEY_CMP(_eina_stringshared_key_cmp),
837 EINA_KEY_HASH(eina_hash_superfast),
838 data_free_cb,
839 EINA_HASH_BUCKET_SIZE);
840}
841
842EAPI int
843eina_hash_population(const Eina_Hash *hash)
844{
845 if (!hash)
846 return 0;
847
848 EINA_MAGIC_CHECK_HASH(hash);
849 return hash->population;
850}
851
852EAPI void
853eina_hash_free(Eina_Hash *hash)
854{
855 int i;
856
857 EINA_MAGIC_CHECK_HASH(hash);
858 EINA_SAFETY_ON_NULL_RETURN(hash);
859
860 if (hash->buckets)
861 {
862 for (i = 0; i < hash->size; i++)
863 eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
864 free(hash->buckets);
865 }
866 free(hash);
867}
868
869EAPI void
870eina_hash_free_buckets(Eina_Hash *hash)
871{
872 int i;
873
874 EINA_MAGIC_CHECK_HASH(hash);
875 EINA_SAFETY_ON_NULL_RETURN(hash);
876
877 if (hash->buckets)
878 {
879 for (i = 0; i < hash->size; i++)
880 eina_rbtree_delete(hash->buckets[i],
881 EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
882 free(hash->buckets);
883 hash->buckets = NULL;
884 hash->population = 0;
885 }
886}
887
888EAPI Eina_Bool
889eina_hash_add_by_hash(Eina_Hash *hash,
890 const void *key,
891 int key_length,
892 int key_hash,
893 const void *data)
894{
895 return eina_hash_add_alloc_by_hash(hash,
896 key,
897 key_length,
898 key_length,
899 key_hash,
900 data);
901}
902
903EAPI Eina_Bool
904eina_hash_direct_add_by_hash(Eina_Hash *hash,
905 const void *key,
906 int key_length,
907 int key_hash,
908 const void *data)
909{
910 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
911}
912
913EAPI Eina_Bool
914eina_hash_add(Eina_Hash *hash, const void *key, const void *data)
915{
916 unsigned int key_length;
917 int key_hash;
918
919 EINA_MAGIC_CHECK_HASH(hash);
920 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
921 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
922 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
923 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
924
925 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
926 key_hash = hash->key_hash_cb(key, key_length);
927
928 return eina_hash_add_alloc_by_hash(hash, key, key_length, key_length, key_hash, data);
929}
930
931EAPI Eina_Bool
932eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data)
933{
934 int key_length;
935 int key_hash;
936
937 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
938 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
939 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
940 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
941 EINA_MAGIC_CHECK_HASH(hash);
942
943 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
944 key_hash = hash->key_hash_cb(key, key_length);
945
946 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
947}
948
949EAPI Eina_Bool
950eina_hash_del_by_key_hash(Eina_Hash *hash,
951 const void *key,
952 int key_length,
953 int key_hash)
954{
955 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
956 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
957
958 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, NULL);
959}
960
961EAPI Eina_Bool
962eina_hash_del_by_key(Eina_Hash *hash, const void *key)
963{
964 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
965 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
966
967 return _eina_hash_del_by_key(hash, key, NULL);
968}
969
970EAPI Eina_Bool
971eina_hash_del_by_data(Eina_Hash *hash, const void *data)
972{
973 Eina_Hash_Element *hash_element;
974 Eina_Hash_Head *hash_head;
975 int key_hash;
976
977 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
978 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
979 EINA_MAGIC_CHECK_HASH(hash);
980
981 hash_element = _eina_hash_find_by_data(hash, data, &key_hash, &hash_head);
982 if (!hash_element)
983 goto error;
984
985 if (hash_element->tuple.data != data)
986 goto error;
987
988 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
989
990error:
991 return EINA_FALSE;
992}
993
994EAPI Eina_Bool
995eina_hash_del_by_hash(Eina_Hash *hash,
996 const void *key,
997 int key_length,
998 int key_hash,
999 const void *data)
1000{
1001 Eina_Bool ret;
1002
1003 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1004 EINA_MAGIC_CHECK_HASH(hash);
1005
1006 if (key)
1007 ret = _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
1008 else
1009 ret = eina_hash_del_by_data(hash, data);
1010
1011 return ret;
1012}
1013
1014EAPI Eina_Bool
1015eina_hash_del(Eina_Hash *hash, const void *key, const void *data)
1016{
1017 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1018 EINA_MAGIC_CHECK_HASH(hash);
1019
1020 if (!key)
1021 return eina_hash_del_by_data(hash, data);
1022
1023 return _eina_hash_del_by_key(hash, key, data);
1024}
1025
1026EAPI void *
1027eina_hash_find_by_hash(const Eina_Hash *hash,
1028 const void *key,
1029 int key_length,
1030 int key_hash)
1031{
1032 Eina_Hash_Head *hash_head;
1033 Eina_Hash_Element *hash_element;
1034 Eina_Hash_Tuple tuple;
1035
1036 if (!hash)
1037 return NULL;
1038
1039 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1040 EINA_MAGIC_CHECK_HASH(hash);
1041
1042 tuple.key = key;
1043 tuple.key_length = key_length;
1044 tuple.data = NULL;
1045
1046 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1047 if (hash_element)
1048 return hash_element->tuple.data;
1049
1050 return NULL;
1051}
1052
1053EAPI void *
1054eina_hash_find(const Eina_Hash *hash, const void *key)
1055{
1056 int key_length;
1057 int hash_num;
1058
1059 if (!hash)
1060 return NULL;
1061
1062 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1063 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1064 EINA_MAGIC_CHECK_HASH(hash);
1065
1066 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1067 hash_num = hash->key_hash_cb(key, key_length);
1068
1069 return eina_hash_find_by_hash(hash, key, key_length, hash_num);
1070}
1071
1072EAPI void *
1073eina_hash_modify_by_hash(Eina_Hash *hash,
1074 const void *key,
1075 int key_length,
1076 int key_hash,
1077 const void *data)
1078{
1079 Eina_Hash_Head *hash_head;
1080 Eina_Hash_Element *hash_element;
1081 void *old_data = NULL;
1082 Eina_Hash_Tuple tuple;
1083
1084 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1085 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1086 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1087 EINA_MAGIC_CHECK_HASH(hash);
1088
1089 tuple.key = key;
1090 tuple.key_length = key_length;
1091 tuple.data = NULL;
1092
1093 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1094 if (hash_element)
1095 {
1096 old_data = hash_element->tuple.data;
1097 hash_element->tuple.data = (void *)data;
1098 }
1099
1100 return old_data;
1101}
1102
1103EAPI void *
1104eina_hash_set(Eina_Hash *hash, const void *key, const void *data)
1105{
1106 Eina_Hash_Tuple tuple;
1107 Eina_Hash_Head *hash_head;
1108 Eina_Hash_Element *hash_element;
1109 int key_length;
1110 int key_hash;
1111
1112 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1113 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1114 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1115 EINA_MAGIC_CHECK_HASH(hash);
1116
1117 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1118 key_hash = hash->key_hash_cb(key, key_length);
1119
1120 tuple.key = key;
1121 tuple.key_length = key_length;
1122 tuple.data = NULL;
1123
1124 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1125 if (hash_element)
1126 {
1127 void *old_data = NULL;
1128
1129 old_data = hash_element->tuple.data;
1130
1131 if (data)
1132 {
1133 hash_element->tuple.data = (void *)data;
1134 }
1135 else
1136 {
1137 _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
1138 }
1139
1140 return old_data;
1141 }
1142
1143 if (!data) return NULL;
1144
1145 eina_hash_add_alloc_by_hash(hash,
1146 key,
1147 key_length,
1148 key_length,
1149 key_hash,
1150 data);
1151 return NULL;
1152}
1153EAPI void *
1154eina_hash_modify(Eina_Hash *hash, const void *key, const void *data)
1155{
1156 int key_length;
1157 int hash_num;
1158
1159 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1160 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1161 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1162 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1163 EINA_MAGIC_CHECK_HASH(hash);
1164
1165 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1166 hash_num = hash->key_hash_cb(key, key_length);
1167
1168 return eina_hash_modify_by_hash(hash, key, key_length, hash_num, data);
1169}
1170
1171EAPI Eina_Bool
1172eina_hash_move(Eina_Hash *hash, const void *old_key, const void *new_key)
1173{
1174 Eina_Free_Cb hash_free_cb;
1175 const void *data;
1176 Eina_Bool result = EINA_FALSE;
1177
1178 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1179 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
1180 EINA_SAFETY_ON_NULL_RETURN_VAL(old_key, EINA_FALSE);
1181 EINA_SAFETY_ON_NULL_RETURN_VAL(new_key, EINA_FALSE);
1182 EINA_MAGIC_CHECK_HASH(hash);
1183
1184 data = eina_hash_find(hash, old_key);
1185 if (!data) goto error;
1186
1187 hash_free_cb = hash->data_free_cb;
1188 hash->data_free_cb = NULL;
1189
1190 eina_hash_del(hash, old_key, data);
1191 result = eina_hash_add(hash, new_key, data);
1192
1193 hash->data_free_cb = hash_free_cb;
1194
1195error:
1196 return result;
1197}
1198
1199/*============================================================================*
1200* Iterator *
1201*============================================================================*/
1202
1203EAPI void
1204eina_hash_foreach(const Eina_Hash *hash,
1205 Eina_Hash_Foreach func,
1206 const void *fdata)
1207{
1208 Eina_Iterator *it;
1209 Eina_Hash_Foreach_Data foreach;
1210
1211 EINA_MAGIC_CHECK_HASH(hash);
1212 EINA_SAFETY_ON_NULL_RETURN(hash);
1213 EINA_SAFETY_ON_NULL_RETURN(func);
1214
1215 foreach.cb = func;
1216 foreach.fdata = fdata;
1217
1218 it = eina_hash_iterator_tuple_new(hash);
1219 if (!it)
1220 return;
1221 eina_iterator_foreach(it, EINA_EACH_CB(_eina_foreach_cb), &foreach);
1222
1223 eina_iterator_free(it);
1224}
1225
1226EAPI Eina_Iterator *
1227eina_hash_iterator_data_new(const Eina_Hash *hash)
1228{
1229 Eina_Iterator_Hash *it;
1230
1231 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1232 EINA_MAGIC_CHECK_HASH(hash);
1233
1234 eina_error_set(0);
1235 it = calloc(1, sizeof (Eina_Iterator_Hash));
1236 if (!it)
1237 {
1238 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1239 return NULL;
1240 }
1241
1242 it->hash = hash;
1243 it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content);
1244
1245 it->iterator.version = EINA_ITERATOR_VERSION;
1246 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1247 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1248 _eina_hash_iterator_get_container);
1249 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1250
1251 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1252 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1253
1254 return &it->iterator;
1255}
1256
1257EAPI Eina_Iterator *
1258eina_hash_iterator_key_new(const Eina_Hash *hash)
1259{
1260 Eina_Iterator_Hash *it;
1261
1262 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1263 EINA_MAGIC_CHECK_HASH(hash);
1264
1265 eina_error_set(0);
1266 it = calloc(1, sizeof (Eina_Iterator_Hash));
1267 if (!it)
1268 {
1269 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1270 return NULL;
1271 }
1272
1273 it->hash = hash;
1274 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1275 _eina_hash_iterator_key_get_content);
1276
1277 it->iterator.version = EINA_ITERATOR_VERSION;
1278 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1279 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1280 _eina_hash_iterator_get_container);
1281 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1282
1283 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1284 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1285
1286 return &it->iterator;
1287}
1288
1289EAPI Eina_Iterator *
1290eina_hash_iterator_tuple_new(const Eina_Hash *hash)
1291{
1292 Eina_Iterator_Hash *it;
1293
1294 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1295 EINA_MAGIC_CHECK_HASH(hash);
1296
1297 eina_error_set(0);
1298 it = calloc(1, sizeof (Eina_Iterator_Hash));
1299 if (!it)
1300 {
1301 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1302 return NULL;
1303 }
1304
1305 it->hash = hash;
1306 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1307 _eina_hash_iterator_tuple_get_content);
1308
1309 it->iterator.version = EINA_ITERATOR_VERSION;
1310 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1311 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1312 _eina_hash_iterator_get_container);
1313 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1314
1315 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1316 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1317
1318 return &it->iterator;
1319}
1320
1321/* Common hash functions */
1322
1323/* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
1324 used by WebCore (http://webkit.org/blog/8/hashtables-part-2/) */
1325EAPI int
1326eina_hash_superfast(const char *key, int len)
1327{
1328 int hash = len, tmp;
1329 int rem;
1330
1331 rem = len & 3;
1332 len >>= 2;
1333
1334 /* Main loop */
1335 for (; len > 0; len--)
1336 {
1337 hash += get16bits(key);
1338 tmp = (get16bits(key + 2) << 11) ^ hash;
1339 hash = (hash << 16) ^ tmp;
1340 key += 2 * sizeof (uint16_t);
1341 hash += hash >> 11;
1342 }
1343
1344 /* Handle end cases */
1345 switch (rem)
1346 {
1347 case 3:
1348 hash += get16bits(key);
1349 hash ^= hash << 16;
1350 hash ^= key[sizeof (uint16_t)] << 18;
1351 hash += hash >> 11;
1352 break;
1353
1354 case 2:
1355 hash += get16bits(key);
1356 hash ^= hash << 11;
1357 hash += hash >> 17;
1358 break;
1359
1360 case 1:
1361 hash += *key;
1362 hash ^= hash << 10;
1363 hash += hash >> 1;
1364 }
1365
1366 /* Force "avalanching" of final 127 bits */
1367 hash ^= hash << 3;
1368 hash += hash >> 5;
1369 hash ^= hash << 4;
1370 hash += hash >> 17;
1371 hash ^= hash << 25;
1372 hash += hash >> 6;
1373
1374 return hash;
1375}
diff --git a/libraries/eina/src/lib/eina_inlist.c b/libraries/eina/src/lib/eina_inlist.c
new file mode 100644
index 0000000..75a2cc1
--- /dev/null
+++ b/libraries/eina/src/lib/eina_inlist.c
@@ -0,0 +1,909 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, 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 <stdlib.h>
24#include <assert.h>
25
26#include <stdio.h>
27
28#include "eina_config.h"
29#include "eina_private.h"
30#include "eina_error.h"
31#include "eina_log.h"
32
33/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
34#include "eina_safety_checks.h"
35#include "eina_inlist.h"
36
37/* FIXME: TODO please, refactor this :) */
38
39/*============================================================================*
40* Local *
41*============================================================================*/
42
43/**
44 * @cond LOCAL
45 */
46
47#define EINA_INLIST_SORT_STACK_SIZE 32
48
49typedef struct _Eina_Iterator_Inlist Eina_Iterator_Inlist;
50typedef struct _Eina_Accessor_Inlist Eina_Accessor_Inlist;
51
52struct _Eina_Iterator_Inlist
53{
54 Eina_Iterator iterator;
55 const Eina_Inlist *head;
56 const Eina_Inlist *current;
57};
58
59struct _Eina_Accessor_Inlist
60{
61 Eina_Accessor accessor;
62
63 const Eina_Inlist *head;
64 const Eina_Inlist *current;
65
66 unsigned int index;
67};
68
69struct _Eina_Inlist_Sorted_State
70{
71 Eina_Inlist *jump_table[EINA_INLIST_JUMP_SIZE];
72
73 unsigned short jump_limit;
74 int jump_div;
75
76 int inserted;
77};
78
79static Eina_Bool
80eina_inlist_iterator_next(Eina_Iterator_Inlist *it, void **data) {
81 if (!it->current)
82 return EINA_FALSE;
83
84 if (data)
85 *data = (void *)it->current;
86
87 it->current = it->current->next;
88
89 return EINA_TRUE;
90}
91
92static Eina_Inlist *
93eina_inlist_iterator_get_container(Eina_Iterator_Inlist *it) {
94 return (Eina_Inlist *)it->head;
95}
96
97static void
98eina_inlist_iterator_free(Eina_Iterator_Inlist *it) {
99 free(it);
100}
101
102static Eina_Bool
103eina_inlist_accessor_get_at(Eina_Accessor_Inlist *it,
104 unsigned int idx,
105 void **data) {
106 const Eina_Inlist *over;
107 unsigned int middle;
108 unsigned int i;
109
110 if (it->index == idx)
111 over = it->current;
112 else if (idx > it->index)
113 /* Looking after current. */
114 for (i = it->index, over = it->current;
115 i < idx && over;
116 ++i, over = over->next)
117 ;
118 else
119 {
120 middle = it->index >> 1;
121
122 if (idx > middle)
123 /* Looking backward from current. */
124 for (i = it->index, over = it->current;
125 i > idx && over;
126 --i, over = over->prev)
127 ;
128 else
129 /* Looking from the start. */
130 for (i = 0, over = it->head;
131 i < idx && over;
132 ++i, over = over->next)
133 ;
134 }
135
136 if (!over)
137 return EINA_FALSE;
138
139 it->current = over;
140 it->index = idx;
141
142 if (data)
143 *data = (void *)over;
144
145 return EINA_TRUE;
146}
147
148static Eina_Inlist *
149eina_inlist_accessor_get_container(Eina_Accessor_Inlist *it) {
150 return (Eina_Inlist *)it->head;
151}
152
153static void
154eina_inlist_accessor_free(Eina_Accessor_Inlist *it) {
155 free(it);
156}
157
158static Eina_Inlist *
159eina_inlist_sort_merge(Eina_Inlist *a, Eina_Inlist *b, Eina_Compare_Cb func)
160{
161 Eina_Inlist *first, *last;
162
163 if (func(a, b) < 0)
164 a = (last = first = a)->next;
165 else
166 b = (last = first = b)->next;
167
168 while (a && b)
169 if (func(a, b) < 0)
170 a = (last = last->next = a)->next;
171 else
172 b = (last = last->next = b)->next;
173
174 last->next = a ? a : b;
175
176 return first;
177}
178
179static Eina_Inlist *
180eina_inlist_sort_rebuild_prev(Eina_Inlist *list)
181{
182 Eina_Inlist *prev = NULL;
183
184 for (; list; list = list->next)
185 {
186 list->prev = prev;
187 prev = list;
188 }
189
190 return prev;
191}
192
193static void
194_eina_inlist_sorted_state_compact(Eina_Inlist_Sorted_State *state)
195{
196 unsigned short i, j;
197
198 /* compress the jump table */
199 state->jump_div *= 2;
200 state->jump_limit /= 2;
201
202 for (i = 2, j = 1;
203 i < EINA_INLIST_JUMP_SIZE;
204 i += 2, j++)
205 state->jump_table[j] = state->jump_table[i];
206}
207
208/**
209 * @endcond
210 */
211
212
213/*============================================================================*
214* Global *
215*============================================================================*/
216
217/*============================================================================*
218* API *
219*============================================================================*/
220
221EAPI Eina_Inlist *
222eina_inlist_append(Eina_Inlist *list, Eina_Inlist *new_l)
223{
224 Eina_Inlist *l;
225
226 EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list);
227
228 new_l->next = NULL;
229 if (!list)
230 {
231 new_l->prev = NULL;
232 new_l->last = new_l;
233 return new_l;
234 }
235
236 if (list->last)
237 l = list->last;
238 else
239 for (l = list; (l) && (l->next); l = l->next)
240 ;
241
242 l->next = new_l;
243 new_l->prev = l;
244 list->last = new_l;
245 return list;
246}
247
248EAPI Eina_Inlist *
249eina_inlist_prepend(Eina_Inlist *list, Eina_Inlist *new_l)
250{
251 EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list);
252
253 new_l->prev = NULL;
254 if (!list)
255 {
256 new_l->next = NULL;
257 new_l->last = new_l;
258 return new_l;
259 }
260
261 new_l->next = list;
262 list->prev = new_l;
263 new_l->last = list->last;
264 list->last = NULL;
265 return new_l;
266}
267
268EAPI Eina_Inlist *
269eina_inlist_append_relative(Eina_Inlist *list,
270 Eina_Inlist *new_l,
271 Eina_Inlist *relative)
272{
273 EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list);
274
275 if (relative)
276 {
277 if (relative->next)
278 {
279 new_l->next = relative->next;
280 relative->next->prev = new_l;
281 }
282 else
283 new_l->next = NULL;
284
285 relative->next = new_l;
286 new_l->prev = relative;
287 if (!new_l->next)
288 list->last = new_l;
289
290 return list;
291 }
292
293 return eina_inlist_append(list, new_l);
294}
295
296EAPI Eina_Inlist *
297eina_inlist_prepend_relative(Eina_Inlist *list,
298 Eina_Inlist *new_l,
299 Eina_Inlist *relative)
300{
301 EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list);
302
303 if (relative)
304 {
305 new_l->prev = relative->prev;
306 new_l->next = relative;
307 relative->prev = new_l;
308 if (new_l->prev)
309 {
310 new_l->prev->next = new_l;
311 /* new_l->next could not be NULL, as it was set to 'relative' */
312 assert(new_l->next);
313 return list;
314 }
315 else
316 {
317 /* new_l->next could not be NULL, as it was set to 'relative' */
318 assert(new_l->next);
319
320 new_l->last = list->last;
321 list->last = NULL;
322 return new_l;
323 }
324 }
325
326 return eina_inlist_prepend(list, new_l);
327}
328
329EAPI Eina_Inlist *
330eina_inlist_remove(Eina_Inlist *list, Eina_Inlist *item)
331{
332 Eina_Inlist *return_l;
333
334 /* checkme */
335 EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL);
336 EINA_SAFETY_ON_NULL_RETURN_VAL(item, list);
337 if (EINA_UNLIKELY((item != list) && (!item->prev) && (!item->next)))
338 {
339 eina_error_set(EINA_ERROR_SAFETY_FAILED);
340 EINA_LOG_ERR("safety check failed: item %p does not appear to be part of an inlist!", item);
341 return list;
342 }
343
344 if (item->next)
345 item->next->prev = item->prev;
346
347 if (item->prev)
348 {
349 item->prev->next = item->next;
350 return_l = list;
351 }
352 else
353 {
354 return_l = item->next;
355 if (return_l)
356 return_l->last = list->last;
357 }
358
359 if (item == list->last)
360 list->last = item->prev;
361
362 item->next = NULL;
363 item->prev = NULL;
364 return return_l;
365}
366
367EAPI Eina_Inlist *
368eina_inlist_promote(Eina_Inlist *list, Eina_Inlist *item)
369{
370 EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL);
371 EINA_SAFETY_ON_NULL_RETURN_VAL(item, list);
372
373 if (item == list)
374 return list;
375
376 if (item->next)
377 item->next->prev = item->prev;
378
379 item->prev->next = item->next;
380
381 if (list->last == item)
382 list->last = item->prev;
383
384 item->next = list;
385 item->prev = NULL;
386 item->last = list->last;
387
388 list->prev = item;
389 list->last = NULL;
390
391 return item;
392}
393
394EAPI Eina_Inlist *
395eina_inlist_demote(Eina_Inlist *list, Eina_Inlist *item)
396{
397 Eina_Inlist *l;
398
399 EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL);
400 EINA_SAFETY_ON_NULL_RETURN_VAL(item, list);
401
402 if (list->last == item)
403 return list;
404
405 if (!list->last)
406 {
407 for (l = list; l->next; l = l->next)
408 ;
409 list->last = l;
410 }
411
412 l = list;
413 if (item->prev)
414 item->prev->next = item->next;
415 else
416 l = item->next;
417
418 item->next->prev = item->prev;
419
420 list->last->next = item;
421 item->prev = list->last;
422 item->next = NULL;
423
424 l->last = item;
425 return l;
426}
427
428EAPI Eina_Inlist *
429eina_inlist_find(Eina_Inlist *list, Eina_Inlist *item)
430{
431 Eina_Inlist *l;
432
433 for (l = list; l; l = l->next) {
434 if (l == item)
435 return item;
436 }
437 return NULL;
438}
439
440EAPI unsigned int
441eina_inlist_count(const Eina_Inlist *list)
442{
443 const Eina_Inlist *l;
444 unsigned int i = 0;
445
446 for (l = list; l; l = l->next)
447 i++;
448
449 return i;
450}
451
452EAPI int
453eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list)
454{
455 Eina_Inlist *ct = NULL;
456 int count = 0;
457 int jump_count = 1;
458
459 /*
460 * prepare a jump table to avoid doing unnecessary rewalk
461 * of the inlist as much as possible.
462 */
463 for (ct = list; ct; ct = ct->next, jump_count++, count++)
464 {
465 if (jump_count == state->jump_div)
466 {
467 if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
468 {
469 _eina_inlist_sorted_state_compact(state);
470 }
471
472 state->jump_table[state->jump_limit] = ct;
473 state->jump_limit++;
474 jump_count = 0;
475 }
476 }
477
478 state->inserted = count;
479 return count;
480}
481
482EAPI Eina_Inlist_Sorted_State *
483eina_inlist_sorted_state_new(void)
484{
485 Eina_Inlist_Sorted_State *r;
486
487 r = calloc(1, sizeof (Eina_Inlist_Sorted_State));
488 if (!r) return NULL;
489
490 r->jump_div = 1;
491
492 return r;
493}
494
495EAPI void
496eina_inlist_sorted_state_free(Eina_Inlist_Sorted_State *state)
497{
498 free(state);
499}
500
501static void
502_eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state,
503 unsigned short idx,
504 int offset)
505{
506 Eina_Inlist *last;
507 int jump_count;
508 int start;
509
510 state->inserted++;
511
512 if (offset != 0) idx++;
513 for (; idx < state->jump_limit; idx++)
514 {
515 state->jump_table[idx] = state->jump_table[idx]->prev;
516 }
517
518 start = state->jump_limit - 3;
519 if (start < 0)
520 start = 0;
521
522 last = state->jump_table[start];
523 start++;
524
525 /* Correctly rebuild end of list */
526 for (jump_count = 0; last->next != NULL; last = last->next, jump_count++)
527 {
528 if (jump_count == state->jump_div)
529 {
530 if (state->jump_limit == start)
531 {
532 if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
533 {
534 _eina_inlist_sorted_state_compact(state);
535 start = state->jump_limit - 1;
536 continue ;
537 }
538 else
539 {
540 state->jump_limit++;
541 }
542 }
543
544 state->jump_table[start++] = last;
545 jump_count = 0;
546 }
547 }
548}
549
550EAPI Eina_Inlist *
551eina_inlist_sorted_insert(Eina_Inlist *list,
552 Eina_Inlist *item,
553 Eina_Compare_Cb func)
554{
555 Eina_Inlist *ct = NULL;
556 Eina_Inlist_Sorted_State state;
557 int cmp = 0;
558 int inf, sup;
559 int cur = 0;
560 int count;
561
562 if (!list) return eina_inlist_append(NULL, item);
563
564 if (!list->next)
565 {
566 cmp = func(list, item);
567
568 if (cmp < 0)
569 return eina_inlist_append(list, item);
570 return eina_inlist_prepend(list, item);
571 }
572
573 state.jump_div = 1;
574 state.jump_limit = 0;
575 count = eina_inlist_sorted_state_init(&state, list);
576
577 /*
578 * now do a dychotomic search directly inside the jump_table.
579 */
580 inf = 0;
581 sup = state.jump_limit - 1;
582 cur = 0;
583 ct = state.jump_table[cur];
584 cmp = func(ct, item);
585
586 while (inf <= sup)
587 {
588 cur = inf + ((sup - inf) >> 1);
589 ct = state.jump_table[cur];
590
591 cmp = func(ct, item);
592 if (cmp == 0)
593 break ;
594 else if (cmp < 0)
595 inf = cur + 1;
596 else if (cmp > 0)
597 {
598 if (cur > 0)
599 sup = cur - 1;
600 else
601 break;
602 }
603 else
604 break;
605 }
606
607 /* If at the beginning of the table and cmp < 0,
608 * insert just after the head */
609 if (cur == 0 && cmp > 0)
610 return eina_inlist_prepend_relative(list, item, ct);
611
612 /* If at the end of the table and cmp >= 0,
613 * just append the item to the list */
614 if (cmp < 0 && ct == list->last)
615 return eina_inlist_append(list, item);
616
617 /*
618 * Now do a dychotomic search between two entries inside the jump_table
619 */
620 cur *= state.jump_div;
621 inf = cur - state.jump_div - 1;
622 sup = cur + state.jump_div + 1;
623
624 if (sup > count - 1) sup = count - 1;
625 if (inf < 0) inf = 0;
626
627 while (inf <= sup)
628 {
629 int tmp = cur;
630
631 cur = inf + ((sup - inf) >> 1);
632 if (tmp < cur)
633 for (; tmp != cur; tmp++, ct = ct->next);
634 else if (tmp > cur)
635 for (; tmp != cur; tmp--, ct = ct->prev);
636
637 cmp = func(ct, item);
638 if (cmp == 0)
639 break ;
640 else if (cmp < 0)
641 inf = cur + 1;
642 else if (cmp > 0)
643 {
644 if (cur > 0)
645 sup = cur - 1;
646 else
647 break;
648 }
649 else
650 break;
651 }
652
653 if (cmp <= 0)
654 return eina_inlist_append_relative(list, item, ct);
655 return eina_inlist_prepend_relative(list, item, ct);
656}
657
658EAPI Eina_Inlist *
659eina_inlist_sorted_state_insert(Eina_Inlist *list,
660 Eina_Inlist *item,
661 Eina_Compare_Cb func,
662 Eina_Inlist_Sorted_State *state)
663{
664 Eina_Inlist *ct = NULL;
665 int cmp = 0;
666 int inf, sup;
667 int cur = 0;
668 int count;
669 unsigned short head;
670 unsigned int offset;
671
672 if (!list)
673 {
674 state->inserted = 1;
675 state->jump_limit = 1;
676 state->jump_table[0] = item;
677 return eina_inlist_append(NULL, item);
678 }
679
680 if (!list->next)
681 {
682 cmp = func(list, item);
683
684 state->jump_limit = 2;
685 state->inserted = 2;
686
687 if (cmp < 0)
688 {
689 state->jump_table[1] = item;
690 return eina_inlist_append(list, item);
691 }
692 state->jump_table[1] = state->jump_table[0];
693 state->jump_table[0] = item;
694 return eina_inlist_prepend(list, item);
695 }
696
697 count = state->inserted;
698
699 /*
700 * now do a dychotomic search directly inside the jump_table.
701 */
702 inf = 0;
703 sup = state->jump_limit - 1;
704 cur = 0;
705 ct = state->jump_table[cur];
706 cmp = func(ct, item);
707
708 while (inf <= sup)
709 {
710 cur = inf + ((sup - inf) >> 1);
711 ct = state->jump_table[cur];
712
713 cmp = func(ct, item);
714 if (cmp == 0)
715 break ;
716 else if (cmp < 0)
717 inf = cur + 1;
718 else if (cmp > 0)
719 {
720 if (cur > 0)
721 sup = cur - 1;
722 else
723 break;
724 }
725 else
726 break;
727 }
728
729 /* If at the beginning of the table and cmp < 0,
730 * insert just after the head */
731 if (cur == 0 && cmp > 0)
732 {
733 ct = eina_inlist_prepend_relative(list, item, ct);
734 _eina_inlist_sorted_state_insert(state, 0, 0);
735 return ct;
736 }
737
738 /* If at the end of the table and cmp >= 0,
739 * just append the item to the list */
740 if (cmp < 0 && ct == list->last)
741 {
742 ct = eina_inlist_append(list, item);
743 _eina_inlist_sorted_state_insert(state, state->jump_limit - 1, 1);
744 return ct;
745 }
746
747 /*
748 * Now do a dychotomic search between two entries inside the jump_table
749 */
750 cur *= state->jump_div;
751 inf = cur - state->jump_div - 1;
752 sup = cur + state->jump_div + 1;
753
754 if (sup > count - 1) sup = count - 1;
755 if (inf < 0) inf = 0;
756
757 while (inf <= sup)
758 {
759 int tmp = cur;
760
761 cur = inf + ((sup - inf) >> 1);
762 if (tmp < cur)
763 for (; tmp != cur; tmp++, ct = ct->next);
764 else if (tmp > cur)
765 for (; tmp != cur; tmp--, ct = ct->prev);
766
767 cmp = func(ct, item);
768 if (cmp == 0)
769 break ;
770 else if (cmp < 0)
771 inf = cur + 1;
772 else if (cmp > 0)
773 {
774 if (cur > 0)
775 sup = cur - 1;
776 else
777 break;
778 }
779 else
780 break;
781 }
782
783 if (cmp <= 0)
784 {
785 cur++;
786
787 ct = eina_inlist_append_relative(list, item, ct);
788 }
789 else
790 {
791 ct = eina_inlist_prepend_relative(list, item, ct);
792 }
793
794 head = cur / state->jump_div;
795 offset = cur % state->jump_div;
796
797 _eina_inlist_sorted_state_insert(state, head, offset);
798 return ct;
799}
800
801EAPI Eina_Inlist *
802eina_inlist_sort(Eina_Inlist *head, Eina_Compare_Cb func)
803{
804 unsigned int i = 0;
805 unsigned int n = 0;
806 Eina_Inlist *tail = head;
807 Eina_Inlist *unsort = NULL;
808 Eina_Inlist *stack[EINA_INLIST_SORT_STACK_SIZE];
809
810 EINA_SAFETY_ON_NULL_RETURN_VAL(head, NULL);
811 EINA_SAFETY_ON_NULL_RETURN_VAL(func, head);
812
813 while (tail)
814 {
815 unsigned int idx, tmp;
816
817 Eina_Inlist *a = tail;
818 Eina_Inlist *b = tail->next;
819
820 if (!b)
821 {
822 stack[i++] = a;
823 break;
824 }
825
826 tail = b->next;
827
828 if (func(a, b) < 0)
829 ((stack[i++] = a)->next = b)->next = 0;
830 else
831 ((stack[i++] = b)->next = a)->next = 0;
832
833 tmp = n++;
834 for (idx = n ^ tmp; idx &= idx - 1; i--)
835 stack[i - 2] = eina_inlist_sort_merge(stack[i - 2], stack[i - 1], func);
836 }
837
838 while (i-- > 1)
839 stack[i - 1] = eina_inlist_sort_merge(stack[i - 1], stack[i], func);
840
841 head = stack[0];
842 tail = eina_inlist_sort_rebuild_prev(head);
843
844 if (unsort)
845 {
846 tail->next = unsort;
847 unsort->prev = tail;
848 }
849
850 head->last = tail;
851
852 return head;
853
854}
855
856EAPI Eina_Iterator *
857eina_inlist_iterator_new(const Eina_Inlist *list)
858{
859 Eina_Iterator_Inlist *it;
860
861 eina_error_set(0);
862 it = calloc(1, sizeof (Eina_Iterator_Inlist));
863 if (!it)
864 {
865 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
866 return NULL;
867 }
868
869 it->head = list;
870 it->current = list;
871
872 it->iterator.version = EINA_ITERATOR_VERSION;
873 it->iterator.next = FUNC_ITERATOR_NEXT(eina_inlist_iterator_next);
874 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
875 eina_inlist_iterator_get_container);
876 it->iterator.free = FUNC_ITERATOR_FREE(eina_inlist_iterator_free);
877
878 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
879
880 return &it->iterator;
881}
882
883EAPI Eina_Accessor *
884eina_inlist_accessor_new(const Eina_Inlist *list)
885{
886 Eina_Accessor_Inlist *ac;
887
888 eina_error_set(0);
889 ac = calloc(1, sizeof (Eina_Accessor_Inlist));
890 if (!ac)
891 {
892 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
893 return NULL;
894 }
895
896 ac->head = list;
897 ac->current = list;
898 ac->index = 0;
899
900 ac->accessor.version = EINA_ACCESSOR_VERSION;
901 ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_inlist_accessor_get_at);
902 ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
903 eina_inlist_accessor_get_container);
904 ac->accessor.free = FUNC_ACCESSOR_FREE(eina_inlist_accessor_free);
905
906 EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
907
908 return &ac->accessor;
909}
diff --git a/libraries/eina/src/lib/eina_iterator.c b/libraries/eina/src/lib/eina_iterator.c
new file mode 100644
index 0000000..0721066
--- /dev/null
+++ b/libraries/eina/src/lib/eina_iterator.c
@@ -0,0 +1,172 @@
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_iterator.h"
31
32/*============================================================================*
33* Local *
34*============================================================================*/
35
36/**
37 * @cond LOCAL
38 */
39
40static const char EINA_MAGIC_ITERATOR_STR[] = "Eina Iterator";
41
42#define EINA_MAGIC_CHECK_ITERATOR(d) \
43 do { \
44 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ITERATOR)) { \
45 EINA_MAGIC_FAIL(d, EINA_MAGIC_ITERATOR); } \
46 } while(0)
47
48/**
49 * @endcond
50 */
51
52
53/*============================================================================*
54* Global *
55*============================================================================*/
56
57/**
58 * @internal
59 * @brief Initialize the iterator module.
60 *
61 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
62 *
63 * This function sets up the iterator module of Eina. It is called by
64 * eina_init().
65 *
66 * @see eina_init()
67 */
68Eina_Bool
69eina_iterator_init(void)
70{
71 return eina_magic_string_set(EINA_MAGIC_ITERATOR, EINA_MAGIC_ITERATOR_STR);
72}
73
74/**
75 * @internal
76 * @brief Shut down the iterator module.
77 *
78 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
79 *
80 * This function shuts down the iterator module set up by
81 * eina_iterator_init(). It is called by eina_shutdown().
82 *
83 * @see eina_shutdown()
84 */
85Eina_Bool
86eina_iterator_shutdown(void)
87{
88 return EINA_TRUE;
89}
90
91/*============================================================================*
92* API *
93*============================================================================*/
94
95EAPI void
96eina_iterator_free(Eina_Iterator *iterator)
97{
98 EINA_MAGIC_CHECK_ITERATOR(iterator);
99 EINA_SAFETY_ON_NULL_RETURN(iterator);
100 EINA_SAFETY_ON_NULL_RETURN(iterator->free);
101 iterator->free(iterator);
102}
103
104EAPI void *
105eina_iterator_container_get(Eina_Iterator *iterator)
106{
107 EINA_MAGIC_CHECK_ITERATOR(iterator);
108 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, NULL);
109 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator->get_container, NULL);
110 return iterator->get_container(iterator);
111}
112
113EAPI Eina_Bool
114eina_iterator_next(Eina_Iterator *iterator, void **data)
115{
116 if (!iterator)
117 return EINA_FALSE;
118
119 EINA_MAGIC_CHECK_ITERATOR(iterator);
120 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE);
121 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator->next, EINA_FALSE);
122 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
123 return iterator->next(iterator, data);
124}
125
126EAPI void
127eina_iterator_foreach(Eina_Iterator *iterator,
128 Eina_Each_Cb cb,
129 const void *fdata)
130{
131 const void *container;
132 void *data;
133
134 EINA_MAGIC_CHECK_ITERATOR(iterator);
135 EINA_SAFETY_ON_NULL_RETURN(iterator);
136 EINA_SAFETY_ON_NULL_RETURN(iterator->get_container);
137 EINA_SAFETY_ON_NULL_RETURN(iterator->next);
138 EINA_SAFETY_ON_NULL_RETURN(cb);
139
140 if (!eina_iterator_lock(iterator)) return ;
141
142 container = iterator->get_container(iterator);
143 while (iterator->next(iterator, &data) == EINA_TRUE) {
144 if (cb(container, data, (void *)fdata) != EINA_TRUE)
145 goto on_exit;
146 }
147
148 on_exit:
149 (void) eina_iterator_unlock(iterator);
150}
151
152EAPI Eina_Bool
153eina_iterator_lock(Eina_Iterator *iterator)
154{
155 EINA_MAGIC_CHECK_ITERATOR(iterator);
156 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE);
157
158 if (iterator->lock)
159 return iterator->lock(iterator);
160 return EINA_TRUE;
161}
162
163EAPI Eina_Bool
164eina_iterator_unlock(Eina_Iterator *iterator)
165{
166 EINA_MAGIC_CHECK_ITERATOR(iterator);
167 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE);
168
169 if (iterator->unlock)
170 return iterator->unlock(iterator);
171 return EINA_TRUE;
172}
diff --git a/libraries/eina/src/lib/eina_lalloc.c b/libraries/eina/src/lib/eina_lalloc.c
new file mode 100644
index 0000000..b1e62b7
--- /dev/null
+++ b/libraries/eina/src/lib/eina_lalloc.c
@@ -0,0 +1,158 @@
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#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_lalloc.h"
31
32/*============================================================================*
33* Local *
34*============================================================================*/
35
36/**
37 * @cond LOCAL
38 */
39
40struct _Eina_Lalloc
41{
42 void *data;
43 int num_allocated;
44 int num_elements;
45 int acc;
46 Eina_Lalloc_Alloc alloc_cb;
47 Eina_Lalloc_Free free_cb;
48};
49
50/**
51 * @endcond
52 */
53
54/*============================================================================*
55* Global *
56*============================================================================*/
57
58/*============================================================================*
59* API *
60*============================================================================*/
61
62/**
63 * @addtogroup Eina_Lalloc_Group Lazy allocator
64 *
65 * @{
66 */
67
68EAPI Eina_Lalloc *eina_lalloc_new(void *data,
69 Eina_Lalloc_Alloc alloc_cb,
70 Eina_Lalloc_Free free_cb,
71 int num_init)
72{
73 Eina_Lalloc *a;
74
75 EINA_SAFETY_ON_NULL_RETURN_VAL(alloc_cb, NULL);
76 EINA_SAFETY_ON_NULL_RETURN_VAL(free_cb, NULL);
77
78 a = calloc(1, sizeof(Eina_Lalloc));
79 a->data = data;
80 a->alloc_cb = alloc_cb;
81 a->free_cb = free_cb;
82 if (num_init > 0)
83 {
84 a->num_allocated = num_init;
85 a->alloc_cb(a->data, a->num_allocated);
86 }
87
88 return a;
89}
90
91EAPI void eina_lalloc_free(Eina_Lalloc *a)
92{
93 EINA_SAFETY_ON_NULL_RETURN(a);
94 EINA_SAFETY_ON_NULL_RETURN(a->free_cb);
95 a->free_cb(a->data);
96 free(a);
97}
98
99EAPI Eina_Bool eina_lalloc_element_add(Eina_Lalloc *a)
100{
101 EINA_SAFETY_ON_NULL_RETURN_VAL(a, EINA_FALSE);
102 EINA_SAFETY_ON_NULL_RETURN_VAL(a->alloc_cb, EINA_FALSE);
103
104 if (a->num_elements == a->num_allocated)
105 {
106 if (a->alloc_cb(a->data, (1 << a->acc)) == EINA_TRUE)
107 {
108 a->num_allocated = (1 << a->acc);
109 a->acc++;
110 }
111 else
112 return EINA_FALSE;
113 }
114
115 a->num_elements++;
116
117 return EINA_TRUE;
118}
119
120EAPI Eina_Bool eina_lalloc_elements_add(Eina_Lalloc *a, int num)
121{
122 int tmp;
123
124 EINA_SAFETY_ON_NULL_RETURN_VAL(a, EINA_FALSE);
125 EINA_SAFETY_ON_NULL_RETURN_VAL(a->alloc_cb, EINA_FALSE);
126
127 tmp = a->num_elements + num;
128 if (tmp > a->num_allocated)
129 {
130 int allocated;
131 int acc;
132
133 allocated = a->num_allocated;
134 acc = a->acc;
135
136 while (tmp > allocated)
137 {
138 allocated = (1 << acc);
139 acc++;
140 }
141
142 if (a->alloc_cb(a->data, allocated) == EINA_TRUE)
143 {
144 a->num_allocated = allocated;
145 a->acc = acc;
146 }
147 else
148 return EINA_FALSE;
149 }
150
151 a->num_elements += num;
152
153 return EINA_TRUE;
154}
155
156/**
157 * @}
158 */
diff --git a/libraries/eina/src/lib/eina_list.c b/libraries/eina/src/lib/eina_list.c
new file mode 100644
index 0000000..d45cffd
--- /dev/null
+++ b/libraries/eina/src/lib/eina_list.c
@@ -0,0 +1,1490 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck,
3 * Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga,
4 * Corey Donohoe, Arnaud de Turckheim, Alexandre Becoulet
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library;
18 * if not, see <http://www.gnu.org/licenses/>.
19 *
20 * This file incorporates work covered by the following copyright and
21 * permission notice:
22 *
23 * Copyright (C) 2004 ncn
24 * Copyright (C) 2006 Sebastian Dransfeld
25 * Copyright (C) 2007 Christopher Michael
26 *
27 * Permission is hereby granted, free of charge, to any person obtaining a copy
28 * of this software and associated documentation files (the "Software"), to
29 * deal in the Software without restriction, including without limitation the
30 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
31 * sell copies of the Software, and to permit persons to whom the Software is
32 * furnished to do so, subject to the following conditions:
33
34 * The above copyright notice and this permission notice shall be included in
35 * all copies of the Software and its Copyright notices. In addition publicly
36 * documented acknowledgment must be given that this software has been used if no
37 * source code of this software is made available publicly. This includes
38 * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
39 * documents or any documentation provided with any product containing this
40 * software. This License does not apply to any software that links to the
41 * libraries provided by this software (statically or dynamically), but only to
42 * the software provided.
43
44 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
45 * and it's intent.
46
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
50 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
51 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53 */
54
55
56#ifdef HAVE_CONFIG_H
57# include "config.h"
58#endif
59
60#include <stdlib.h>
61#include <stdio.h>
62#include <string.h>
63
64#ifdef HAVE_EVIL
65# include <Evil.h>
66#endif
67
68#include "eina_config.h"
69#include "eina_private.h"
70#include "eina_error.h"
71#include "eina_log.h"
72#include "eina_mempool.h"
73
74/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
75#include "eina_safety_checks.h"
76#include "eina_list.h"
77
78
79/*============================================================================*
80 * Local *
81 *============================================================================*/
82
83/**
84 * @cond LOCAL
85 */
86
87static const char EINA_MAGIC_LIST_STR[] = "Eina List";
88static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator";
89static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor";
90static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting";
91
92
93#define EINA_MAGIC_CHECK_LIST(d, ...) \
94 do { \
95 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \
96 { \
97 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \
98 return __VA_ARGS__; \
99 } \
100 } while(0)
101
102#define EINA_MAGIC_CHECK_LIST_ITERATOR(d, ...) \
103 do { \
104 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ITERATOR)) \
105 { \
106 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ITERATOR); \
107 return __VA_ARGS__; \
108 } \
109 } while(0)
110
111#define EINA_MAGIC_CHECK_LIST_ACCESSOR(d, ...) \
112 do { \
113 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCESSOR)) \
114 { \
115 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCESSOR); \
116 return __VA_ARGS__; \
117 } \
118 } while(0)
119
120#define EINA_MAGIC_CHECK_LIST_ACCOUNTING(d) \
121 do { \
122 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCOUNTING)) \
123 { \
124 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCOUNTING); \
125 return; \
126 } \
127 } while(0)
128
129#define EINA_LIST_SORT_STACK_SIZE 32
130
131typedef struct _Eina_Iterator_List Eina_Iterator_List;
132typedef struct _Eina_Accessor_List Eina_Accessor_List;
133
134struct _Eina_Iterator_List
135{
136 Eina_Iterator iterator;
137
138 const Eina_List *head;
139 const Eina_List *current;
140
141 EINA_MAGIC
142};
143
144struct _Eina_Accessor_List
145{
146 Eina_Accessor accessor;
147
148 const Eina_List *head;
149 const Eina_List *current;
150
151 unsigned int index;
152
153 EINA_MAGIC
154};
155
156static Eina_Mempool *_eina_list_mp = NULL;
157static Eina_Mempool *_eina_list_accounting_mp = NULL;
158static int _eina_list_log_dom = -1;
159
160#ifdef ERR
161#undef ERR
162#endif
163#define ERR(...) EINA_LOG_DOM_ERR(_eina_list_log_dom, __VA_ARGS__)
164
165#ifdef DBG
166#undef DBG
167#endif
168#define DBG(...) EINA_LOG_DOM_DBG(_eina_list_log_dom, __VA_ARGS__)
169
170static inline Eina_List_Accounting *
171_eina_list_mempool_accounting_new(__UNUSED__ Eina_List *list)
172{
173 Eina_List_Accounting *tmp;
174
175 tmp =
176 eina_mempool_malloc(_eina_list_accounting_mp,
177 sizeof (Eina_List_Accounting));
178 if (!tmp)
179 return NULL;
180
181 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST_ACCOUNTING);
182
183 return tmp;
184}
185static inline void
186_eina_list_mempool_accounting_free(Eina_List_Accounting *accounting)
187{
188 EINA_MAGIC_CHECK_LIST_ACCOUNTING(accounting);
189
190 EINA_MAGIC_SET(accounting, EINA_MAGIC_NONE);
191 eina_mempool_free(_eina_list_accounting_mp, accounting);
192}
193
194static inline Eina_List *
195_eina_list_mempool_list_new(__UNUSED__ Eina_List *list)
196{
197 Eina_List *tmp;
198
199 tmp = eina_mempool_malloc(_eina_list_mp, sizeof (Eina_List));
200 if (!tmp)
201 return NULL;
202
203 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST);
204
205 return tmp;
206}
207static inline void
208_eina_list_mempool_list_free(Eina_List *list)
209{
210 EINA_MAGIC_CHECK_LIST(list);
211
212 list->accounting->count--;
213 if (list->accounting->count == 0)
214 _eina_list_mempool_accounting_free(list->accounting);
215
216 EINA_MAGIC_SET(list, EINA_MAGIC_NONE);
217 eina_mempool_free(_eina_list_mp, list);
218}
219
220static Eina_List *
221_eina_list_setup_accounting(Eina_List *list)
222{
223 EINA_MAGIC_CHECK_LIST(list, NULL);
224
225 list->accounting = _eina_list_mempool_accounting_new(list);
226 if (!list->accounting)
227 goto on_error;
228
229 list->accounting->last = list;
230 list->accounting->count = 1;
231
232 return list;
233
234on_error:
235 _eina_list_mempool_list_free(list);
236 return NULL;
237}
238
239static inline void
240_eina_list_update_accounting(Eina_List *list, Eina_List *new_list)
241{
242 EINA_MAGIC_CHECK_LIST(list);
243 EINA_MAGIC_CHECK_LIST(new_list);
244
245 list->accounting->count++;
246 new_list->accounting = list->accounting;
247}
248
249#if 0
250static Eina_Mempool2 _eina_list_mempool =
251{
252 sizeof(Eina_List),
253 320,
254 0, NULL, NULL
255};
256static Eina_Mempool2 _eina_list_accounting_mempool =
257{
258 sizeof(Eina_List_Accounting),
259 80,
260 0, NULL, NULL
261};
262#endif
263
264static Eina_Bool
265eina_list_iterator_next(Eina_Iterator_List *it, void **data)
266{
267 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
268
269 if (!it->current)
270 return EINA_FALSE;
271
272 *data = eina_list_data_get(it->current);
273
274 it->current = eina_list_next(it->current);
275
276 return EINA_TRUE;
277}
278
279static Eina_Bool
280eina_list_iterator_prev(Eina_Iterator_List *it, void **data)
281{
282 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
283
284 if (!it->current)
285 return EINA_FALSE;
286
287 *data = eina_list_data_get(it->current);
288
289 it->current = eina_list_prev(it->current);
290
291 return EINA_TRUE;
292}
293
294static Eina_List *
295eina_list_iterator_get_container(Eina_Iterator_List *it)
296{
297 EINA_MAGIC_CHECK_LIST_ITERATOR(it, NULL);
298
299 return (Eina_List *)it->head;
300}
301
302static void
303eina_list_iterator_free(Eina_Iterator_List *it)
304{
305 EINA_MAGIC_CHECK_LIST_ITERATOR(it);
306
307 MAGIC_FREE(it);
308}
309
310static Eina_Bool
311eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int idx, void **data)
312{
313 const Eina_List *over;
314 unsigned int middle;
315 unsigned int i;
316
317 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, EINA_FALSE);
318
319 if (idx >= eina_list_count(it->head))
320 return EINA_FALSE;
321
322 if (it->index == idx)
323 over = it->current;
324 else if (idx > it->index)
325 {
326 /* After current position. */
327 middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index;
328
329 if (idx > middle)
330 /* Go backward from the end. */
331 for (i = eina_list_count(it->head) - 1,
332 over = eina_list_last(it->head);
333 i > idx && over;
334 --i, over = eina_list_prev(over))
335 ;
336 else
337 /* Go forward from current. */
338 for (i = it->index, over = it->current;
339 i < idx && over;
340 ++i, over = eina_list_next(over))
341 ;
342 }
343 else
344 {
345 /* Before current position. */
346 middle = it->index >> 1;
347
348 if (idx > middle)
349 /* Go backward from current. */
350 for (i = it->index, over = it->current;
351 i > idx && over;
352 --i, over = eina_list_prev(over))
353 ;
354 else
355 /* Go forward from start. */
356 for (i = 0, over = it->head;
357 i < idx && over;
358 ++i, over = eina_list_next(over))
359 ;
360 }
361
362 if (!over)
363 return EINA_FALSE;
364
365 it->current = over;
366 it->index = idx;
367
368 *data = eina_list_data_get(it->current);
369 return EINA_TRUE;
370}
371
372static Eina_List *
373eina_list_accessor_get_container(Eina_Accessor_List *it)
374{
375 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, NULL);
376
377 return (Eina_List *)it->head;
378}
379
380static void
381eina_list_accessor_free(Eina_Accessor_List *it)
382{
383 EINA_MAGIC_CHECK_LIST_ACCESSOR(it);
384
385 MAGIC_FREE(it);
386}
387
388static Eina_List *
389eina_list_sort_rebuild_prev(Eina_List *list)
390{
391 Eina_List *prev = NULL;
392
393 EINA_MAGIC_CHECK_LIST(list, NULL);
394
395 for (; list; list = list->next)
396 {
397 list->prev = prev;
398 prev = list;
399 }
400
401 return prev;
402}
403
404static Eina_List *
405eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
406{
407 Eina_List *first, *last;
408
409 if (func(a->data, b->data) < 0)
410 a = (last = first = a)->next;
411 else
412 b = (last = first = b)->next;
413
414 while (a && b)
415 if (func(a->data, b->data) < 0)
416 a = (last = last->next = a)->next;
417 else
418 b = (last = last->next = b)->next;
419
420 last->next = a ? a : b;
421
422 return first;
423}
424
425/**
426 * @endcond
427 */
428
429/*============================================================================*
430 * Global *
431 *============================================================================*/
432
433/**
434 * @internal
435 * @brief Initialize the list module.
436 *
437 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
438 *
439 * This function sets up the list module of Eina. It is called by
440 * eina_init().
441 *
442 * This function creates mempool to speed up list node and accounting
443 * management, using EINA_MEMPOOL environment variable if it is set to
444 * choose the memory pool type to use.
445 *
446 * @see eina_init()
447 */
448Eina_Bool
449eina_list_init(void)
450{
451 const char *choice, *tmp;
452
453 _eina_list_log_dom = eina_log_domain_register("eina_list",
454 EINA_LOG_COLOR_DEFAULT);
455 if (_eina_list_log_dom < 0)
456 {
457 EINA_LOG_ERR("Could not register log domain: eina_list");
458 return EINA_FALSE;
459 }
460
461#ifdef EINA_DEFAULT_MEMPOOL
462 choice = "pass_through";
463#else
464 choice = "chained_mempool";
465#endif
466 tmp = getenv("EINA_MEMPOOL");
467 if (tmp && tmp[0])
468 choice = tmp;
469
470 _eina_list_mp = eina_mempool_add
471 (choice, "list", NULL, sizeof(Eina_List), 320);
472 if (!_eina_list_mp)
473 {
474 ERR("ERROR: Mempool for list cannot be allocated in list init.");
475 goto on_init_fail;
476 }
477
478 _eina_list_accounting_mp = eina_mempool_add
479 (choice, "list_accounting", NULL, sizeof(Eina_List_Accounting), 80);
480 if (!_eina_list_accounting_mp)
481 {
482 ERR(
483 "ERROR: Mempool for list accounting cannot be allocated in list init.");
484 eina_mempool_del(_eina_list_mp);
485 goto on_init_fail;
486 }
487
488#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
489 EMS(EINA_MAGIC_LIST);
490 EMS(EINA_MAGIC_LIST_ITERATOR);
491 EMS(EINA_MAGIC_LIST_ACCESSOR);
492 EMS(EINA_MAGIC_LIST_ACCOUNTING);
493#undef EMS
494
495 return EINA_TRUE;
496
497on_init_fail:
498 eina_log_domain_unregister(_eina_list_log_dom);
499 _eina_list_log_dom = -1;
500 return EINA_FALSE;
501}
502
503/**
504 * @internal
505 * @brief Shut down the list module.
506 *
507 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
508 *
509 * This function shuts down the list module set up by
510 * eina_list_init(). It is called by eina_shutdown().
511 *
512 * @see eina_shutdown()
513 */
514Eina_Bool
515eina_list_shutdown(void)
516{
517 eina_mempool_del(_eina_list_accounting_mp);
518 eina_mempool_del(_eina_list_mp);
519
520 eina_log_domain_unregister(_eina_list_log_dom);
521 _eina_list_log_dom = -1;
522 return EINA_TRUE;
523}
524
525/*============================================================================*
526 * API *
527 *============================================================================*/
528
529EAPI Eina_List *
530eina_list_append(Eina_List *list, const void *data)
531{
532 Eina_List *l, *new_l;
533
534 eina_error_set(0);
535 new_l = _eina_list_mempool_list_new(list);
536 if (!new_l)
537 return list;
538
539 new_l->next = NULL;
540 new_l->data = (void *)data;
541 if (!list)
542 {
543 new_l->prev = NULL;
544 return _eina_list_setup_accounting(new_l);
545 }
546
547 EINA_MAGIC_CHECK_LIST(list, NULL);
548
549 l = list->accounting->last;
550 list->accounting->last = new_l;
551
552 l->next = new_l;
553 new_l->prev = l;
554
555 _eina_list_update_accounting(list, new_l);
556 return list;
557}
558
559EAPI Eina_List *
560eina_list_prepend(Eina_List *list, const void *data)
561{
562 Eina_List *new_l;
563
564 eina_error_set(0);
565 new_l = _eina_list_mempool_list_new(list);
566 if (!new_l)
567 return list;
568
569 new_l->prev = NULL;
570 new_l->next = list;
571 new_l->data = (void *)data;
572
573 if (!list)
574 return _eina_list_setup_accounting(new_l);
575
576 EINA_MAGIC_CHECK_LIST(list, NULL);
577
578 list->prev = new_l;
579
580 _eina_list_update_accounting(list, new_l);
581
582 return new_l;
583}
584
585EAPI Eina_List *
586eina_list_append_relative(Eina_List *list,
587 const void *data,
588 const void *relative)
589{
590 Eina_List *l;
591 void *list_data;
592
593 if (list)
594 EINA_MAGIC_CHECK_LIST(list, NULL);
595
596 EINA_LIST_FOREACH(list, l, list_data)
597 {
598 if (list_data == relative)
599 return eina_list_append_relative_list(list, data, l);
600 }
601
602 return eina_list_append(list, data);
603}
604
605EAPI Eina_List *
606eina_list_append_relative_list(Eina_List *list,
607 const void *data,
608 Eina_List *relative)
609{
610 Eina_List *new_l;
611
612 if ((!list) || (!relative))
613 return eina_list_append(list, data);
614
615 eina_error_set(0);
616 new_l = _eina_list_mempool_list_new(list);
617 if (!new_l)
618 return list;
619
620 EINA_MAGIC_CHECK_LIST(relative, NULL);
621 new_l->next = relative->next;
622 new_l->data = (void *)data;
623
624 if (relative->next)
625 relative->next->prev = new_l;
626
627 relative->next = new_l;
628 new_l->prev = relative;
629
630 _eina_list_update_accounting(list, new_l);
631
632 if (!new_l->next)
633 new_l->accounting->last = new_l;
634
635 return list;
636}
637
638EAPI Eina_List *
639eina_list_prepend_relative(Eina_List *list,
640 const void *data,
641 const void *relative)
642{
643 Eina_List *l;
644 void *list_data;
645
646 if (list)
647 EINA_MAGIC_CHECK_LIST(list, NULL);
648
649 EINA_LIST_FOREACH(list, l, list_data)
650 {
651 if (list_data == relative)
652 return eina_list_prepend_relative_list(list, data, l);
653 }
654 return eina_list_prepend(list, data);
655}
656
657EAPI Eina_List *
658eina_list_prepend_relative_list(Eina_List *list,
659 const void *data,
660 Eina_List *relative)
661{
662 Eina_List *new_l;
663
664 if ((!list) || (!relative))
665 return eina_list_prepend(list, data);
666
667 eina_error_set(0);
668 new_l = _eina_list_mempool_list_new(list);
669 if (!new_l)
670 return list;
671
672 EINA_MAGIC_CHECK_LIST(relative, NULL);
673
674 new_l->prev = relative->prev;
675 new_l->next = relative;
676 new_l->data = (void *)data;
677
678 if (relative->prev)
679 relative->prev->next = new_l;
680
681 relative->prev = new_l;
682
683 _eina_list_update_accounting(list, new_l);
684
685 if (new_l->prev)
686 return list;
687
688 return new_l;
689}
690
691EAPI Eina_List *
692eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data)
693{
694 Eina_List *lnear;
695 int cmp;
696
697 if (!list)
698 return eina_list_append(NULL, data);
699
700 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
701 if (cmp < 0)
702 return eina_list_append_relative_list(list, data, lnear);
703 else
704 return eina_list_prepend_relative_list(list, data, lnear);
705}
706
707EAPI Eina_List *
708eina_list_remove(Eina_List *list, const void *data)
709{
710 Eina_List *l;
711
712 if (list)
713 EINA_MAGIC_CHECK_LIST(list, NULL);
714
715 l = eina_list_data_find_list(list, data);
716 return eina_list_remove_list(list, l);
717}
718
719EAPI Eina_List *
720eina_list_remove_list(Eina_List *list, Eina_List *remove_list)
721{
722 Eina_List *return_l;
723
724 if (!list)
725 return NULL;
726
727 if (!remove_list)
728 return list;
729
730 EINA_MAGIC_CHECK_LIST(remove_list, NULL);
731
732 if (remove_list->next)
733 remove_list->next->prev = remove_list->prev;
734
735 if (remove_list->prev)
736 {
737 remove_list->prev->next = remove_list->next;
738 return_l = list;
739 }
740 else
741 return_l = remove_list->next;
742
743 if (remove_list == remove_list->accounting->last)
744 {
745 EINA_MAGIC_CHECK_LIST(list, NULL);
746 list->accounting->last = remove_list->prev;
747 }
748
749 _eina_list_mempool_list_free(remove_list);
750 return return_l;
751}
752
753EAPI Eina_List *
754eina_list_free(Eina_List *list)
755{
756 Eina_List *l, *free_l;
757
758 if (!list)
759 return NULL;
760
761 EINA_MAGIC_CHECK_LIST(list, NULL);
762
763 for (l = list; l; )
764 {
765 free_l = l;
766 l = l->next;
767
768 _eina_list_mempool_list_free(free_l);
769 }
770
771 return NULL;
772}
773
774EAPI Eina_List *
775eina_list_promote_list(Eina_List *list, Eina_List *move_list)
776{
777 if (!list)
778 return NULL;
779
780 if (!move_list)
781 {
782 return list; /* Promoting head to be head. */
783
784 }
785
786 if (move_list == list)
787 return list;
788
789 if (move_list->next == list)
790 return move_list;
791
792 EINA_MAGIC_CHECK_LIST(list, NULL);
793 EINA_MAGIC_CHECK_LIST(move_list, NULL);
794
795 /* Remove the promoted item from the list. */
796 if (!move_list->prev)
797 move_list->next->prev = NULL;
798 else
799 {
800 move_list->prev->next = move_list->next;
801 if (move_list == list->accounting->last)
802 list->accounting->last = move_list->prev;
803 else
804 move_list->next->prev = move_list->prev;
805 }
806
807 /* Add the promoted item in the list. */
808 move_list->next = list;
809 move_list->prev = list->prev;
810 list->prev = move_list;
811 if (move_list->prev)
812 move_list->prev->next = move_list;
813
814 return move_list;
815}
816
817EAPI Eina_List *
818eina_list_demote_list(Eina_List *list, Eina_List *move_list)
819{
820 if (!list)
821 return NULL;
822
823 if (!move_list)
824 {
825 return list; /* Demoting tail to be tail. */
826
827 }
828
829 if (move_list == list->accounting->last)
830 return list;
831
832 EINA_MAGIC_CHECK_LIST(list, NULL);
833 EINA_MAGIC_CHECK_LIST(move_list, NULL);
834
835 /* Update pointer list if necessary. */
836 if (list == move_list)
837 {
838 list = move_list->next; /* Remove the demoted item from the list. */
839
840 }
841
842 if (move_list->prev)
843 move_list->prev->next = move_list->next;
844
845 move_list->next->prev = move_list->prev;
846 /* Add the demoted item in the list. */
847 move_list->prev = list->accounting->last;
848 move_list->prev->next = move_list;
849 move_list->next = NULL;
850 list->accounting->last = move_list;
851
852 return list;
853}
854
855EAPI void *
856eina_list_data_find(const Eina_List *list, const void *data)
857{
858 if (eina_list_data_find_list(list, data))
859 return (void *)data;
860
861 return NULL;
862}
863
864EAPI Eina_Bool
865eina_list_move(Eina_List **to, Eina_List **from, void *data)
866{
867 Eina_List *l;
868
869 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
870 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
871 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
872
873 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
874 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
875
876 l = eina_list_data_find_list(*from, data);
877 EINA_SAFETY_ON_NULL_RETURN_VAL(l, EINA_FALSE);
878
879 *to = eina_list_append(*to, data);
880 *from = eina_list_remove_list(*from, l);
881 return EINA_TRUE;
882}
883
884EAPI Eina_Bool
885eina_list_move_list(Eina_List **to, Eina_List **from, Eina_List *data)
886{
887 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
888 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
889
890 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
891 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
892 EINA_MAGIC_CHECK_LIST(data, EINA_FALSE);
893
894 *to = eina_list_append(*to, data->data);
895 *from = eina_list_remove_list(*from, data);
896 return EINA_TRUE;
897}
898
899EAPI Eina_List *
900eina_list_data_find_list(const Eina_List *list, const void *data)
901{
902 const Eina_List *l;
903 void *list_data;
904
905 if (list)
906 EINA_MAGIC_CHECK_LIST(list, NULL);
907
908 EINA_LIST_FOREACH(list, l, list_data)
909 {
910 if (list_data == data)
911 return (Eina_List *)l;
912 }
913
914 return NULL;
915}
916
917EAPI void *
918eina_list_nth(const Eina_List *list, unsigned int n)
919{
920 Eina_List *l;
921
922 l = eina_list_nth_list(list, n);
923 return l ? l->data : NULL;
924}
925
926EAPI Eina_List *
927eina_list_nth_list(const Eina_List *list, unsigned int n)
928{
929 const Eina_List *l;
930 unsigned int i;
931
932 if (list)
933 EINA_MAGIC_CHECK_LIST(list, NULL);
934
935 /* check for non-existing nodes */
936 if ((!list) || (n > (list->accounting->count - 1)))
937 return NULL;
938
939 /* if the node is in the 2nd half of the list, search from the end
940 * else, search from the beginning.
941 */
942 if (n > (list->accounting->count / 2))
943 for (i = list->accounting->count - 1,
944 l = list->accounting->last;
945 l;
946 l = l->prev, i--)
947 {
948 if (i == n)
949 return (Eina_List *)l;
950 }
951 else
952 for (i = 0, l = list; l; l = l->next, i++)
953 {
954 if (i == n)
955 return (Eina_List *)l;
956 }
957
958 abort();
959}
960
961EAPI Eina_List *
962eina_list_reverse(Eina_List *list)
963{
964 Eina_List *l1, *l2;
965
966 if (!list)
967 return NULL;
968
969 EINA_MAGIC_CHECK_LIST(list, NULL);
970
971 l1 = list;
972 l2 = list->accounting->last;
973 while (l1 != l2)
974 {
975 void *data;
976
977 data = l1->data;
978 l1->data = l2->data;
979 l2->data = data;
980 l1 = l1->next;
981 if (l1 == l2)
982 break;
983
984 l2 = l2->prev;
985 }
986
987 return list;
988}
989
990EAPI Eina_List *
991eina_list_reverse_clone(const Eina_List *list)
992{
993 const Eina_List *l;
994 Eina_List *lclone;
995 void *data;
996
997 if (!list)
998 return NULL;
999
1000 EINA_MAGIC_CHECK_LIST(list, NULL);
1001
1002 lclone = NULL;
1003 EINA_LIST_FOREACH(list, l, data)
1004 lclone = eina_list_prepend(lclone, data);
1005
1006 return lclone;
1007}
1008
1009EAPI Eina_List *
1010eina_list_clone(const Eina_List *list)
1011{
1012 const Eina_List *l;
1013 Eina_List *lclone;
1014 void *data;
1015
1016 if (!list)
1017 return NULL;
1018
1019 EINA_MAGIC_CHECK_LIST(list, NULL);
1020
1021 lclone = NULL;
1022 EINA_LIST_FOREACH(list, l, data)
1023 lclone = eina_list_append(lclone, data);
1024
1025 return lclone;
1026}
1027
1028EAPI Eina_List *
1029eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func)
1030{
1031 unsigned int i = 0;
1032 unsigned int n = 0;
1033 Eina_List *tail = list;
1034 Eina_List *unsort = NULL;
1035 Eina_List *stack[EINA_LIST_SORT_STACK_SIZE];
1036
1037 EINA_SAFETY_ON_NULL_RETURN_VAL(func, list);
1038 if (!list)
1039 return NULL;
1040
1041 EINA_MAGIC_CHECK_LIST(list, NULL);
1042
1043 /* if the caller specified an invalid size, sort the whole list */
1044 if ((size == 0) ||
1045 (size > list->accounting->count))
1046 size = list->accounting->count;
1047
1048 if (size != list->accounting->count)
1049 {
1050 unsort = eina_list_nth_list(list, size);
1051 if (unsort)
1052 unsort->prev->next = NULL;
1053 }
1054
1055 while (tail)
1056 {
1057 unsigned int idx, tmp;
1058
1059 Eina_List *a = tail;
1060 Eina_List *b = tail->next;
1061
1062 if (!b)
1063 {
1064 stack[i++] = a;
1065 break;
1066 }
1067
1068 tail = b->next;
1069
1070 if (func(a->data, b->data) < 0)
1071 ((stack[i++] = a)->next = b)->next = 0;
1072 else
1073 ((stack[i++] = b)->next = a)->next = 0;
1074
1075 tmp = n++;
1076 for (idx = n ^ tmp; idx &= idx - 1; i--)
1077 stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
1078 }
1079
1080 while (i-- > 1)
1081 stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
1082
1083 list = stack[0];
1084 tail = eina_list_sort_rebuild_prev(list);
1085
1086 if (unsort)
1087 {
1088 tail->next = unsort;
1089 unsort->prev = tail;
1090 }
1091 else
1092 list->accounting->last = tail;
1093
1094 return list;
1095}
1096
1097EAPI Eina_List *
1098eina_list_merge(Eina_List *left, Eina_List *right)
1099{
1100 unsigned int n_left, n_right;
1101
1102 if (!left)
1103 return right;
1104
1105 if (!right)
1106 return left;
1107
1108 left->accounting->last->next = right;
1109 right->prev = left->accounting->last;
1110
1111 n_left = left->accounting->count;
1112 n_right = right->accounting->count;
1113
1114 if (n_left >= n_right)
1115 {
1116 Eina_List *itr = right;
1117 left->accounting->last = right->accounting->last;
1118 left->accounting->count += n_right;
1119
1120 _eina_list_mempool_accounting_free(right->accounting);
1121
1122 do
1123 {
1124 itr->accounting = left->accounting;
1125 itr = itr->next;
1126 }
1127 while (itr);
1128 }
1129 else
1130 {
1131 Eina_List *itr = left->accounting->last;
1132 right->accounting->count += n_left;
1133
1134 _eina_list_mempool_accounting_free(left->accounting);
1135
1136 do
1137 {
1138 itr->accounting = right->accounting;
1139 itr = itr->prev;
1140 }
1141 while (itr);
1142 }
1143
1144 return left;
1145}
1146
1147
1148EAPI Eina_List *
1149eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
1150{
1151 Eina_List *next;
1152 Eina_List *itr;
1153
1154 if(!right)
1155 return list;
1156
1157 *right = NULL;
1158
1159 if (!list)
1160 return NULL;
1161
1162 if (!relative)
1163 {
1164 *right = list;
1165 return NULL;
1166 }
1167
1168 if (relative == eina_list_last(list))
1169 return list;
1170
1171 next = eina_list_next(relative);
1172 next->prev = NULL;
1173 next->accounting = _eina_list_mempool_accounting_new(next);
1174 next->accounting->last = list->accounting->last;
1175 *right = next;
1176
1177 itr = next;
1178 do
1179 {
1180 itr->accounting = next->accounting;
1181 next->accounting->count++;
1182 itr = itr->next;
1183 }
1184 while (itr);
1185
1186 relative->next = NULL;
1187 list->accounting->last = relative;
1188 list->accounting->count = list->accounting->count - next->accounting->count;
1189
1190 return list;
1191}
1192
1193EAPI Eina_List *
1194eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
1195{
1196 Eina_List *ret;
1197 Eina_List *current;
1198
1199 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1200
1201 if (!left)
1202 return right;
1203
1204 if (!right)
1205 return left;
1206
1207 if (func(left->data, right->data) < 0)
1208 {
1209 ret = left;
1210 current = left;
1211 left = left->next;
1212 ret->accounting->count += right->accounting->count;
1213
1214 _eina_list_mempool_accounting_free(right->accounting);
1215 }
1216 else
1217 {
1218 ret = right;
1219 current = right;
1220 right = right->next;
1221 ret->accounting->count += left->accounting->count;
1222
1223 _eina_list_mempool_accounting_free(left->accounting);
1224 }
1225
1226 while (left && right)
1227 {
1228 if (func(left->data, right->data) < 0)
1229 {
1230 current->next = left;
1231 left->prev = current;
1232 left = left->next;
1233 }
1234 else
1235 {
1236 current->next = right;
1237 right->prev = current;
1238 right = right->next;
1239 }
1240
1241 current = current->next;
1242 current->accounting = ret->accounting;
1243 }
1244
1245 if (left)
1246 {
1247 current->next = left;
1248 left->prev = current;
1249 current->accounting = ret->accounting;
1250 }
1251
1252 if (right)
1253 {
1254 current->next = right;
1255 right->prev = current;
1256 current->accounting = ret->accounting;
1257 }
1258
1259 while (current->next)
1260 {
1261 current = current->next;
1262 current->accounting = ret->accounting;
1263 }
1264
1265 ret->accounting->last = current;
1266
1267 return ret;
1268}
1269
1270EAPI Eina_List *
1271eina_list_search_sorted_near_list(const Eina_List *list,
1272 Eina_Compare_Cb func,
1273 const void *data,
1274 int *result_cmp)
1275{
1276 const Eina_List *ct;
1277 unsigned int inf, sup, cur;
1278 int cmp;
1279
1280 if (!list)
1281 {
1282 if (result_cmp)
1283 *result_cmp = 0;
1284
1285 return NULL;
1286 }
1287
1288 if (list->accounting->count == 1)
1289 {
1290 if (result_cmp)
1291 *result_cmp = func(list->data, data);
1292
1293 return (Eina_List *)list;
1294 }
1295
1296 /* list walk is expensive, do quick check: tail */
1297 ct = list->accounting->last;
1298 cmp = func(ct->data, data);
1299 if (cmp <= 0)
1300 goto end;
1301
1302 /* list walk is expensive, do quick check: head */
1303 ct = list;
1304 cmp = func(ct->data, data);
1305 if (cmp >= 0)
1306 goto end;
1307
1308 /* inclusive bounds */
1309 inf = 1;
1310 sup = list->accounting->count - 2;
1311 cur = 1;
1312 ct = list->next;
1313
1314 /* no loop, just compare if comparison value is important to caller */
1315 if (inf > sup)
1316 {
1317 if (result_cmp)
1318 cmp = func(ct->data, data);
1319
1320 goto end;
1321 }
1322
1323 while (inf <= sup)
1324 {
1325 unsigned int tmp = cur;
1326 cur = inf + ((sup - inf) >> 1);
1327 if (tmp < cur)
1328 for (; tmp != cur; tmp++, ct = ct->next) ;
1329 else if (tmp > cur)
1330 for (; tmp != cur; tmp--, ct = ct->prev) ;
1331
1332 cmp = func(ct->data, data);
1333 if (cmp == 0)
1334 break;
1335 else if (cmp < 0)
1336 inf = cur + 1;
1337 else if (cmp > 0)
1338 {
1339 if (cur > 0)
1340 sup = cur - 1;
1341 else
1342 break;
1343 }
1344 else
1345 break;
1346 }
1347
1348end:
1349 if (result_cmp)
1350 *result_cmp = cmp;
1351
1352 return (Eina_List *)ct;
1353}
1354
1355EAPI Eina_List *
1356eina_list_search_sorted_list(const Eina_List *list,
1357 Eina_Compare_Cb func,
1358 const void *data)
1359{
1360 Eina_List *lnear;
1361 int cmp;
1362
1363 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
1364 if (!lnear)
1365 return NULL;
1366
1367 if (cmp == 0)
1368 return lnear;
1369
1370 return NULL;
1371}
1372
1373
1374EAPI void *
1375eina_list_search_sorted(const Eina_List *list,
1376 Eina_Compare_Cb func,
1377 const void *data)
1378{
1379 return eina_list_data_get(eina_list_search_sorted_list(list, func, data));
1380}
1381
1382EAPI Eina_List *
1383eina_list_search_unsorted_list(const Eina_List *list,
1384 Eina_Compare_Cb func,
1385 const void *data)
1386{
1387 const Eina_List *l;
1388 void *d;
1389
1390 EINA_LIST_FOREACH(list, l, d)
1391 {
1392 if (!func(d, data))
1393 return (Eina_List *)l;
1394 }
1395 return NULL;
1396}
1397
1398EAPI void *
1399eina_list_search_unsorted(const Eina_List *list,
1400 Eina_Compare_Cb func,
1401 const void *data)
1402{
1403 return eina_list_data_get(eina_list_search_unsorted_list(list, func, data));
1404}
1405
1406
1407EAPI Eina_Iterator *
1408eina_list_iterator_new(const Eina_List *list)
1409{
1410 Eina_Iterator_List *it;
1411
1412 eina_error_set(0);
1413 it = calloc(1, sizeof (Eina_Iterator_List));
1414 if (!it)
1415 {
1416 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1417 return NULL;
1418 }
1419
1420 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1421 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1422
1423 it->head = list;
1424 it->current = list;
1425
1426 it->iterator.version = EINA_ITERATOR_VERSION;
1427 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next);
1428 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1429 eina_list_iterator_get_container);
1430 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1431
1432 return &it->iterator;
1433}
1434
1435EAPI Eina_Iterator *
1436eina_list_iterator_reversed_new(const Eina_List *list)
1437{
1438 Eina_Iterator_List *it;
1439
1440 eina_error_set(0);
1441 it = calloc(1, sizeof (Eina_Iterator_List));
1442 if (!it)
1443 {
1444 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1445 return NULL;
1446 }
1447
1448 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1449 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1450
1451 it->head = eina_list_last(list);
1452 it->current = it->head;
1453
1454 it->iterator.version = EINA_ITERATOR_VERSION;
1455 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev);
1456 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1457 eina_list_iterator_get_container);
1458 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1459
1460 return &it->iterator;
1461}
1462
1463EAPI Eina_Accessor *
1464eina_list_accessor_new(const Eina_List *list)
1465{
1466 Eina_Accessor_List *ac;
1467
1468 eina_error_set(0);
1469 ac = calloc(1, sizeof (Eina_Accessor_List));
1470 if (!ac)
1471 {
1472 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1473 return NULL;
1474 }
1475
1476 EINA_MAGIC_SET(ac, EINA_MAGIC_LIST_ACCESSOR);
1477 EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
1478
1479 ac->head = list;
1480 ac->current = list;
1481 ac->index = 0;
1482
1483 ac->accessor.version = EINA_ACCESSOR_VERSION;
1484 ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at);
1485 ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
1486 eina_list_accessor_get_container);
1487 ac->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free);
1488
1489 return &ac->accessor;
1490}
diff --git a/libraries/eina/src/lib/eina_log.c b/libraries/eina/src/lib/eina_log.c
new file mode 100644
index 0000000..dd772d2
--- /dev/null
+++ b/libraries/eina/src/lib/eina_log.c
@@ -0,0 +1,1852 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2009 Jorge Luis Zapata Muga, Cedric Bail, Andre Dieb
3 * Martins
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#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <fnmatch.h>
28#include <assert.h>
29#include <errno.h>
30
31#ifdef HAVE_UNISTD_H
32# include <unistd.h>
33#endif
34
35#ifdef EFL_HAVE_POSIX_THREADS
36# include <pthread.h>
37#endif
38
39#ifdef HAVE_EVIL
40# include <Evil.h>
41#endif
42
43#include "eina_config.h"
44#include "eina_private.h"
45#include "eina_inlist.h"
46
47/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
48#include "eina_safety_checks.h"
49#include "eina_log.h"
50
51/* TODO
52 * + printing logs to stdout or stderr can be implemented
53 * using a queue, useful for multiple threads printing
54 * + add a wrapper for assert?
55 */
56
57/*============================================================================*
58* Local *
59*============================================================================*/
60
61/**
62 * @cond LOCAL
63 */
64
65#define EINA_LOG_ENV_ABORT "EINA_LOG_ABORT"
66#define EINA_LOG_ENV_ABORT_LEVEL "EINA_LOG_ABORT_LEVEL"
67#define EINA_LOG_ENV_LEVEL "EINA_LOG_LEVEL"
68#define EINA_LOG_ENV_LEVELS "EINA_LOG_LEVELS"
69#define EINA_LOG_ENV_LEVELS_GLOB "EINA_LOG_LEVELS_GLOB"
70#define EINA_LOG_ENV_COLOR_DISABLE "EINA_LOG_COLOR_DISABLE"
71#define EINA_LOG_ENV_FILE_DISABLE "EINA_LOG_FILE_DISABLE"
72#define EINA_LOG_ENV_FUNCTION_DISABLE "EINA_LOG_FUNCTION_DISABLE"
73
74
75// Structure for storing domain level settings passed from the command line
76// that will be matched with application-defined domains.
77typedef struct _Eina_Log_Domain_Level_Pending Eina_Log_Domain_Level_Pending;
78struct _Eina_Log_Domain_Level_Pending
79{
80 EINA_INLIST;
81 unsigned int level;
82 size_t namelen;
83 char name[];
84};
85
86/*
87 * List of levels for domains set by the user before the domains are registered,
88 * updates the domain levels on the first log and clears itself.
89 */
90static Eina_Inlist *_pending_list = NULL;
91static Eina_Inlist *_glob_list = NULL;
92
93// Disable color flag (can be changed through the env var
94// EINA_LOG_ENV_COLOR_DISABLE).
95static Eina_Bool _disable_color = EINA_FALSE;
96static Eina_Bool _disable_file = EINA_FALSE;
97static Eina_Bool _disable_function = EINA_FALSE;
98static Eina_Bool _abort_on_critical = EINA_FALSE;
99static int _abort_level_on_critical = EINA_LOG_LEVEL_CRITICAL;
100
101#ifdef EFL_HAVE_THREADS
102
103static Eina_Bool _threads_enabled = EINA_FALSE;
104static Eina_Bool _threads_inited = EINA_FALSE;
105
106# ifdef EFL_HAVE_POSIX_THREADS
107
108typedef pthread_t Thread;
109
110static pthread_t _main_thread;
111
112# define SELF() pthread_self()
113# define IS_MAIN(t) pthread_equal(t, _main_thread)
114# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
115# define CHECK_MAIN(...) \
116 do { \
117 if (!IS_MAIN(pthread_self())) { \
118 fprintf(stderr, \
119 "ERR: not main thread! current=%lu, main=%lu\n", \
120 (unsigned long)pthread_self(), \
121 (unsigned long)_main_thread); \
122 return __VA_ARGS__; \
123 } \
124 } while (0)
125
126# ifdef EFL_HAVE_POSIX_THREADS_SPINLOCK
127
128static pthread_spinlock_t _log_lock;
129
130static Eina_Bool _eina_log_spinlock_init(void)
131{
132 if (pthread_spin_init(&_log_lock, PTHREAD_PROCESS_PRIVATE) == 0)
133 return EINA_TRUE;
134
135 fprintf(stderr,
136 "ERROR: pthread_spin_init(%p, PTHREAD_PROCESS_PRIVATE): %s\n",
137 &_log_lock, strerror(errno));
138 return EINA_FALSE;
139}
140
141# define LOG_LOCK() \
142 if (_threads_enabled) \
143 do { \
144 if (0) { \
145 fprintf(stderr, "+++LOG LOG_LOCKED! [%s, %lu]\n", \
146 __FUNCTION__, (unsigned long)pthread_self()); } \
147 if (EINA_UNLIKELY(_threads_enabled)) { \
148 pthread_spin_lock(&_log_lock); } \
149 } while (0)
150# define LOG_UNLOCK() \
151 if (_threads_enabled) \
152 do { \
153 if (EINA_UNLIKELY(_threads_enabled)) { \
154 pthread_spin_unlock(&_log_lock); } \
155 if (0) { \
156 fprintf(stderr, \
157 "---LOG LOG_UNLOCKED! [%s, %lu]\n", \
158 __FUNCTION__, (unsigned long)pthread_self()); } \
159 } while (0)
160# define INIT() _eina_log_spinlock_init()
161# define SHUTDOWN() pthread_spin_destroy(&_log_lock)
162
163# else /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
164
165static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
166# define LOG_LOCK() if(_threads_enabled) {pthread_mutex_lock(&_log_mutex); }
167# define LOG_UNLOCK() if(_threads_enabled) {pthread_mutex_unlock(&_log_mutex); }
168# define INIT() (1)
169# define SHUTDOWN() do {} while (0)
170
171# endif /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
172
173# else /* EFL_HAVE_WIN32_THREADS */
174
175typedef DWORD Thread;
176
177static DWORD _main_thread;
178
179# define SELF() GetCurrentThreadId()
180# define IS_MAIN(t) (t == _main_thread)
181# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
182# define CHECK_MAIN(...) \
183 do { \
184 if (!IS_MAIN(GetCurrentThreadId())) { \
185 fprintf(stderr, \
186 "ERR: not main thread! current=%lu, main=%lu\n", \
187 GetCurrentThreadId(), _main_thread); \
188 return __VA_ARGS__; \
189 } \
190 } while (0)
191
192static HANDLE _log_mutex = NULL;
193
194# define LOG_LOCK() if(_threads_enabled) WaitForSingleObject(_log_mutex, INFINITE)
195# define LOG_UNLOCK() if(_threads_enabled) ReleaseMutex(_log_mutex)
196# define INIT() ((_log_mutex = CreateMutex(NULL, FALSE, NULL)) ? 1 : 0)
197# define SHUTDOWN() if (_log_mutex) CloseHandle(_log_mutex)
198
199# endif /* EFL_HAVE_WIN32_THREADS */
200
201#else /* ! EFL_HAVE_THREADS */
202
203# define LOG_LOCK() do {} while (0)
204# define LOG_UNLOCK() do {} while (0)
205# define IS_MAIN(t) (1)
206# define IS_OTHER(t) (0)
207# define CHECK_MAIN(...) do {} while (0)
208# define INIT() (1)
209# define SHUTDOWN() do {} while (0)
210
211#endif /* ! EFL_HAVE_THREADS */
212
213
214// List of domains registered
215static Eina_Log_Domain *_log_domains = NULL;
216static unsigned int _log_domains_count = 0;
217static size_t _log_domains_allocated = 0;
218
219// Default function for printing on domains
220static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr;
221static void *_print_cb_data = NULL;
222
223#ifdef DEBUG
224static Eina_Log_Level _log_level = EINA_LOG_LEVEL_DBG;
225#elif DEBUG_CRITICAL
226static Eina_Log_Level _log_level = EINA_LOG_LEVEL_CRITICAL;
227#else
228static Eina_Log_Level _log_level = EINA_LOG_LEVEL_ERR;
229#endif
230
231/* NOTE: if you change this, also change:
232 * eina_log_print_level_name_get()
233 * eina_log_print_level_name_color_get()
234 */
235static const char *_names[] = {
236 "CRI",
237 "ERR",
238 "WRN",
239 "INF",
240 "DBG",
241};
242
243#ifdef _WIN32
244static int
245eina_log_win32_color_get(const char *domain_str)
246{
247 char *str;
248 char *tmp;
249 char *tmp2;
250 int code = -1;
251 int lighted = 0;
252 int ret = 0;
253
254 str = strdup(domain_str);
255 if (!str)
256 return 0;
257
258 /* this should not append */
259 if (str[0] != '\033')
260 {
261 free(str);
262 return 0;
263 }
264
265 /* we skip the first char and the [ */
266 tmp = tmp2 = str + 2;
267 while (*tmp != 'm')
268 {
269 if (*tmp == ';')
270 {
271 *tmp = '\0';
272 code = atol(tmp2);
273 tmp++;
274 tmp2 = tmp;
275 }
276
277 tmp++;
278 }
279 *tmp = '\0';
280 if (code < 0)
281 code = atol(tmp2);
282 else
283 lighted = atol(tmp2);
284
285 free(str);
286
287 if (code < lighted)
288 {
289 int c;
290
291 c = code;
292 code = lighted;
293 lighted = c;
294 }
295
296 if (lighted)
297 ret = FOREGROUND_INTENSITY;
298
299 if (code == 31)
300 ret |= FOREGROUND_RED;
301 else if (code == 32)
302 ret |= FOREGROUND_GREEN;
303 else if (code == 33)
304 ret |= FOREGROUND_RED | FOREGROUND_GREEN;
305 else if (code == 34)
306 ret |= FOREGROUND_BLUE;
307 else if (code == 36)
308 ret |= FOREGROUND_GREEN | FOREGROUND_BLUE;
309 else if (code == 37)
310 ret |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
311
312 return ret;
313}
314#endif
315
316static inline unsigned int
317eina_log_pid_get(void)
318{
319 return (unsigned int)getpid();
320}
321
322static inline void
323eina_log_print_level_name_get(int level, const char **p_name)
324{
325 static char buf[4];
326 /* NOTE: if you change this, also change
327 * eina_log_print_level_name_color_get()
328 * eina_log_level_name_get() (at eina_inline_log.x)
329 */
330 if (EINA_UNLIKELY(level < 0))
331 {
332 snprintf(buf, sizeof(buf), "%03d", level);
333 *p_name = buf;
334 }
335 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
336 {
337 snprintf(buf, sizeof(buf), "%03d", level);
338 *p_name = buf;
339 }
340 else
341 *p_name = _names[level];
342}
343
344#ifdef _WIN32
345static inline void
346eina_log_print_level_name_color_get(int level,
347 const char **p_name,
348 int *p_color)
349{
350 static char buf[4];
351 /* NOTE: if you change this, also change:
352 * eina_log_print_level_name_get()
353 */
354 if (EINA_UNLIKELY(level < 0))
355 {
356 snprintf(buf, sizeof(buf), "%03d", level);
357 *p_name = buf;
358 }
359 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
360 {
361 snprintf(buf, sizeof(buf), "%03d", level);
362 *p_name = buf;
363 }
364 else
365 *p_name = _names[level];
366
367 *p_color = eina_log_win32_color_get(eina_log_level_color_get(level));
368}
369#else
370static inline void
371eina_log_print_level_name_color_get(int level,
372 const char **p_name,
373 const char **p_color)
374{
375 static char buf[4];
376 /* NOTE: if you change this, also change:
377 * eina_log_print_level_name_get()
378 */
379 if (EINA_UNLIKELY(level < 0))
380 {
381 snprintf(buf, sizeof(buf), "%03d", level);
382 *p_name = buf;
383 }
384 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
385 {
386 snprintf(buf, sizeof(buf), "%03d", level);
387 *p_name = buf;
388 }
389 else
390 *p_name = _names[level];
391
392 *p_color = eina_log_level_color_get(level);
393}
394#endif
395
396#define DECLARE_LEVEL_NAME(level) const char *name; \
397 eina_log_print_level_name_get(level, &name)
398#ifdef _WIN32
399# define DECLARE_LEVEL_NAME_COLOR(level) const char *name; int color; \
400 eina_log_print_level_name_color_get(level, &name, &color)
401#else
402# define DECLARE_LEVEL_NAME_COLOR(level) const char *name, *color; \
403 eina_log_print_level_name_color_get(level, &name, &color)
404#endif
405
406/** No threads, No color */
407static void
408eina_log_print_prefix_NOthreads_NOcolor_file_func(FILE *fp,
409 const Eina_Log_Domain *d,
410 Eina_Log_Level level,
411 const char *file,
412 const char *fnc,
413 int line)
414{
415 DECLARE_LEVEL_NAME(level);
416 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
417 d->domain_str, file, line, fnc);
418}
419
420static void
421eina_log_print_prefix_NOthreads_NOcolor_NOfile_func(FILE *fp,
422 const Eina_Log_Domain *d,
423 Eina_Log_Level level,
424 const char *file __UNUSED__,
425 const char *fnc,
426 int line __UNUSED__)
427{
428 DECLARE_LEVEL_NAME(level);
429 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
430 fnc);
431}
432
433static void
434eina_log_print_prefix_NOthreads_NOcolor_file_NOfunc(FILE *fp,
435 const Eina_Log_Domain *d,
436 Eina_Log_Level level,
437 const char *file,
438 const char *fnc __UNUSED__,
439 int line)
440{
441 DECLARE_LEVEL_NAME(level);
442 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
443 file, line);
444}
445
446/* No threads, color */
447static void
448eina_log_print_prefix_NOthreads_color_file_func(FILE *fp,
449 const Eina_Log_Domain *d,
450 Eina_Log_Level level,
451 const char *file,
452 const char *fnc,
453 int line)
454{
455 DECLARE_LEVEL_NAME_COLOR(level);
456#ifdef _WIN32_WCE
457 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
458 d->domain_str, file, line, fnc);
459#elif _WIN32
460 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
461 color);
462 fprintf(fp, "%s", name);
463 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
464 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
465 fprintf(fp, ":");
466 SetConsoleTextAttribute(GetStdHandle(
467 STD_OUTPUT_HANDLE),
468 eina_log_win32_color_get(d->domain_str));
469 fprintf(fp, "%s", d->name);
470 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
471 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
472 fprintf(fp, " %s:%d ", file, line);
473 SetConsoleTextAttribute(GetStdHandle(
474 STD_OUTPUT_HANDLE),
475 FOREGROUND_INTENSITY | FOREGROUND_RED |
476 FOREGROUND_GREEN | FOREGROUND_BLUE);
477 fprintf(fp, "%s()", fnc);
478 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
479 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
480 fprintf(fp, " ");
481#else
482 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
483 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
484 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
485#endif
486}
487
488static void
489eina_log_print_prefix_NOthreads_color_NOfile_func(FILE *fp,
490 const Eina_Log_Domain *d,
491 Eina_Log_Level level,
492 const char *file __UNUSED__,
493 const char *fnc,
494 int line __UNUSED__)
495{
496 DECLARE_LEVEL_NAME_COLOR(level);
497#ifdef _WIN32_WCE
498 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
499 fnc);
500#elif _WIN32
501 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
502 color);
503 fprintf(fp, "%s", name);
504 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
505 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
506 fprintf(fp, ":");
507 SetConsoleTextAttribute(GetStdHandle(
508 STD_OUTPUT_HANDLE),
509 eina_log_win32_color_get(d->domain_str));
510 fprintf(fp, "%s", d->name);
511 SetConsoleTextAttribute(GetStdHandle(
512 STD_OUTPUT_HANDLE),
513 FOREGROUND_INTENSITY | FOREGROUND_RED |
514 FOREGROUND_GREEN | FOREGROUND_BLUE);
515 fprintf(fp, "%s()", fnc);
516 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
517 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
518 fprintf(fp, " ");
519#else
520 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
521 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
522 color, name, eina_log_pid_get(), d->domain_str, fnc);
523#endif
524}
525
526static void
527eina_log_print_prefix_NOthreads_color_file_NOfunc(FILE *fp,
528 const Eina_Log_Domain *d,
529 Eina_Log_Level level,
530 const char *file,
531 const char *fnc __UNUSED__,
532 int line)
533{
534 DECLARE_LEVEL_NAME_COLOR(level);
535#ifdef _WIN32_WCE
536 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
537 file, line);
538#elif _WIN32
539 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
540 color);
541 fprintf(fp, "%s", name);
542 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
543 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
544 fprintf(fp, ":");
545 SetConsoleTextAttribute(GetStdHandle(
546 STD_OUTPUT_HANDLE),
547 eina_log_win32_color_get(d->domain_str));
548 fprintf(fp, "%s", d->name);
549 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
550 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
551 fprintf(fp, " %s:%d ", file, line);
552#else
553 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d ",
554 color, name, eina_log_pid_get(), d->domain_str, file, line);
555#endif
556}
557
558/** threads, No color */
559#ifdef EFL_HAVE_THREADS
560static void
561eina_log_print_prefix_threads_NOcolor_file_func(FILE *fp,
562 const Eina_Log_Domain *d,
563 Eina_Log_Level level,
564 const char *file,
565 const char *fnc,
566 int line)
567{
568 Thread cur;
569
570 DECLARE_LEVEL_NAME(level);
571 cur = SELF();
572 if (IS_OTHER(cur))
573 {
574 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d %s() ",
575 name, eina_log_pid_get(), d->domain_str,
576 (unsigned long)cur, file, line, fnc);
577 return;
578 }
579 fprintf(fp, "%s<%u>:%s %s:%d %s() ",
580 name, eina_log_pid_get(), d->domain_str, file, line, fnc);
581}
582
583static void
584eina_log_print_prefix_threads_NOcolor_NOfile_func(FILE *fp,
585 const Eina_Log_Domain *d,
586 Eina_Log_Level level,
587 const char *file __UNUSED__,
588 const char *fnc,
589 int line __UNUSED__)
590{
591 Thread cur;
592
593 DECLARE_LEVEL_NAME(level);
594 cur = SELF();
595 if (IS_OTHER(cur))
596 {
597 fprintf(fp, "%s<%u>:%s[T:%lu] %s() ",
598 name, eina_log_pid_get(), d->domain_str,
599 (unsigned long)cur, fnc);
600 return;
601 }
602 fprintf(fp, "%s<%u>:%s %s() ",
603 name, eina_log_pid_get(), d->domain_str, fnc);
604}
605
606static void
607eina_log_print_prefix_threads_NOcolor_file_NOfunc(FILE *fp,
608 const Eina_Log_Domain *d,
609 Eina_Log_Level level,
610 const char *file,
611 const char *fnc __UNUSED__,
612 int line)
613{
614 Thread cur;
615
616 DECLARE_LEVEL_NAME(level);
617 cur = SELF();
618 if (IS_OTHER(cur))
619 {
620 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d ",
621 name, eina_log_pid_get(), d->domain_str, (unsigned long)cur,
622 file, line);
623 return;
624 }
625
626 fprintf(fp, "%s<%u>:%s %s:%d ",
627 name, eina_log_pid_get(), d->domain_str, file, line);
628}
629
630/* threads, color */
631static void
632eina_log_print_prefix_threads_color_file_func(FILE *fp,
633 const Eina_Log_Domain *d,
634 Eina_Log_Level level,
635 const char *file,
636 const char *fnc,
637 int line)
638{
639 Thread cur;
640
641 DECLARE_LEVEL_NAME_COLOR(level);
642 cur = SELF();
643 if (IS_OTHER(cur))
644 {
645# ifdef _WIN32
646 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
647 color);
648 fprintf(fp, "%s", name);
649 SetConsoleTextAttribute(GetStdHandle(
650 STD_OUTPUT_HANDLE),
651 FOREGROUND_RED | FOREGROUND_GREEN |
652 FOREGROUND_BLUE);
653 fprintf(fp, ":");
654 SetConsoleTextAttribute(GetStdHandle(
655 STD_OUTPUT_HANDLE),
656 eina_log_win32_color_get(d->domain_str));
657 fprintf(fp, "%s[T:", d->name);
658 SetConsoleTextAttribute(GetStdHandle(
659 STD_OUTPUT_HANDLE),
660 FOREGROUND_RED | FOREGROUND_GREEN |
661 FOREGROUND_BLUE);
662 fprintf(fp, "[T:");
663 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
664 FOREGROUND_GREEN | FOREGROUND_BLUE);
665 fprintf(fp, "%lu", (unsigned long)cur);
666 SetConsoleTextAttribute(GetStdHandle(
667 STD_OUTPUT_HANDLE),
668 FOREGROUND_RED | FOREGROUND_GREEN |
669 FOREGROUND_BLUE);
670 fprintf(fp, "] %s:%d ", file, line);
671 SetConsoleTextAttribute(GetStdHandle(
672 STD_OUTPUT_HANDLE),
673 FOREGROUND_INTENSITY | FOREGROUND_RED |
674 FOREGROUND_GREEN | FOREGROUND_BLUE);
675 fprintf(fp, "%s()", fnc);
676 SetConsoleTextAttribute(GetStdHandle(
677 STD_OUTPUT_HANDLE),
678 FOREGROUND_RED | FOREGROUND_GREEN |
679 FOREGROUND_BLUE);
680 fprintf(fp, " ");
681# else
682 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
683 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d "
684 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
685 color, name, eina_log_pid_get() ,d->domain_str,
686 (unsigned long)cur, file, line, fnc);
687# endif
688 return;
689 }
690
691# ifdef _WIN32
692 eina_log_print_prefix_NOthreads_color_file_func(fp,
693 d,
694 level,
695 file,
696 fnc,
697 line);
698# else
699 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
700 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
701 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
702# endif
703}
704
705static void
706eina_log_print_prefix_threads_color_NOfile_func(FILE *fp,
707 const Eina_Log_Domain *d,
708 Eina_Log_Level level,
709 const char *file __UNUSED__,
710 const char *fnc,
711 int line __UNUSED__)
712{
713 Thread cur;
714
715 DECLARE_LEVEL_NAME_COLOR(level);
716 cur = SELF();
717 if (IS_OTHER(cur))
718 {
719# ifdef _WIN32
720 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
721 color);
722 fprintf(fp, "%s", name);
723 SetConsoleTextAttribute(GetStdHandle(
724 STD_OUTPUT_HANDLE),
725 FOREGROUND_RED | FOREGROUND_GREEN |
726 FOREGROUND_BLUE);
727 fprintf(fp, ":");
728 SetConsoleTextAttribute(GetStdHandle(
729 STD_OUTPUT_HANDLE),
730 eina_log_win32_color_get(d->domain_str));
731 fprintf(fp, "%s[T:", d->name);
732 SetConsoleTextAttribute(GetStdHandle(
733 STD_OUTPUT_HANDLE),
734 FOREGROUND_RED | FOREGROUND_GREEN |
735 FOREGROUND_BLUE);
736 fprintf(fp, "[T:");
737 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
738 FOREGROUND_GREEN | FOREGROUND_BLUE);
739 fprintf(fp, "%lu", (unsigned long)cur);
740 SetConsoleTextAttribute(GetStdHandle(
741 STD_OUTPUT_HANDLE),
742 FOREGROUND_INTENSITY | FOREGROUND_RED |
743 FOREGROUND_GREEN | FOREGROUND_BLUE);
744 fprintf(fp, "%s()", fnc);
745 SetConsoleTextAttribute(GetStdHandle(
746 STD_OUTPUT_HANDLE),
747 FOREGROUND_RED | FOREGROUND_GREEN |
748 FOREGROUND_BLUE);
749 fprintf(fp, " ");
750# else
751 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
752 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] "
753 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
754 color, name, eina_log_pid_get(), d->domain_str,
755 (unsigned long)cur, fnc);
756# endif
757 return;
758 }
759
760# ifdef _WIN32
761 eina_log_print_prefix_NOthreads_color_NOfile_func(fp,
762 d,
763 level,
764 file,
765 fnc,
766 line);
767# else
768 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
769 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
770 color, name, eina_log_pid_get(), d->domain_str, fnc);
771# endif
772}
773
774static void
775eina_log_print_prefix_threads_color_file_NOfunc(FILE *fp,
776 const Eina_Log_Domain *d,
777 Eina_Log_Level level,
778 const char *file,
779 const char *fnc __UNUSED__,
780 int line)
781{
782 Thread cur;
783
784 DECLARE_LEVEL_NAME_COLOR(level);
785 cur = SELF();
786 if (IS_OTHER(cur))
787 {
788# ifdef _WIN32
789 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
790 color);
791 fprintf(fp, "%s", name);
792 SetConsoleTextAttribute(GetStdHandle(
793 STD_OUTPUT_HANDLE),
794 FOREGROUND_RED | FOREGROUND_GREEN |
795 FOREGROUND_BLUE);
796 fprintf(fp, ":");
797 SetConsoleTextAttribute(GetStdHandle(
798 STD_OUTPUT_HANDLE),
799 eina_log_win32_color_get(d->domain_str));
800 fprintf(fp, "%s[T:", d->name);
801 SetConsoleTextAttribute(GetStdHandle(
802 STD_OUTPUT_HANDLE),
803 FOREGROUND_RED | FOREGROUND_GREEN |
804 FOREGROUND_BLUE);
805 fprintf(fp, "[T:");
806 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
807 FOREGROUND_GREEN | FOREGROUND_BLUE);
808 fprintf(fp, "%lu", (unsigned long)cur);
809 SetConsoleTextAttribute(GetStdHandle(
810 STD_OUTPUT_HANDLE),
811 FOREGROUND_RED | FOREGROUND_GREEN |
812 FOREGROUND_BLUE);
813 fprintf(fp, "] %s:%d ", file, line);
814# else
815 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
816 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d ",
817 color, name, eina_log_pid_get(), d->domain_str,
818 (unsigned long)cur, file, line);
819# endif
820 return;
821 }
822
823# ifdef _WIN32
824 eina_log_print_prefix_NOthreads_color_file_NOfunc(fp,
825 d,
826 level,
827 file,
828 fnc,
829 line);
830# else
831 fprintf(fp, "%s%s" EINA_COLOR_RESET ":%s %s:%d ",
832 color, name, d->domain_str, file, line);
833# endif
834}
835#endif /* EFL_HAVE_THREADS */
836
837static void (*_eina_log_print_prefix)(FILE *fp, const Eina_Log_Domain *d,
838 Eina_Log_Level level, const char *file,
839 const char *fnc,
840 int line) =
841 eina_log_print_prefix_NOthreads_color_file_func;
842
843static inline void
844eina_log_print_prefix_update(void)
845{
846 if (_disable_file && _disable_function)
847 {
848 fprintf(stderr, "ERROR: cannot have " EINA_LOG_ENV_FILE_DISABLE " and "
849 EINA_LOG_ENV_FUNCTION_DISABLE " set at the same time, will "
850 "just disable function.\n");
851 _disable_file = 0;
852 }
853
854#define S(NOthread, NOcolor, NOfile, NOfunc) \
855 _eina_log_print_prefix = \
856 eina_log_print_prefix_ ## NOthread ## threads_ ## NOcolor ## color_ ## \
857 NOfile \
858 ## file_ ## NOfunc ## func
859
860#ifdef EFL_HAVE_THREADS
861 if (_threads_enabled)
862 {
863 if (_disable_color)
864 {
865 if (_disable_file)
866 S(,NO,NO,);
867 else if (_disable_function)
868 S(,NO,,NO);
869 else
870 S(,NO,,);
871 }
872 else
873 {
874 if (_disable_file)
875 S(,,NO,);
876 else if (_disable_function)
877 S(,,,NO);
878 else
879 S(,,,);
880 }
881
882 return;
883 }
884
885#endif
886
887 if (_disable_color)
888 {
889 if (_disable_file)
890 S(NO,NO,NO,);
891 else if (_disable_function)
892 S(NO,NO,,NO);
893 else
894 S(NO,NO,,);
895 }
896 else
897 {
898 if (_disable_file)
899 S(NO,,NO,);
900 else if (_disable_function)
901 S(NO,,,NO);
902 else
903 S(NO,,,);
904 }
905
906#undef S
907}
908
909/*
910 * Creates a colored domain name string.
911 */
912static const char *
913eina_log_domain_str_get(const char *name, const char *color)
914{
915 const char *d;
916
917 if (color)
918 {
919 size_t name_len;
920 size_t color_len;
921
922 name_len = strlen(name);
923 color_len = strlen(color);
924 d =
925 malloc(sizeof(char) *
926 (color_len + name_len + strlen(EINA_COLOR_RESET) + 1));
927 if (!d)
928 return NULL;
929
930 memcpy((char *)d, color, color_len);
931 memcpy((char *)(d + color_len), name, name_len);
932 memcpy((char *)(d + color_len + name_len), EINA_COLOR_RESET,
933 strlen(EINA_COLOR_RESET));
934 ((char *)d)[color_len + name_len + strlen(EINA_COLOR_RESET)] = '\0';
935 }
936 else
937 d = strdup(name);
938
939 return d;
940}
941
942/*
943 * Setups a new logging domain to the name and color specified. Note that this
944 * constructor acts upon an pre-allocated object.
945 */
946static Eina_Log_Domain *
947eina_log_domain_new(Eina_Log_Domain *d, const char *name, const char *color)
948{
949 EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
950 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
951
952 d->level = EINA_LOG_LEVEL_UNKNOWN;
953 d->deleted = EINA_FALSE;
954
955 if ((color) && (!_disable_color))
956 d->domain_str = eina_log_domain_str_get(name, color);
957 else
958 d->domain_str = eina_log_domain_str_get(name, NULL);
959
960 d->name = strdup(name);
961 d->namelen = strlen(name);
962
963 return d;
964}
965
966/*
967 * Frees internal strings of a log domain, keeping the log domain itself as a
968 * slot for next domain registers.
969 */
970static void
971eina_log_domain_free(Eina_Log_Domain *d)
972{
973 EINA_SAFETY_ON_NULL_RETURN(d);
974
975 if (d->domain_str)
976 free((char *)d->domain_str);
977
978 if (d->name)
979 free((char *)d->name);
980}
981
982/*
983 * Parses domain levels passed through the env var.
984 */
985static void
986eina_log_domain_parse_pendings(void)
987{
988 const char *start;
989
990 if (!(start = getenv(EINA_LOG_ENV_LEVELS)))
991 return;
992
993 // name1:level1,name2:level2,name3:level3,...
994 while (1)
995 {
996 Eina_Log_Domain_Level_Pending *p;
997 char *end = NULL;
998 char *tmp = NULL;
999 long int level;
1000
1001 end = strchr(start, ':');
1002 if (!end)
1003 break;
1004
1005 // Parse level, keep going if failed
1006 level = strtol((char *)(end + 1), &tmp, 10);
1007 if (tmp == (end + 1))
1008 goto parse_end;
1009
1010 // Parse name
1011 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1012 if (!p)
1013 break;
1014
1015 p->namelen = end - start;
1016 memcpy((char *)p->name, start, end - start);
1017 ((char *)p->name)[end - start] = '\0';
1018 p->level = level;
1019
1020 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(p));
1021
1022parse_end:
1023 start = strchr(tmp, ',');
1024 if (start)
1025 start++;
1026 else
1027 break;
1028 }
1029}
1030
1031static void
1032eina_log_domain_parse_pending_globs(void)
1033{
1034 const char *start;
1035
1036 if (!(start = getenv(EINA_LOG_ENV_LEVELS_GLOB)))
1037 return;
1038
1039 // name1:level1,name2:level2,name3:level3,...
1040 while (1)
1041 {
1042 Eina_Log_Domain_Level_Pending *p;
1043 char *end = NULL;
1044 char *tmp = NULL;
1045 long int level;
1046
1047 end = strchr(start, ':');
1048 if (!end)
1049 break;
1050
1051 // Parse level, keep going if failed
1052 level = strtol((char *)(end + 1), &tmp, 10);
1053 if (tmp == (end + 1))
1054 goto parse_end;
1055
1056 // Parse name
1057 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1058 if (!p)
1059 break;
1060
1061 p->namelen = 0; /* not that useful */
1062 memcpy((char *)p->name, start, end - start);
1063 ((char *)p->name)[end - start] = '\0';
1064 p->level = level;
1065
1066 _glob_list = eina_inlist_append(_glob_list, EINA_INLIST_GET(p));
1067
1068parse_end:
1069 start = strchr(tmp, ',');
1070 if (start)
1071 start++;
1072 else
1073 break;
1074 }
1075}
1076
1077static inline int
1078eina_log_domain_register_unlocked(const char *name, const char *color)
1079{
1080 Eina_Log_Domain_Level_Pending *pending = NULL;
1081 size_t namelen;
1082 unsigned int i;
1083
1084 for (i = 0; i < _log_domains_count; i++)
1085 {
1086 if (_log_domains[i].deleted)
1087 {
1088 // Found a flagged slot, free domain_str and replace slot
1089 eina_log_domain_new(&_log_domains[i], name, color);
1090 goto finish_register;
1091 }
1092 }
1093
1094 if (_log_domains_count >= _log_domains_allocated)
1095 {
1096 Eina_Log_Domain *tmp;
1097 size_t size;
1098
1099 if (!_log_domains)
1100 // special case for init, eina itself will allocate a dozen of domains
1101 size = 24;
1102 else
1103 // grow 8 buckets to minimize reallocs
1104 size = _log_domains_allocated + 8;
1105
1106 tmp = realloc(_log_domains, sizeof(Eina_Log_Domain) * size);
1107
1108 if (tmp)
1109 {
1110 // Success!
1111 _log_domains = tmp;
1112 _log_domains_allocated = size;
1113 }
1114 else
1115 return -1;
1116 }
1117
1118 // Use an allocated slot
1119 eina_log_domain_new(&_log_domains[i], name, color);
1120 _log_domains_count++;
1121
1122finish_register:
1123 namelen = _log_domains[i].namelen;
1124
1125 EINA_INLIST_FOREACH(_pending_list, pending)
1126 {
1127 if ((namelen == pending->namelen) && (strcmp(pending->name, name) == 0))
1128 {
1129 _log_domains[i].level = pending->level;
1130 _pending_list =
1131 eina_inlist_remove(_pending_list, EINA_INLIST_GET(pending));
1132 free(pending);
1133 break;
1134 }
1135 }
1136
1137 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1138 {
1139 EINA_INLIST_FOREACH(_glob_list, pending)
1140 {
1141 if (!fnmatch(pending->name, name, 0))
1142 {
1143 _log_domains[i].level = pending->level;
1144 break;
1145 }
1146 }
1147 }
1148
1149 // Check if level is still UNKNOWN, set it to global
1150 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1151 _log_domains[i].level = _log_level;
1152
1153 return i;
1154}
1155
1156static inline Eina_Bool
1157eina_log_term_color_supported(const char *term)
1158{
1159 const char *tail;
1160
1161 if (!term)
1162 return EINA_FALSE;
1163
1164 tail = term + 1;
1165 switch (term[0])
1166 {
1167 /* list of known to support color terminals,
1168 * take from gentoo's portage.
1169 */
1170
1171 case 'x': /* xterm and xterm-color */
1172 return ((strncmp(tail, "term", sizeof("term") - 1) == 0) &&
1173 ((tail[sizeof("term") - 1] == '\0') ||
1174 (strcmp(tail + sizeof("term") - 1, "-color") == 0)));
1175
1176 case 'E': /* Eterm */
1177 case 'a': /* aterm */
1178 case 'k': /* kterm */
1179 return (strcmp(tail, "term") == 0);
1180
1181 case 'r': /* xrvt or rxvt-unicode */
1182 return ((strncmp(tail, "xvt", sizeof("xvt") - 1) == 0) &&
1183 ((tail[sizeof("xvt") - 1] == '\0') ||
1184 (strcmp(tail + sizeof("xvt") - 1, "-unicode") == 0)));
1185
1186 case 's': /* screen */
1187 return (strcmp(tail, "creen") == 0);
1188
1189 case 'g': /* gnome */
1190 return (strcmp(tail, "nome") == 0);
1191
1192 case 'i': /* interix */
1193 return (strcmp(tail, "nterix") == 0);
1194
1195 default:
1196 return EINA_FALSE;
1197 }
1198}
1199
1200static inline void
1201eina_log_domain_unregister_unlocked(int domain)
1202{
1203 Eina_Log_Domain *d;
1204
1205 if ((unsigned int)domain >= _log_domains_count)
1206 return;
1207
1208 d = &_log_domains[domain];
1209 eina_log_domain_free(d);
1210 d->deleted = 1;
1211}
1212
1213static inline void
1214eina_log_print_unlocked(int domain,
1215 Eina_Log_Level level,
1216 const char *file,
1217 const char *fnc,
1218 int line,
1219 const char *fmt,
1220 va_list args)
1221{
1222 Eina_Log_Domain *d;
1223
1224#ifdef EINA_SAFETY_CHECKS
1225 if (EINA_UNLIKELY((unsigned int)domain >= _log_domains_count) ||
1226 EINA_UNLIKELY(domain < 0))
1227 {
1228 if (file && fnc && fmt)
1229 fprintf(
1230 stderr,
1231 "CRI: %s:%d %s() eina_log_print() unknown domain %d, original message format '%s'\n",
1232 file,
1233 line,
1234 fnc,
1235 domain,
1236 fmt);
1237 else
1238 fprintf(
1239 stderr,
1240 "CRI: eina_log_print() unknown domain %d, original message format '%s'\n",
1241 domain,
1242 fmt ? fmt : "");
1243
1244 if (_abort_on_critical)
1245 abort();
1246
1247 return;
1248 }
1249
1250#endif
1251 d = _log_domains + domain;
1252#ifdef EINA_SAFETY_CHECKS
1253 if (EINA_UNLIKELY(d->deleted))
1254 {
1255 fprintf(stderr,
1256 "ERR: eina_log_print() domain %d is deleted\n",
1257 domain);
1258 return;
1259 }
1260
1261#endif
1262
1263 if (level > d->level)
1264 return;
1265
1266#ifdef _WIN32
1267 {
1268 char *wfmt;
1269 char *tmp;
1270
1271 wfmt = strdup(fmt);
1272 if (!wfmt)
1273 {
1274 fprintf(stderr, "ERR: %s: can not allocate memory\n", __FUNCTION__);
1275 return;
1276 }
1277
1278 tmp = wfmt;
1279 while (strchr(tmp, '%'))
1280 {
1281 tmp++;
1282 if (*tmp == 'z')
1283 *tmp = 'I';
1284 }
1285 _print_cb(d, level, file, fnc, line, wfmt, _print_cb_data, args);
1286 free(wfmt);
1287 }
1288#else
1289 _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args);
1290#endif
1291
1292 if (EINA_UNLIKELY(_abort_on_critical) &&
1293 EINA_UNLIKELY(level <= _abort_level_on_critical))
1294 abort();
1295}
1296
1297/**
1298 * @endcond
1299 */
1300
1301
1302/*============================================================================*
1303* Global *
1304*============================================================================*/
1305
1306/**
1307 * @internal
1308 * @brief Initialize the log module.
1309 *
1310 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1311 *
1312 * This function sets up the log module of Eina. It is called by
1313 * eina_init().
1314 *
1315 * @see eina_init()
1316 *
1317 * @warning Not-MT: just call this function from main thread! The
1318 * place where this function was called the first time is
1319 * considered the main thread.
1320 */
1321Eina_Bool
1322eina_log_init(void)
1323{
1324 const char *level, *tmp;
1325 int color_disable;
1326
1327 assert((sizeof(_names) / sizeof(_names[0])) == EINA_LOG_LEVELS);
1328
1329 if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)))
1330 color_disable = atoi(tmp);
1331 else
1332 color_disable = -1;
1333
1334 /* Check if color is explicitly disabled */
1335 if (color_disable == 1)
1336 _disable_color = EINA_TRUE;
1337
1338#ifndef _WIN32
1339 /* color was not explicitly disabled or enabled, guess it */
1340 else if (color_disable == -1)
1341 {
1342 if (!eina_log_term_color_supported(getenv("TERM")))
1343 _disable_color = EINA_TRUE;
1344 else
1345 {
1346 /* if not a terminal, but redirected to a file, disable color */
1347 int fd;
1348
1349 if (_print_cb == eina_log_print_cb_stderr)
1350 fd = STDERR_FILENO;
1351 else if (_print_cb == eina_log_print_cb_stdout)
1352 fd = STDOUT_FILENO;
1353 else
1354 fd = -1;
1355
1356 if ((fd >= 0) && (!isatty(fd)))
1357 _disable_color = EINA_TRUE;
1358 }
1359 }
1360#endif
1361
1362 if ((tmp = getenv(EINA_LOG_ENV_FILE_DISABLE)) && (atoi(tmp) == 1))
1363 _disable_file = EINA_TRUE;
1364
1365 if ((tmp = getenv(EINA_LOG_ENV_FUNCTION_DISABLE)) && (atoi(tmp) == 1))
1366 _disable_function = EINA_TRUE;
1367
1368 if ((tmp = getenv(EINA_LOG_ENV_ABORT)) && (atoi(tmp) == 1))
1369 _abort_on_critical = EINA_TRUE;
1370
1371 if ((tmp = getenv(EINA_LOG_ENV_ABORT_LEVEL)))
1372 _abort_level_on_critical = atoi(tmp);
1373
1374 eina_log_print_prefix_update();
1375
1376 // Global log level
1377 if ((level = getenv(EINA_LOG_ENV_LEVEL)))
1378 _log_level = atoi(level);
1379
1380 // Register UNKNOWN domain, the default logger
1381 EINA_LOG_DOMAIN_GLOBAL = eina_log_domain_register("", NULL);
1382
1383 if (EINA_LOG_DOMAIN_GLOBAL < 0)
1384 {
1385 fprintf(stderr, "Failed to create global logging domain.\n");
1386 return EINA_FALSE;
1387 }
1388
1389 // Parse pending domains passed through EINA_LOG_LEVELS_GLOB
1390 eina_log_domain_parse_pending_globs();
1391
1392 // Parse pending domains passed through EINA_LOG_LEVELS
1393 eina_log_domain_parse_pendings();
1394
1395 return EINA_TRUE;
1396}
1397
1398/**
1399 * @internal
1400 * @brief Shut down the log module.
1401 *
1402 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1403 *
1404 * This function shuts down the log module set up by
1405 * eina_log_init(). It is called by eina_shutdown().
1406 *
1407 * @see eina_shutdown()
1408 *
1409 * @warning Not-MT: just call this function from main thread! The
1410 * place where eina_log_init() (eina_init()) was called the
1411 * first time is considered the main thread.
1412 */
1413Eina_Bool
1414eina_log_shutdown(void)
1415{
1416 Eina_Inlist *tmp;
1417
1418 while (_log_domains_count--)
1419 {
1420 if (_log_domains[_log_domains_count].deleted)
1421 continue;
1422
1423 eina_log_domain_free(&_log_domains[_log_domains_count]);
1424 }
1425
1426 free(_log_domains);
1427
1428 _log_domains = NULL;
1429 _log_domains_count = 0;
1430 _log_domains_allocated = 0;
1431
1432 while (_glob_list)
1433 {
1434 tmp = _glob_list;
1435 _glob_list = _glob_list->next;
1436 free(tmp);
1437 }
1438
1439 while (_pending_list)
1440 {
1441 tmp = _pending_list;
1442 _pending_list = _pending_list->next;
1443 free(tmp);
1444 }
1445
1446 return EINA_TRUE;
1447}
1448
1449#ifdef EFL_HAVE_THREADS
1450
1451/**
1452 * @internal
1453 * @brief Activate the log mutex.
1454 *
1455 * This function activate the mutex in the eina log module. It is called by
1456 * eina_threads_init().
1457 *
1458 * @see eina_threads_init()
1459 */
1460void
1461eina_log_threads_init(void)
1462{
1463 if (_threads_inited) return;
1464 _main_thread = SELF();
1465 if (!INIT()) return;
1466 _threads_inited = EINA_TRUE;
1467}
1468
1469/**
1470 * @internal
1471 * @brief Shut down the log mutex.
1472 *
1473 * This function shuts down the mutex in the log module.
1474 * It is called by eina_threads_shutdown().
1475 *
1476 * @see eina_threads_shutdown()
1477 */
1478void
1479eina_log_threads_shutdown(void)
1480{
1481 if (!_threads_inited) return;
1482 CHECK_MAIN();
1483 SHUTDOWN();
1484 _threads_enabled = EINA_FALSE;
1485 _threads_inited = EINA_FALSE;
1486}
1487
1488#endif
1489
1490/*============================================================================*
1491* API *
1492*============================================================================*/
1493
1494/**
1495 * @cond LOCAL
1496 */
1497
1498EAPI int EINA_LOG_DOMAIN_GLOBAL = 0;
1499
1500/**
1501 * @endcond
1502 */
1503
1504EAPI void
1505eina_log_threads_enable(void)
1506{
1507#ifdef EFL_HAVE_THREADS
1508 if (_threads_enabled) return;
1509 if (!_threads_inited) eina_log_threads_init();
1510 _threads_enabled = EINA_TRUE;
1511 eina_log_print_prefix_update();
1512#endif
1513}
1514
1515EAPI void
1516eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data)
1517{
1518 LOG_LOCK();
1519 _print_cb = cb;
1520 _print_cb_data = data;
1521 eina_log_print_prefix_update();
1522 LOG_UNLOCK();
1523}
1524
1525EAPI void
1526eina_log_level_set(int level)
1527{
1528 _log_level = level;
1529 if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) &&
1530 ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count)))
1531 _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level;
1532}
1533
1534EAPI int
1535eina_log_level_get(void)
1536{
1537 return _log_level;
1538}
1539
1540EAPI Eina_Bool
1541eina_log_main_thread_check(void)
1542{
1543#ifdef EFL_HAVE_THREADS
1544 return ((!_threads_enabled) || IS_MAIN(SELF()));
1545#else
1546 return EINA_TRUE;
1547#endif
1548}
1549
1550EAPI void
1551eina_log_color_disable_set(Eina_Bool disabled)
1552{
1553 _disable_color = disabled;
1554}
1555
1556EAPI Eina_Bool
1557eina_log_color_disable_get(void)
1558{
1559 return _disable_color;
1560}
1561
1562EAPI void
1563eina_log_file_disable_set(Eina_Bool disabled)
1564{
1565 _disable_file = disabled;
1566}
1567
1568EAPI Eina_Bool
1569eina_log_file_disable_get(void)
1570{
1571 return _disable_file;
1572}
1573
1574EAPI void
1575eina_log_function_disable_set(Eina_Bool disabled)
1576{
1577 _disable_function = disabled;
1578}
1579
1580EAPI Eina_Bool
1581eina_log_function_disable_get(void)
1582{
1583 return _disable_function;
1584}
1585
1586EAPI void
1587eina_log_abort_on_critical_set(Eina_Bool abort_on_critical)
1588{
1589 _abort_on_critical = abort_on_critical;
1590}
1591
1592EAPI Eina_Bool
1593eina_log_abort_on_critical_get(void)
1594{
1595 return _abort_on_critical;
1596}
1597
1598EAPI void
1599eina_log_abort_on_critical_level_set(int critical_level)
1600{
1601 _abort_level_on_critical = critical_level;
1602}
1603
1604EAPI int
1605eina_log_abort_on_critical_level_get(void)
1606{
1607 return _abort_level_on_critical;
1608}
1609
1610EAPI int
1611eina_log_domain_register(const char *name, const char *color)
1612{
1613 int r;
1614
1615 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
1616
1617 LOG_LOCK();
1618 r = eina_log_domain_register_unlocked(name, color);
1619 LOG_UNLOCK();
1620 return r;
1621}
1622
1623EAPI void
1624eina_log_domain_unregister(int domain)
1625{
1626 EINA_SAFETY_ON_FALSE_RETURN(domain >= 0);
1627 LOG_LOCK();
1628 eina_log_domain_unregister_unlocked(domain);
1629 LOG_UNLOCK();
1630}
1631
1632EAPI void
1633eina_log_domain_level_set(const char *domain_name, int level)
1634{
1635 Eina_Log_Domain_Level_Pending *pending;
1636 size_t namelen;
1637 unsigned int i;
1638
1639 EINA_SAFETY_ON_NULL_RETURN(domain_name);
1640
1641 namelen = strlen(domain_name);
1642
1643 for (i = 0; i < _log_domains_count; i++)
1644 {
1645 if (_log_domains[i].deleted)
1646 continue;
1647
1648 if ((namelen != _log_domains[i].namelen) ||
1649 (strcmp(_log_domains[i].name, domain_name) != 0))
1650 continue;
1651
1652 _log_domains[i].level = level;
1653 return;
1654 }
1655
1656 EINA_INLIST_FOREACH(_pending_list, pending)
1657 {
1658 if ((namelen == pending->namelen) &&
1659 (strcmp(pending->name, domain_name) == 0))
1660 {
1661 pending->level = level;
1662 return;
1663 }
1664 }
1665
1666 pending = malloc(sizeof(Eina_Log_Domain_Level_Pending) + namelen + 1);
1667 if (!pending)
1668 return;
1669
1670 pending->level = level;
1671 pending->namelen = namelen;
1672 memcpy(pending->name, domain_name, namelen + 1);
1673
1674 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(pending));
1675}
1676
1677EAPI int
1678eina_log_domain_level_get(const char *domain_name)
1679{
1680 Eina_Log_Domain_Level_Pending *pending;
1681 size_t namelen;
1682 unsigned int i;
1683
1684 EINA_SAFETY_ON_NULL_RETURN_VAL(domain_name, EINA_LOG_LEVEL_UNKNOWN);
1685
1686 namelen = strlen(domain_name);
1687
1688 for (i = 0; i < _log_domains_count; i++)
1689 {
1690 if (_log_domains[i].deleted)
1691 continue;
1692
1693 if ((namelen != _log_domains[i].namelen) ||
1694 (strcmp(_log_domains[i].name, domain_name) != 0))
1695 continue;
1696
1697 return _log_domains[i].level;
1698 }
1699
1700 EINA_INLIST_FOREACH(_pending_list, pending)
1701 {
1702 if ((namelen == pending->namelen) &&
1703 (strcmp(pending->name, domain_name) == 0))
1704 return pending->level;
1705 }
1706
1707 EINA_INLIST_FOREACH(_glob_list, pending)
1708 {
1709 if (!fnmatch(pending->name, domain_name, 0))
1710 return pending->level;
1711 }
1712
1713 return _log_level;
1714}
1715
1716EAPI int
1717eina_log_domain_registered_level_get(int domain)
1718{
1719 EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN);
1720 EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count,
1721 EINA_LOG_LEVEL_UNKNOWN);
1722 EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted,
1723 EINA_LOG_LEVEL_UNKNOWN);
1724 return _log_domains[domain].level;
1725}
1726
1727EAPI void
1728eina_log_print_cb_stderr(const Eina_Log_Domain *d,
1729 Eina_Log_Level level,
1730 const char *file,
1731 const char *fnc,
1732 int line,
1733 const char *fmt,
1734 __UNUSED__ void *data,
1735 va_list args)
1736{
1737 _eina_log_print_prefix(stderr, d, level, file, fnc, line);
1738 vfprintf(stderr, fmt, args);
1739 putc('\n', stderr);
1740}
1741
1742EAPI void
1743eina_log_print_cb_stdout(const Eina_Log_Domain *d,
1744 Eina_Log_Level level,
1745 const char *file,
1746 const char *fnc,
1747 int line,
1748 const char *fmt,
1749 __UNUSED__ void *data,
1750 va_list args)
1751{
1752 _eina_log_print_prefix(stdout, d, level, file, fnc, line);
1753 vprintf(fmt, args);
1754 putchar('\n');
1755}
1756
1757EAPI void
1758eina_log_print_cb_file(const Eina_Log_Domain *d,
1759 __UNUSED__ Eina_Log_Level level,
1760 const char *file,
1761 const char *fnc,
1762 int line,
1763 const char *fmt,
1764 void *data,
1765 va_list args)
1766{
1767 FILE *f = data;
1768#ifdef EFL_HAVE_THREADS
1769 if (_threads_enabled)
1770 {
1771 Thread cur;
1772
1773 cur = SELF();
1774 if (IS_OTHER(cur))
1775 {
1776 fprintf(f, "%s[T:%lu] %s:%d %s() ", d->name, (unsigned long)cur,
1777 file, line, fnc);
1778 goto end;
1779 }
1780 }
1781
1782#endif
1783 fprintf(f, "%s<%u> %s:%d %s() ", d->name, eina_log_pid_get(),
1784 file, line, fnc);
1785#ifdef EFL_HAVE_THREADS
1786end:
1787#endif
1788 vfprintf(f, fmt, args);
1789 putc('\n', f);
1790}
1791
1792EAPI void
1793eina_log_print(int domain, Eina_Log_Level level, const char *file,
1794 const char *fnc, int line, const char *fmt, ...)
1795{
1796 va_list args;
1797
1798#ifdef EINA_SAFETY_CHECKS
1799 if (EINA_UNLIKELY(!file))
1800 {
1801 fputs("ERR: eina_log_print() file == NULL\n", stderr);
1802 return;
1803 }
1804
1805 if (EINA_UNLIKELY(!fnc))
1806 {
1807 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
1808 return;
1809 }
1810
1811 if (EINA_UNLIKELY(!fmt))
1812 {
1813 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
1814 return;
1815 }
1816
1817#endif
1818 va_start(args, fmt);
1819 LOG_LOCK();
1820 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
1821 LOG_UNLOCK();
1822 va_end(args);
1823}
1824
1825EAPI void
1826eina_log_vprint(int domain, Eina_Log_Level level, const char *file,
1827 const char *fnc, int line, const char *fmt, va_list args)
1828{
1829#ifdef EINA_SAFETY_CHECKS
1830 if (EINA_UNLIKELY(!file))
1831 {
1832 fputs("ERR: eina_log_print() file == NULL\n", stderr);
1833 return;
1834 }
1835
1836 if (EINA_UNLIKELY(!fnc))
1837 {
1838 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
1839 return;
1840 }
1841
1842 if (EINA_UNLIKELY(!fmt))
1843 {
1844 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
1845 return;
1846 }
1847
1848#endif
1849 LOG_LOCK();
1850 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
1851 LOG_UNLOCK();
1852}
diff --git a/libraries/eina/src/lib/eina_magic.c b/libraries/eina/src/lib/eina_magic.c
new file mode 100644
index 0000000..1adde92
--- /dev/null
+++ b/libraries/eina/src/lib/eina_magic.c
@@ -0,0 +1,320 @@
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#include <stdlib.h>
24#include <string.h>
25
26#ifdef HAVE_EVIL
27# include <Evil.h>
28#endif
29
30#include "eina_config.h"
31#include "eina_private.h"
32#include "eina_error.h"
33#include "eina_log.h"
34
35/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
36#include "eina_safety_checks.h"
37#include "eina_magic.h"
38
39/*============================================================================*
40* Local *
41*============================================================================*/
42
43/**
44 * @cond LOCAL
45 */
46
47typedef struct _Eina_Magic_String Eina_Magic_String;
48struct _Eina_Magic_String
49{
50 Eina_Magic magic;
51 Eina_Bool string_allocated;
52 const char *string;
53};
54
55static int _eina_magic_string_log_dom = -1;
56
57#ifdef ERR
58#undef ERR
59#endif
60#define ERR(...) EINA_LOG_DOM_ERR(_eina_magic_string_log_dom, __VA_ARGS__)
61
62#ifdef DBG
63#undef DBG
64#endif
65#define DBG(...) EINA_LOG_DOM_DBG(_eina_magic_string_log_dom, __VA_ARGS__)
66
67static Eina_Magic_String *_eina_magic_strings = NULL;
68static size_t _eina_magic_strings_count = 0;
69static size_t _eina_magic_strings_allocated = 0;
70static Eina_Bool _eina_magic_strings_dirty = 0;
71
72static int
73_eina_magic_strings_sort_cmp(const void *p1, const void *p2)
74{
75 const Eina_Magic_String *a = p1, *b = p2;
76 return a->magic - b->magic;
77}
78
79static int
80_eina_magic_strings_find_cmp(const void *p1, const void *p2)
81{
82 Eina_Magic a = (Eina_Magic)p1;
83 const Eina_Magic_String *b = p2;
84 return a - b->magic;
85}
86
87static Eina_Magic_String *
88_eina_magic_strings_alloc(void)
89{
90 size_t idx;
91
92 if (_eina_magic_strings_count == _eina_magic_strings_allocated)
93 {
94 void *tmp;
95 size_t size;
96
97 if (EINA_UNLIKELY(_eina_magic_strings_allocated == 0))
98 size = 48;
99 else
100 size = _eina_magic_strings_allocated + 16;
101
102 tmp = realloc(_eina_magic_strings, sizeof(Eina_Magic_String) * size);
103 if (!tmp)
104 {
105#ifdef _WIN32
106 ERR("could not realloc magic_strings from %Iu to %Iu buckets.",
107 _eina_magic_strings_allocated, size);
108#else
109 ERR("could not realloc magic_strings from %zu to %zu buckets.",
110 _eina_magic_strings_allocated, size);
111#endif
112 return NULL;
113 }
114
115 _eina_magic_strings = tmp;
116 _eina_magic_strings_allocated = size;
117 }
118
119 idx = _eina_magic_strings_count;
120 _eina_magic_strings_count++;
121 return _eina_magic_strings + idx;
122}
123
124/**
125 * @endcond
126 */
127
128/*============================================================================*
129* Global *
130*============================================================================*/
131
132/**
133 * @internal
134 * @brief Initialize the magic string module.
135 *
136 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
137 *
138 * This function sets up the magic string module of Eina. It is called by
139 * eina_init().
140 *
141 * @see eina_init()
142 */
143Eina_Bool
144eina_magic_string_init(void)
145{
146 _eina_magic_string_log_dom = eina_log_domain_register
147 ("eina_magic_string", EINA_LOG_COLOR_DEFAULT);
148 if (_eina_magic_string_log_dom < 0)
149 {
150 EINA_LOG_ERR("Could not register log domain: eina_magic_string");
151 return EINA_FALSE;
152 }
153
154 return EINA_TRUE;
155}
156
157/**
158 * @internal
159 * @brief Shut down the magic string module.
160 *
161 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
162 *
163 * This function shuts down the magic string module set up by
164 * eina_magic string_init(). It is called by eina_shutdown().
165 *
166 * @see eina_shutdown()
167 */
168Eina_Bool
169eina_magic_string_shutdown(void)
170{
171 Eina_Magic_String *ems, *ems_end;
172
173 ems = _eina_magic_strings;
174 ems_end = ems + _eina_magic_strings_count;
175
176 for (; ems < ems_end; ems++)
177 if (ems->string_allocated)
178 free((char *)ems->string);
179
180 free(_eina_magic_strings);
181 _eina_magic_strings = NULL;
182 _eina_magic_strings_count = 0;
183 _eina_magic_strings_allocated = 0;
184
185 eina_log_domain_unregister(_eina_magic_string_log_dom);
186 _eina_magic_string_log_dom = -1;
187
188 return EINA_TRUE;
189}
190
191/*============================================================================*
192* API *
193*============================================================================*/
194EAPI const char *
195eina_magic_string_get(Eina_Magic magic)
196{
197 Eina_Magic_String *ems;
198
199 if (!_eina_magic_strings)
200 return "(none)";
201
202 if (_eina_magic_strings_dirty)
203 {
204 qsort(_eina_magic_strings, _eina_magic_strings_count,
205 sizeof(Eina_Magic_String), _eina_magic_strings_sort_cmp);
206 _eina_magic_strings_dirty = 0;
207 }
208
209 ems = bsearch((void *)magic, _eina_magic_strings,
210 _eina_magic_strings_count, sizeof(Eina_Magic_String),
211 _eina_magic_strings_find_cmp);
212 if (ems)
213 return ems->string ? ems->string : "(undefined)";
214
215 return "(unknown)";
216}
217
218EAPI Eina_Bool
219eina_magic_string_set(Eina_Magic magic, const char *magic_name)
220{
221 Eina_Magic_String *ems;
222
223 EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE);
224
225 ems = _eina_magic_strings_alloc();
226 if (!ems)
227 return EINA_FALSE;
228
229 ems->magic = magic;
230 ems->string_allocated = EINA_TRUE;
231 ems->string = strdup(magic_name);
232 if (!ems->string)
233 {
234 ERR("could not allocate string '%s'", magic_name);
235 _eina_magic_strings_count--;
236 return EINA_FALSE;
237 }
238
239 _eina_magic_strings_dirty = 1;
240 return EINA_TRUE;
241}
242
243EAPI Eina_Bool
244eina_magic_string_static_set(Eina_Magic magic, const char *magic_name)
245{
246 Eina_Magic_String *ems;
247
248 EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE);
249
250 ems = _eina_magic_strings_alloc();
251 if (!ems)
252 return EINA_FALSE;
253
254 ems->magic = magic;
255 ems->string_allocated = EINA_FALSE;
256 ems->string = magic_name;
257
258 _eina_magic_strings_dirty = 1;
259 return EINA_TRUE;
260}
261
262#ifdef eina_magic_fail
263# undef eina_magic_fail
264#endif
265
266EAPI void
267eina_magic_fail(void *d,
268 Eina_Magic m,
269 Eina_Magic req_m,
270 const char *file,
271 const char *fnc,
272 int line)
273{
274 if (!d)
275 eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
276 file, fnc, line,
277 "*** Eina Magic Check Failed !!!\n"
278 " Input handle pointer is NULL !\n"
279 "*** NAUGHTY PROGRAMMER!!!\n"
280 "*** SPANK SPANK SPANK!!!\n"
281 "*** Now go fix your code. Tut tut tut!\n"
282 "\n");
283 else
284 if (m == EINA_MAGIC_NONE)
285 eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
286 file, fnc, line,
287 "*** Eina Magic Check Failed !!!\n"
288 " Input handle has already been freed!\n"
289 "*** NAUGHTY PROGRAMMER!!!\n"
290 "*** SPANK SPANK SPANK!!!\n"
291 "*** Now go fix your code. Tut tut tut!\n"
292 "\n");
293 else
294 if (m != req_m)
295 eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
296 file, fnc, line,
297 "*** Eina Magic Check Failed !!!\n"
298 " Input handle is wrong type\n"
299 " Expected: %08x - %s\n"
300 " Supplied: %08x - %s\n"
301 "*** NAUGHTY PROGRAMMER!!!\n"
302 "*** SPANK SPANK SPANK!!!\n"
303 "*** Now go fix your code. Tut tut tut!\n"
304 "\n",
305 req_m, eina_magic_string_get(req_m),
306 m, eina_magic_string_get(m));
307 else
308 eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
309 file, fnc, line,
310 "*** Eina Magic Check Failed !!!\n"
311 " Why did you call me !\n"
312 "*** NAUGHTY PROGRAMMER!!!\n"
313 "*** SPANK SPANK SPANK!!!\n"
314 "*** Now go fix your code. Tut tut tut!\n"
315 "\n");
316}
317
318/**
319 * @}
320 */
diff --git a/libraries/eina/src/lib/eina_main.c b/libraries/eina/src/lib/eina_main.c
new file mode 100644
index 0000000..8727f83
--- /dev/null
+++ b/libraries/eina/src/lib/eina_main.c
@@ -0,0 +1,431 @@
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#include <stdio.h>
24
25#ifdef EFL_HAVE_WIN32_THREADS
26# define WIN32_LEAN_AND_MEAN
27# include <windows.h>
28# undef WIN32_LEAN_AND_MEAN
29#endif
30
31#ifdef EFL_HAVE_THREADS
32# ifdef HAVE_SYS_TYPES_H
33# include <sys/types.h>
34# endif
35# ifdef HAVE_UNISTD_H
36# include <unistd.h>
37# endif
38#endif
39
40#ifdef HAVE_MCHECK
41# ifdef HAVE_MTRACE
42# define MT 1
43# endif
44#endif
45
46#ifdef MT
47#include <mcheck.h>
48#endif
49
50#include "eina_lock.h"
51#include "eina_config.h"
52#include "eina_private.h"
53#include "eina_types.h"
54#include "eina_main.h"
55#include "eina_error.h"
56#include "eina_log.h"
57#include "eina_hash.h"
58#include "eina_binshare.h"
59#include "eina_stringshare.h"
60#include "eina_ustringshare.h"
61#include "eina_list.h"
62#include "eina_matrixsparse.h"
63#include "eina_array.h"
64#include "eina_counter.h"
65#include "eina_benchmark.h"
66#include "eina_magic.h"
67#include "eina_rectangle.h"
68#include "eina_safety_checks.h"
69#include "eina_inlist.h"
70
71/*============================================================================*
72* Local *
73*============================================================================*/
74
75/**
76 * @cond LOCAL
77 */
78
79static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV };
80
81static int _eina_main_count = 0;
82#ifdef EFL_HAVE_THREADS
83static int _eina_main_thread_count = 0;
84#endif
85static int _eina_log_dom = -1;
86
87#ifdef ERR
88#undef ERR
89#endif
90#define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__)
91
92#ifdef DBG
93#undef DBG
94#endif
95#define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
96
97EAPI Eina_Bool _eina_threads_activated = EINA_FALSE;
98EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0;
99
100static const char EINA_ERROR_NOT_MAIN_LOOP_STR[] = "Main loop thread check failed.";
101
102#ifdef EFL_HAVE_THREADS
103# ifdef _WIN32
104EAPI DWORD _eina_main_loop;
105# else
106EAPI pthread_t _eina_main_loop;
107# endif
108static pid_t _eina_pid;
109#endif
110
111#ifdef MT
112static int _mt_enabled = 0;
113#endif
114
115#ifdef EFL_HAVE_THREADS
116EAPI int _eina_threads_debug = 0;
117# if !defined(_WIN32_WCE) && !defined(_WIN32)
118EAPI pthread_mutex_t _eina_tracking_lock;
119EAPI Eina_Inlist *_eina_tracking = NULL;
120# endif
121#endif
122
123/* place module init/shutdown functions here to avoid other modules
124 * calling them by mistake.
125 */
126#define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
127 extern Eina_Bool eina_ ## x ## _shutdown(void)
128 S(log);
129 S(error);
130 S(safety_checks);
131 S(magic_string);
132 S(iterator);
133 S(accessor);
134 S(array);
135 S(module);
136 S(mempool);
137 S(list);
138 S(binshare);
139 S(stringshare);
140 S(ustringshare);
141 S(matrixsparse);
142 S(convert);
143 S(counter);
144 S(benchmark);
145 S(rectangle);
146 S(strbuf);
147 S(ustrbuf);
148 S(quadtree);
149 S(simple_xml);
150 S(file);
151 S(prefix);
152#undef S
153
154struct eina_desc_setup
155{
156 const char *name;
157 Eina_Bool (*init)(void);
158 Eina_Bool (*shutdown)(void);
159};
160
161static const struct eina_desc_setup _eina_desc_setup[] = {
162#define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
163 /* log is a special case as it needs printf */
164 S(error),
165 S(safety_checks),
166 S(magic_string),
167 S(iterator),
168 S(accessor),
169 S(array),
170 S(module),
171 S(mempool),
172 S(list),
173 S(binshare),
174 S(stringshare),
175 S(ustringshare),
176 S(matrixsparse),
177 S(convert),
178 S(counter),
179 S(benchmark),
180 S(rectangle),
181 S(strbuf),
182 S(ustrbuf),
183 S(quadtree),
184 S(simple_xml),
185 S(file),
186 S(prefix)
187#undef S
188};
189static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
190 sizeof(_eina_desc_setup[0]);
191
192static void
193_eina_shutdown_from_desc(const struct eina_desc_setup *itr)
194{
195 for (itr--; itr >= _eina_desc_setup; itr--)
196 {
197 if (!itr->shutdown())
198 ERR("Problems shutting down eina module '%s', ignored.", itr->name);
199 }
200
201 eina_log_domain_unregister(_eina_log_dom);
202 _eina_log_dom = -1;
203 eina_log_shutdown();
204}
205
206/**
207 * @endcond
208 */
209
210/*============================================================================*
211* Global *
212*============================================================================*/
213
214
215/*============================================================================*
216* API *
217*============================================================================*/
218
219/**
220 * @var eina_version
221 * @brief Eina version (defined at configuration time)
222 */
223EAPI Eina_Version *eina_version = &_version;
224
225EAPI int
226eina_init(void)
227{
228 const struct eina_desc_setup *itr, *itr_end;
229
230 if (EINA_LIKELY(_eina_main_count > 0))
231 return ++_eina_main_count;
232
233#ifdef MT
234 if ((getenv("EINA_MTRACE")) && (getenv("MALLOC_TRACE")))
235 {
236 _mt_enabled = 1;
237 mtrace();
238 }
239#endif
240
241 if (!eina_log_init())
242 {
243 fprintf(stderr, "Could not initialize eina logging system.\n");
244 return 0;
245 }
246
247 _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
248 if (_eina_log_dom < 0)
249 {
250 EINA_LOG_ERR("Could not register log domain: eina");
251 eina_log_shutdown();
252 return 0;
253 }
254
255 EINA_ERROR_NOT_MAIN_LOOP = eina_error_msg_static_register(
256 EINA_ERROR_NOT_MAIN_LOOP_STR);
257
258#ifdef EFL_HAVE_THREADS
259# ifdef _WIN32
260 _eina_main_loop = GetCurrentThreadId();
261# else
262 _eina_main_loop = pthread_self();
263# endif
264 _eina_pid = getpid();
265#endif
266
267#ifdef EINA_HAVE_DEBUG_THREADS
268 pthread_mutex_init(&_eina_tracking_lock, NULL);
269
270 if (getenv("EINA_DEBUG_THREADS"))
271 _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
272#endif
273
274 itr = _eina_desc_setup;
275 itr_end = itr + _eina_desc_setup_len;
276 for (; itr < itr_end; itr++)
277 {
278 if (!itr->init())
279 {
280 ERR("Could not initialize eina module '%s'.", itr->name);
281 _eina_shutdown_from_desc(itr);
282 return 0;
283 }
284 }
285
286 _eina_main_count = 1;
287 return 1;
288}
289
290EAPI int
291eina_shutdown(void)
292{
293 _eina_main_count--;
294 if (EINA_UNLIKELY(_eina_main_count == 0))
295 {
296 _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
297
298#ifdef EINA_HAVE_DEBUG_THREADS
299 pthread_mutex_destroy(&_eina_tracking_lock);
300#endif
301#ifdef MT
302 if (_mt_enabled)
303 {
304 muntrace();
305 _mt_enabled = 0;
306 }
307#endif
308 }
309
310 return _eina_main_count;
311}
312
313
314EAPI int
315eina_threads_init(void)
316{
317#ifdef EFL_HAVE_THREADS
318 int ret;
319
320#ifdef EINA_HAVE_DEBUG_THREADS
321 assert(pthread_equal(_eina_main_loop, pthread_self()));
322#endif
323
324 ++_eina_main_thread_count;
325 ret = _eina_main_thread_count;
326
327 if(_eina_main_thread_count > 1)
328 return ret;
329
330 eina_share_common_threads_init();
331 eina_log_threads_init();
332 _eina_threads_activated = EINA_TRUE;
333
334 return ret;
335#else
336 return 0;
337#endif
338}
339
340EAPI int
341eina_threads_shutdown(void)
342{
343#ifdef EFL_HAVE_THREADS
344 int ret;
345
346#ifdef EINA_HAVE_DEBUG_THREADS
347 const Eina_Lock *lk;
348
349 assert(pthread_equal(_eina_main_loop, pthread_self()));
350 assert(_eina_main_thread_count > 0);
351#endif
352
353 ret = --_eina_main_thread_count;
354 if(_eina_main_thread_count > 0)
355 return ret;
356
357#ifdef EINA_HAVE_DEBUG_THREADS
358 pthread_mutex_lock(&_eina_tracking_lock);
359 if (_eina_tracking)
360 {
361 fprintf(stderr, "*************************\n");
362 fprintf(stderr, "* The IMPOSSIBLE HAPPEN *\n");
363 fprintf(stderr, "* LOCK STILL TAKEN : *\n");
364 fprintf(stderr, "*************************\n");
365 EINA_INLIST_FOREACH(_eina_tracking, lk)
366 eina_lock_debug(lk);
367 fprintf(stderr, "*************************\n");
368 abort();
369 }
370 pthread_mutex_unlock(&_eina_tracking_lock);
371#endif
372
373 eina_share_common_threads_shutdown();
374 eina_log_threads_shutdown();
375
376 _eina_threads_activated = EINA_FALSE;
377
378 return ret;
379#else
380 return 0;
381#endif
382}
383
384EAPI Eina_Bool
385eina_main_loop_is(void)
386{
387#ifdef EFL_HAVE_THREADS
388 pid_t pid = getpid();
389
390# ifdef _WIN32
391 if (pid != _eina_pid)
392 {
393 _eina_pid = pid;
394 _eina_main_loop = GetCurrentThreadId();
395 return EINA_TRUE;
396 }
397 if (_eina_main_loop == GetCurrentThreadId())
398 return EINA_TRUE;
399# else
400 if (pid != _eina_pid)
401 {
402 /* This is in case of a fork, but don't like the solution */
403 _eina_pid = pid;
404 _eina_main_loop = pthread_self();
405 return EINA_TRUE;
406 }
407
408 if (pthread_equal(_eina_main_loop, pthread_self()))
409 return EINA_TRUE;
410# endif
411#endif
412 return EINA_FALSE;
413}
414
415/** The purpose of this API should not be documented, it is used only by the one who know what they are doing. */
416EAPI void
417eina_main_loop_define(void)
418{
419#ifdef EFL_HAVE_THREADS
420 _eina_pid = getpid();
421# ifdef _WIN32
422 _eina_main_loop = GetCurrentThreadId();
423# else
424 _eina_main_loop = pthread_self();
425# endif
426#endif
427}
428
429/**
430 * @}
431 */
diff --git a/libraries/eina/src/lib/eina_matrixsparse.c b/libraries/eina/src/lib/eina_matrixsparse.c
new file mode 100644
index 0000000..3ac0439
--- /dev/null
+++ b/libraries/eina/src/lib/eina_matrixsparse.c
@@ -0,0 +1,1421 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2009 Gustavo Sverzut Barbieri
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/**
21 * @page tutorial_matrixsparse_page Sparse Matrix Tutorial
22 *
23 * to be written...
24 *
25 */
26
27#ifdef HAVE_CONFIG_H
28# include "config.h"
29#endif
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <assert.h>
35
36#ifdef HAVE_EVIL
37# include <Evil.h>
38#endif
39
40#include "eina_config.h"
41#include "eina_private.h"
42#include "eina_error.h"
43#include "eina_log.h"
44#include "eina_magic.h"
45#include "eina_mempool.h"
46
47/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
48#include "eina_safety_checks.h"
49#include "eina_matrixsparse.h"
50
51
52/*============================================================================*
53* Local *
54*============================================================================*/
55
56/**
57 * @cond LOCAL
58 */
59
60static const char EINA_MAGIC_MATRIXSPARSE_STR[] = "Eina Matrixsparse";
61static const char EINA_MAGIC_MATRIXSPARSE_ROW_STR[] = "Eina Matrixsparse Row";
62static const char EINA_MAGIC_MATRIXSPARSE_CELL_STR[] = "Eina Matrixsparse Cell";
63static const char EINA_MAGIC_MATRIXSPARSE_ITERATOR_STR[] =
64 "Eina Matrixsparse Iterator";
65static const char EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR_STR[] =
66 "Eina Matrixsparse Row Accessor";
67static const char EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR_STR[] =
68 "Eina Matrixsparse Row Iterator";
69static const char EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR_STR[] =
70 "Eina Matrixsparse Cell Accessor";
71static const char EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR_STR[] =
72 "Eina Matrixsparse Cell Iterator";
73
74
75#define EINA_MAGIC_CHECK_MATRIXSPARSE(d, ...) \
76 do { \
77 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE)) \
78 { \
79 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE); \
80 return __VA_ARGS__; \
81 } \
82 } while(0)
83
84#define EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(d, ...) \
85 do { \
86 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ROW)) \
87 { \
88 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ROW); \
89 return __VA_ARGS__; \
90 } \
91 } while(0)
92
93#define EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(d, ...) \
94 do { \
95 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_CELL)) \
96 { \
97 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_CELL); \
98 return __VA_ARGS__; \
99 } \
100 } while(0)
101
102#define EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(d, ...) \
103 do { \
104 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR)) \
105 { \
106 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR); \
107 return __VA_ARGS__; \
108 } \
109 } while(0)
110
111struct _Eina_Matrixsparse_Cell
112{
113 Eina_Matrixsparse_Cell *next;
114 Eina_Matrixsparse_Cell *prev;
115
116 void *data;
117 unsigned long col;
118
119 Eina_Matrixsparse_Row *parent;
120
121 EINA_MAGIC
122};
123
124struct _Eina_Matrixsparse_Row
125{
126 Eina_Matrixsparse_Row *next;
127 Eina_Matrixsparse_Row *prev;
128
129 Eina_Matrixsparse_Cell *cols;
130 Eina_Matrixsparse_Cell *last_col;
131 Eina_Matrixsparse_Cell *last_used; /* fast sequential access */
132 unsigned long row;
133
134 Eina_Matrixsparse *parent;
135
136 EINA_MAGIC
137};
138
139struct _Eina_Matrixsparse
140{
141 Eina_Matrixsparse_Row *rows;
142 Eina_Matrixsparse_Row *last_row;
143 Eina_Matrixsparse_Row *last_used; /* fast sequential access */
144
145 struct
146 {
147 unsigned long rows;
148 unsigned long cols;
149 } size;
150
151 struct
152 {
153 void (*func)(void *user_data, void *cell_data);
154 void *user_data;
155 } free;
156
157 EINA_MAGIC
158};
159
160typedef struct _Eina_Matrixsparse_Iterator Eina_Matrixsparse_Iterator;
161typedef struct _Eina_Matrixsparse_Iterator_Complete
162Eina_Matrixsparse_Iterator_Complete;
163
164struct _Eina_Matrixsparse_Iterator
165{
166 Eina_Iterator iterator;
167
168 const Eina_Matrixsparse *m;
169 struct
170 {
171 const Eina_Matrixsparse_Row *row;
172 const Eina_Matrixsparse_Cell *col;
173 } ref;
174
175 EINA_MAGIC
176};
177
178struct _Eina_Matrixsparse_Iterator_Complete
179{
180 Eina_Iterator iterator;
181
182 const Eina_Matrixsparse *m;
183 struct
184 {
185 const Eina_Matrixsparse_Row *row;
186 const Eina_Matrixsparse_Cell *col;
187 } ref;
188
189 struct
190 {
191 unsigned long row, col;
192 } idx;
193
194 struct
195 {
196 Eina_Matrixsparse_Row row;
197 Eina_Matrixsparse_Cell col;
198 } dummy;
199
200 EINA_MAGIC
201};
202
203/**
204 * @todo Eina_Matrixsparse_Row_Iterator: iterator over rows in matrix
205 * @todo Eina_Matrixsparse_Row_Accessor: accessor over rows in matrix
206 * @todo Eina_Matrixsparse_Cell_Iterator: iterator over cells in row
207 * @todo Eina_Matrixsparse_Cell_Accessor: accessor over cells in row
208 */
209
210static int _eina_matrixsparse_log_dom = -1;
211
212#ifdef ERR
213#undef ERR
214#endif
215#define ERR(...) EINA_LOG_DOM_ERR(_eina_matrixsparse_log_dom, __VA_ARGS__)
216
217#ifdef DBG
218#undef DBG
219#endif
220#define DBG(...) EINA_LOG_DOM_DBG(_eina_matrixsparse_log_dom, __VA_ARGS__)
221
222static Eina_Mempool *_eina_matrixsparse_cell_mp = NULL;
223static Eina_Mempool *_eina_matrixsparse_row_mp = NULL;
224
225static inline void
226_eina_matrixsparse_cell_free(Eina_Matrixsparse_Cell *c, void (*free_func)(
227 void *,
228 void *), void *user_data)
229{
230 if (free_func)
231 free_func(user_data, c->data);
232
233 EINA_MAGIC_SET(c, EINA_MAGIC_NONE);
234 eina_mempool_free(_eina_matrixsparse_cell_mp, c);
235}
236
237static inline void
238_eina_matrixsparse_cell_unlink(Eina_Matrixsparse_Cell *c)
239{
240 Eina_Matrixsparse_Row *r = c->parent;
241
242 if (r->last_used == c)
243 {
244 if (c->next)
245 r->last_used = c->next;
246 else
247 r->last_used = c->prev;
248 }
249
250 if (r->last_col == c)
251 r->last_col = c->prev;
252
253 if (r->cols == c)
254 r->cols = c->next;
255
256 if (c->next && c->prev)
257 {
258 c->next->prev = c->prev;
259 c->prev->next = c->next;
260 }
261 else if (c->next)
262 c->next->prev = NULL;
263 else if (c->prev)
264 c->prev->next = NULL;
265}
266
267static inline void
268_eina_matrixsparse_row_cells_free(Eina_Matrixsparse_Row *r, void (*free_func)(
269 void *,
270 void *), void *user_data)
271{
272 Eina_Matrixsparse_Cell *c = r->cols;
273 while (c)
274 {
275 Eina_Matrixsparse_Cell *c_aux = c;
276 c = c->next;
277 _eina_matrixsparse_cell_free(c_aux, free_func, user_data);
278 }
279}
280
281static inline void
282_eina_matrixsparse_row_free(Eina_Matrixsparse_Row *r, void (*free_func)(void *,
283 void *),
284 void *user_data)
285{
286 _eina_matrixsparse_row_cells_free(r, free_func, user_data);
287 EINA_MAGIC_SET(r, EINA_MAGIC_NONE);
288 eina_mempool_free(_eina_matrixsparse_row_mp, r);
289}
290
291static inline void
292_eina_matrixsparse_row_unlink(Eina_Matrixsparse_Row *r)
293{
294 Eina_Matrixsparse *m = r->parent;
295
296 if (m->last_used == r)
297 {
298 if (r->next)
299 m->last_used = r->next;
300 else
301 m->last_used = r->prev;
302 }
303
304 if (m->last_row == r)
305 m->last_row = r->prev;
306
307 if (m->rows == r)
308 m->rows = r->next;
309
310 if (r->next && r->prev)
311 {
312 r->next->prev = r->prev;
313 r->prev->next = r->next;
314 }
315 else if (r->next)
316 r->next->prev = NULL;
317 else if (r->prev)
318 r->prev->next = NULL;
319}
320
321static inline void
322_eina_matrixsparse_row_find_parms_get(const Eina_Matrixsparse *m,
323 unsigned long row,
324 Eina_Matrixsparse_Row **p_r,
325 int *p_dir)
326{
327 Eina_Matrixsparse_Row *r;
328 unsigned long dist;
329 int dir;
330
331 dist = row - m->rows->row;
332 r = m->rows;
333 dir = 1;
334 if (dist > m->last_row->row - row)
335 {
336 dist = m->last_row->row - row;
337 r = m->last_row;
338 dir = -1;
339 }
340
341 if (m->last_used)
342 {
343 if (m->last_used->row < row)
344 {
345 if (dist > row - m->last_used->row)
346 {
347/* dist = row = m->last_used->row; */
348 r = m->last_used;
349 dir = 1;
350 }
351 }
352 else if (dist > m->last_used->row - row)
353 {
354/* dist = m->last_used->row - row; */
355 r = m->last_used;
356 dir = -1;
357 }
358 }
359
360 *p_r = r;
361 *p_dir = dir;
362}
363
364static inline void
365_eina_matrixsparse_row_cell_find_parms_get(const Eina_Matrixsparse_Row *r,
366 unsigned long col,
367 Eina_Matrixsparse_Cell **p_c,
368 int *p_dir)
369{
370 Eina_Matrixsparse_Cell *c;
371 unsigned long dist;
372 int dir;
373
374 dist = col - r->cols->col;
375 c = r->cols;
376 dir = 1;
377 if (dist > r->last_col->col - col)
378 {
379 dist = r->last_col->col - col;
380 c = r->last_col;
381 dir = -1;
382 }
383
384 if (r->last_used)
385 {
386 if (r->last_used->col < col)
387 {
388 if (dist > col - r->last_used->col)
389 {
390/* dist = col = r->last_used->col; */
391 c = r->last_used;
392 dir = 1;
393 }
394 }
395 else if (dist > r->last_used->col - col)
396 {
397/* dist = r->last_used->col - col; */
398 c = r->last_used;
399 dir = -1;
400 }
401 }
402
403 *p_c = c;
404 *p_dir = dir;
405}
406
407static inline Eina_Matrixsparse_Row *
408_eina_matrixsparse_row_idx_get(const Eina_Matrixsparse *m, unsigned long row)
409{
410 Eina_Matrixsparse_Row *r;
411 int dir;
412
413 if (!m->rows)
414 return NULL;
415
416 if (m->rows->row == row)
417 return m->rows;
418 else if (m->rows->row > row)
419 return NULL;
420
421 if (m->last_row->row == row)
422 return m->last_row;
423 else if (m->last_row->row < row)
424 return NULL;
425
426 if ((m->last_used) && (m->last_used->row == row))
427 return m->last_used;
428
429 _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir);
430 assert(dir != 0);
431 if (dir > 0)
432 {
433 for (; r; r = r->next)
434 if (r->row == row)
435 {
436 ((Eina_Matrixsparse *)m)->last_used = r;
437 return r;
438 }
439 else if (r->row > row)
440 return NULL;
441
442 }
443 else if (dir < 0)
444 {
445 for (; r; r = r->prev)
446 if (r->row == row)
447 {
448 ((Eina_Matrixsparse *)m)->last_used = r;
449 return r;
450 }
451 else if (r->row < row)
452 return NULL;
453 }
454
455 return NULL;
456}
457
458static inline Eina_Matrixsparse_Cell *
459_eina_matrixsparse_row_cell_idx_get(const Eina_Matrixsparse_Row *r,
460 unsigned long col)
461{
462 Eina_Matrixsparse_Cell *c;
463 int dir;
464
465 if (!r->cols)
466 return NULL;
467
468 if (r->cols->col == col)
469 return r->cols;
470 else if (r->cols->col > col)
471 return NULL;
472
473 if (r->last_col->col == col)
474 return r->last_col;
475 else if (r->last_col->col < col)
476 return NULL;
477
478 if ((r->last_used) && (r->last_used->col == col))
479 return r->last_used;
480
481 _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir);
482 assert(dir != 0);
483 if (dir > 0)
484 {
485 for (; r; c = c->next)
486 if (c->col == col)
487 {
488 ((Eina_Matrixsparse_Row *)r)->last_used = c;
489 return c;
490 }
491 else if (c->col > col)
492 return NULL;
493
494 }
495 else if (dir < 0)
496 {
497 for (; r; c = c->prev)
498 if (c->col == col)
499 {
500 ((Eina_Matrixsparse_Row *)r)->last_used = c;
501 return c;
502 }
503 else if (c->col < col)
504 return NULL;
505 }
506
507 return NULL;
508}
509
510static inline Eina_Matrixsparse_Cell *
511_eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m,
512 unsigned long row,
513 unsigned long col)
514{
515 Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row);
516 if (!r)
517 return NULL;
518
519 return _eina_matrixsparse_row_cell_idx_get(r, col);
520}
521
522static inline void
523_eina_matrixsparse_row_idx_siblings_find(const Eina_Matrixsparse *m,
524 unsigned long row,
525 Eina_Matrixsparse_Row **p_prev,
526 Eina_Matrixsparse_Row **p_next)
527{
528 Eina_Matrixsparse_Row *r;
529 int dir;
530
531 _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir);
532 assert(dir != 0);
533 if (dir > 0)
534 {
535 for (; r; r = r->next)
536 if (r->row > row)
537 break;
538
539 assert(r != NULL);
540 *p_prev = r->prev;
541 *p_next = r;
542 }
543 else if (dir < 0)
544 {
545 for (; r; r = r->prev)
546 if (r->row < row)
547 break;
548
549 assert(r != NULL);
550 *p_prev = r;
551 *p_next = r->next;
552 }
553}
554
555static inline void
556_eina_matrixsparse_row_cell_idx_siblings_find(const Eina_Matrixsparse_Row *r,
557 unsigned long col,
558 Eina_Matrixsparse_Cell **p_prev,
559 Eina_Matrixsparse_Cell **p_next)
560{
561 Eina_Matrixsparse_Cell *c;
562 int dir;
563
564 _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir);
565 assert(dir != 0);
566 if (dir > 0)
567 {
568 for (; c; c = c->next)
569 if (c->col > col)
570 break;
571
572 assert(c != NULL);
573 *p_prev = c->prev;
574 *p_next = c;
575 }
576 else if (dir < 0)
577 {
578 for (; c; c = c->prev)
579 if (c->col < col)
580 break;
581
582 assert(c != NULL);
583 *p_prev = c;
584 *p_next = c->next;
585 }
586}
587
588static inline Eina_Matrixsparse_Row *
589_eina_matrixsparse_row_idx_add(Eina_Matrixsparse *m, unsigned long row)
590{
591 Eina_Matrixsparse_Row *r = eina_mempool_malloc
592 (_eina_matrixsparse_row_mp, sizeof(Eina_Matrixsparse_Row));
593 if (!r)
594 return NULL;
595
596 if (!m->rows)
597 {
598 r->prev = NULL;
599 r->next = NULL;
600 m->rows = r;
601 m->last_row = r;
602 }
603 else if (row < m->rows->row)
604 {
605 r->prev = NULL;
606 r->next = m->rows;
607 m->rows->prev = r;
608 m->rows = r;
609 }
610 else if (row > m->last_row->row)
611 {
612 r->prev = m->last_row;
613 m->last_row->next = r;
614 r->next = NULL;
615 m->last_row = r;
616 }
617 else
618 {
619 Eina_Matrixsparse_Row *prev = NULL, *next = NULL;
620 _eina_matrixsparse_row_idx_siblings_find(m, row, &prev, &next);
621 assert(prev != NULL);
622 assert(next != NULL);
623 r->prev = prev;
624 r->next = next;
625 prev->next = r;
626 next->prev = r;
627 }
628
629 r->cols = NULL;
630 r->last_col = NULL;
631 r->last_used = NULL;
632 r->row = row;
633 r->parent = m;
634 EINA_MAGIC_SET(r, EINA_MAGIC_MATRIXSPARSE_ROW);
635 m->last_used = r;
636 return r;
637}
638
639static inline Eina_Matrixsparse_Cell *
640_eina_matrixsparse_row_cell_idx_add(Eina_Matrixsparse_Row *r,
641 unsigned long col,
642 const void *data)
643{
644 Eina_Matrixsparse_Cell *c = eina_mempool_malloc
645 (_eina_matrixsparse_cell_mp, sizeof(Eina_Matrixsparse_Cell));
646 if (!c)
647 return NULL;
648
649 if (!r->cols)
650 {
651 c->prev = NULL;
652 c->next = NULL;
653 r->cols = c;
654 r->last_col = c;
655 }
656 else if (col < r->cols->col)
657 {
658 c->prev = NULL;
659 c->next = r->cols;
660 r->cols->prev = c;
661 r->cols = c;
662 }
663 else if (col > r->last_col->col)
664 {
665 c->prev = r->last_col;
666 r->last_col->next = c;
667 c->next = NULL;
668 r->last_col = c;
669 }
670 else
671 {
672 Eina_Matrixsparse_Cell *prev = NULL, *next = NULL;
673 _eina_matrixsparse_row_cell_idx_siblings_find(r, col, &prev, &next);
674 assert(prev != NULL);
675 assert(next != NULL);
676 c->prev = prev;
677 c->next = next;
678 prev->next = c;
679 next->prev = c;
680 }
681
682 c->data = (void *)data;
683 c->col = col;
684 c->parent = r;
685 EINA_MAGIC_SET(c, EINA_MAGIC_MATRIXSPARSE_CELL);
686 r->last_used = c;
687 return c;
688}
689
690static inline Eina_Bool
691_eina_matrixsparse_cell_idx_add(Eina_Matrixsparse *m,
692 unsigned long row,
693 unsigned long col,
694 const void *data)
695{
696 Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row);
697 if (!r)
698 r = _eina_matrixsparse_row_idx_add(m, row);
699
700 if (!r)
701 return 0;
702
703 if (_eina_matrixsparse_row_cell_idx_add(r, col, data))
704 return 1;
705
706 if (r->cols)
707 return 0;
708
709 _eina_matrixsparse_row_unlink(r);
710 _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data);
711 return 0;
712}
713
714/*============================================================================*
715* Iterators *
716*============================================================================*/
717static Eina_Bool
718_eina_matrixsparse_iterator_next(Eina_Matrixsparse_Iterator *it, void **data)
719{
720 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE);
721
722 /* do not touch it->idx */
723
724 if (!it->ref.col)
725 return 0;
726
727 *data = (Eina_Matrixsparse_Cell *)it->ref.col;
728
729 it->ref.col = it->ref.col->next;
730 if (!it->ref.col)
731 {
732 it->ref.row = it->ref.row->next;
733 if (it->ref.row)
734 it->ref.col = it->ref.row->cols;
735 }
736
737 return 1;
738}
739
740static Eina_Matrixsparse *
741_eina_matrixsparse_iterator_get_container(Eina_Matrixsparse_Iterator *it)
742{
743 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL);
744 return (Eina_Matrixsparse *)it->m;
745}
746
747static void
748_eina_matrixsparse_iterator_free(Eina_Matrixsparse_Iterator *it)
749{
750 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it);
751 EINA_MAGIC_SET(it, EINA_MAGIC_NONE);
752 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
753 free(it);
754}
755
756static Eina_Bool
757_eina_matrixsparse_iterator_complete_next(
758 Eina_Matrixsparse_Iterator_Complete *it,
759 void **data)
760{
761 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE);
762
763 if (it->idx.row >= it->m->size.rows)
764 return 0;
765
766 if (it->dummy.col.data)
767 ERR("Last iterator call changed dummy cell!");
768
769 if ((it->ref.col) &&
770 (it->ref.col->col == it->idx.col) &&
771 (it->ref.row->row == it->idx.row))
772 {
773 *data = (Eina_Matrixsparse_Cell *)it->ref.col;
774 it->ref.col = it->ref.col->next;
775 if (!it->ref.col)
776 {
777 it->ref.row = it->ref.row->next;
778 if (it->ref.row)
779 it->ref.col = it->ref.row->cols;
780 }
781 }
782 else
783 {
784 it->dummy.col.data = NULL;
785 it->dummy.col.col = it->idx.col;
786 it->dummy.row.row = it->idx.row;
787 *data = &it->dummy.col;
788 }
789
790 it->idx.col++;
791 if (it->idx.col == it->m->size.cols)
792 {
793 it->idx.col = 0;
794 it->idx.row++;
795 }
796
797 return 1;
798}
799
800static Eina_Matrixsparse *
801_eina_matrixsparse_iterator_complete_get_container(
802 Eina_Matrixsparse_Iterator_Complete *it)
803{
804 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL);
805 return (Eina_Matrixsparse *)it->m;
806}
807
808static void
809_eina_matrixsparse_iterator_complete_free(
810 Eina_Matrixsparse_Iterator_Complete *it)
811{
812 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it);
813
814 if (it->dummy.col.data)
815 ERR("Last iterator call changed dummy cell!");
816
817 EINA_MAGIC_SET(it, EINA_MAGIC_NONE);
818 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
819 free(it);
820}
821
822
823/**
824 * @endcond
825 */
826
827/*============================================================================*
828* Global *
829*============================================================================*/
830
831/**
832 * @internal
833 * @brief Initialize the matrixsparse module.
834 *
835 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
836 *
837 * This function sets up the matrixsparse module of Eina. It is called by
838 * eina_init().
839 *
840 * This function creates mempool to speed up matrix rows and cells
841 * management, using EINA_MEMPOOL environment variable if it is set to
842 * choose the memory pool type to use.
843 *
844 * @see eina_init()
845 */
846Eina_Bool
847eina_matrixsparse_init(void)
848{
849 const char *choice, *tmp;
850
851 _eina_matrixsparse_log_dom = eina_log_domain_register("eina_matrixsparse",
852 EINA_LOG_COLOR_DEFAULT);
853 if (_eina_matrixsparse_log_dom < 0)
854 {
855 EINA_LOG_ERR("Could not register log domain: eina_matrixsparse");
856 return EINA_FALSE;
857 }
858
859#ifdef EINA_DEFAULT_MEMPOOL
860 choice = "pass_through";
861#else
862 choice = "chained_mempool";
863#endif
864 tmp = getenv("EINA_MEMPOOL");
865 if (tmp && tmp[0])
866 choice = tmp;
867
868 _eina_matrixsparse_cell_mp = eina_mempool_add
869 (choice,
870 "matrixsparse_cell",
871 NULL,
872 sizeof (Eina_Matrixsparse_Cell),
873 120);
874 if (!_eina_matrixsparse_cell_mp)
875 {
876 ERR(
877 "Mempool for matrixsparse_cell cannot be allocated in matrixsparse init.");
878 goto on_init_fail;
879 }
880
881 _eina_matrixsparse_row_mp = eina_mempool_add
882 (choice, "matrixsparse_row", NULL, sizeof (Eina_Matrixsparse_Row), 120);
883 if (!_eina_matrixsparse_row_mp)
884 {
885 ERR(
886 "Mempool for matrixsparse_row cannot be allocated in matrixsparse init.");
887 goto on_init_fail;
888 }
889
890#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
891 EMS(EINA_MAGIC_MATRIXSPARSE);
892 EMS(EINA_MAGIC_MATRIXSPARSE_ROW);
893 EMS(EINA_MAGIC_MATRIXSPARSE_CELL);
894 EMS(EINA_MAGIC_MATRIXSPARSE_ITERATOR);
895 EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR);
896 EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR);
897 EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR);
898 EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR);
899#undef EMS
900
901 return EINA_TRUE;
902
903on_init_fail:
904 eina_log_domain_unregister(_eina_matrixsparse_log_dom);
905 _eina_matrixsparse_log_dom = -1;
906 return EINA_FALSE;
907}
908
909/**
910 * @internal
911 * @brief Shut down the matrixsparse module.
912 *
913 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
914 *
915 * This function shuts down the matrixsparse module set up by
916 * eina_matrixsparse_init(). It is called by eina_shutdown().
917 *
918 * @see eina_shutdown()
919 */
920Eina_Bool
921eina_matrixsparse_shutdown(void)
922{
923 eina_mempool_del(_eina_matrixsparse_row_mp);
924 eina_mempool_del(_eina_matrixsparse_cell_mp);
925
926 eina_log_domain_unregister(_eina_matrixsparse_log_dom);
927 _eina_matrixsparse_log_dom = -1;
928 return EINA_TRUE;
929}
930
931/*============================================================================*
932* API *
933*============================================================================*/
934
935EAPI Eina_Matrixsparse *
936eina_matrixsparse_new(unsigned long rows, unsigned long cols, void (*free_func)(
937 void *user_data,
938 void *cell_data), const void *user_data)
939{
940 Eina_Matrixsparse *m;
941
942 EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, NULL);
943 EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, NULL);
944
945 m = malloc(sizeof(Eina_Matrixsparse));
946 if (!m)
947 {
948 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
949 return NULL;
950 }
951
952 EINA_MAGIC_SET(m, EINA_MAGIC_MATRIXSPARSE);
953
954 m->rows = NULL;
955 m->last_row = NULL;
956 m->last_used = NULL;
957
958 m->size.rows = rows;
959 m->size.cols = cols;
960 m->free.func = free_func;
961 m->free.user_data = (void *)user_data;
962
963 eina_error_set(0);
964 return m;
965}
966
967EAPI void
968eina_matrixsparse_free(Eina_Matrixsparse *m)
969{
970 void (*free_func)(void *, void *);
971 void *user_data;
972
973 Eina_Matrixsparse_Row *r;
974 EINA_MAGIC_CHECK_MATRIXSPARSE(m);
975
976 free_func = m->free.func;
977 user_data = m->free.user_data;
978
979 r = m->rows;
980 while (r)
981 {
982 Eina_Matrixsparse_Row *r_aux = r;
983 r = r->next;
984 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
985 }
986
987 EINA_MAGIC_SET(m, EINA_MAGIC_NONE);
988 free(m);
989}
990
991EAPI void
992eina_matrixsparse_size_get(const Eina_Matrixsparse *m,
993 unsigned long *rows,
994 unsigned long *cols)
995{
996 if (rows)
997 *rows = 0;
998
999 if (cols)
1000 *cols = 0;
1001
1002 EINA_MAGIC_CHECK_MATRIXSPARSE(m);
1003 if (rows)
1004 *rows = m->size.rows;
1005
1006 if (cols)
1007 *cols = m->size.cols;
1008}
1009
1010EAPI Eina_Bool
1011eina_matrixsparse_size_set(Eina_Matrixsparse *m,
1012 unsigned long rows,
1013 unsigned long cols)
1014{
1015 Eina_Bool update_last_used_row;
1016 Eina_Matrixsparse_Row *r;
1017 void (*free_func)(void *, void *);
1018 void *user_data;
1019
1020 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1021 EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, 0);
1022 EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, 0);
1023
1024 if ((rows == m->size.rows) && (cols == m->size.cols))
1025 return 1;
1026
1027 update_last_used_row = ((m->last_used) && (m->last_used->row >= rows));
1028 free_func = m->free.func;
1029 user_data = m->free.user_data;
1030
1031 r = m->last_row;
1032 while (r && r->row >= rows)
1033 {
1034 Eina_Matrixsparse_Row *r_aux = r;
1035 r = r->prev;
1036 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1037 }
1038 if (!r)
1039 {
1040 m->last_row = NULL;
1041 m->rows = NULL;
1042 }
1043 else if (r != m->last_row)
1044 {
1045 r->next = NULL;
1046 m->last_row = r;
1047 }
1048
1049 if (update_last_used_row)
1050 m->last_used = m->last_row;
1051
1052 r = m->rows;
1053 while (r)
1054 {
1055 Eina_Matrixsparse_Cell *c = r->last_col;
1056 Eina_Bool update_last_used_col;
1057 update_last_used_col = ((r->last_used) && (r->last_used->col >= cols));
1058 while (c && c->col >= cols)
1059 {
1060 Eina_Matrixsparse_Cell *c_aux = c;
1061 c = c->prev;
1062 _eina_matrixsparse_cell_free(c_aux, free_func, user_data);
1063 }
1064 if (!c)
1065 {
1066 Eina_Matrixsparse_Row *r_aux = r;
1067 r->cols = NULL;
1068 r->last_col = NULL;
1069 if (r->next)
1070 r->next->prev = r->prev;
1071 else
1072 m->last_row = r->prev;
1073
1074 if (r->prev)
1075 r->prev->next = r->next;
1076 else
1077 m->rows = r->next;
1078
1079 r = r->next;
1080 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1081 }
1082 else
1083 {
1084 if (c != r->last_col)
1085 {
1086 c->next = NULL;
1087 r->last_col = c;
1088 }
1089
1090 if (update_last_used_col)
1091 r->last_used = r->last_col;
1092
1093 r = r->next;
1094 }
1095 }
1096
1097 update_last_used_row = 0;
1098 if (m->last_used)
1099 {
1100 if (m->last_row)
1101 update_last_used_row = m->last_used->row > m->last_row->row;
1102 else
1103 update_last_used_row = 1;
1104 }
1105
1106 if (update_last_used_row)
1107 m->last_used = m->last_row;
1108
1109 m->size.rows = rows;
1110 m->size.cols = cols;
1111 return 1;
1112}
1113
1114EAPI Eina_Bool
1115eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m,
1116 unsigned long row,
1117 unsigned long col,
1118 Eina_Matrixsparse_Cell **cell)
1119{
1120 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1121 EINA_SAFETY_ON_NULL_RETURN_VAL(cell, 0);
1122 *cell = NULL;
1123 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1124 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1125 *cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1126 return 1;
1127}
1128
1129EAPI void *
1130eina_matrixsparse_cell_data_get(const Eina_Matrixsparse_Cell *cell)
1131{
1132 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, NULL);
1133 return cell->data;
1134}
1135
1136EAPI void *
1137eina_matrixsparse_data_idx_get(const Eina_Matrixsparse *m,
1138 unsigned long row,
1139 unsigned long col)
1140{
1141 Eina_Matrixsparse_Cell *c;
1142 EINA_MAGIC_CHECK_MATRIXSPARSE(m, NULL);
1143 c = _eina_matrixsparse_cell_idx_get(m, row, col);
1144 if (c)
1145 return c->data;
1146 else
1147 return NULL;
1148}
1149
1150EAPI Eina_Bool
1151eina_matrixsparse_cell_position_get(const Eina_Matrixsparse_Cell *cell,
1152 unsigned long *row,
1153 unsigned long *col)
1154{
1155 if (row)
1156 *row = 0;
1157
1158 if (col)
1159 *col = 0;
1160
1161 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1162 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1163 if (row)
1164 *row = cell->parent->row;
1165
1166 if (col)
1167 *col = cell->col;
1168
1169 return 1;
1170}
1171
1172EAPI Eina_Bool
1173eina_matrixsparse_cell_data_replace(Eina_Matrixsparse_Cell *cell,
1174 const void *data,
1175 void **p_old)
1176{
1177 if (p_old)
1178 *p_old = NULL;
1179
1180 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1181
1182 if (p_old)
1183 *p_old = cell->data;
1184
1185 cell->data = (void *)data;
1186 return 1;
1187}
1188
1189EAPI Eina_Bool
1190eina_matrixsparse_cell_data_set(Eina_Matrixsparse_Cell *cell, const void *data)
1191{
1192 Eina_Matrixsparse *m;
1193
1194 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1195 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1196 EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0);
1197
1198 m = cell->parent->parent;
1199
1200 if (m->free.func)
1201 m->free.func(m->free.user_data, cell->data);
1202
1203 cell->data = (void *)data;
1204 return 1;
1205}
1206
1207EAPI Eina_Bool
1208eina_matrixsparse_data_idx_replace(Eina_Matrixsparse *m,
1209 unsigned long row,
1210 unsigned long col,
1211 const void *data,
1212 void **p_old)
1213{
1214 Eina_Matrixsparse_Cell *cell;
1215
1216 if (p_old)
1217 *p_old = NULL;
1218
1219 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1220 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1221 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1222
1223 cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1224 if (cell)
1225 {
1226 if (p_old)
1227 *p_old = cell->data;
1228
1229 cell->data = (void *)data;
1230 return 1;
1231 }
1232
1233 return _eina_matrixsparse_cell_idx_add(m, row, col, data);
1234}
1235
1236EAPI Eina_Bool
1237eina_matrixsparse_data_idx_set(Eina_Matrixsparse *m,
1238 unsigned long row,
1239 unsigned long col,
1240 const void *data)
1241{
1242 Eina_Matrixsparse_Cell *cell;
1243
1244 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1245 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1246 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1247
1248 cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1249 if (cell)
1250 {
1251 if (m->free.func)
1252 m->free.func(m->free.user_data, cell->data);
1253
1254 cell->data = (void *)data;
1255 return 1;
1256 }
1257
1258 return _eina_matrixsparse_cell_idx_add(m, row, col, data);
1259}
1260
1261EAPI Eina_Bool
1262eina_matrixsparse_row_idx_clear(Eina_Matrixsparse *m, unsigned long row)
1263{
1264 Eina_Matrixsparse_Row *r;
1265
1266 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1267 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1268
1269 r = _eina_matrixsparse_row_idx_get(m, row);
1270 if (!r)
1271 return 1;
1272
1273 _eina_matrixsparse_row_unlink(r);
1274 _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data);
1275
1276 return 1;
1277}
1278
1279EAPI Eina_Bool
1280eina_matrixsparse_column_idx_clear(Eina_Matrixsparse *m, unsigned long col)
1281{
1282 Eina_Matrixsparse_Row *r;
1283 void (*free_func)(void *, void *);
1284 void *user_data;
1285
1286 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1287 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1288
1289 free_func = m->free.func;
1290 user_data = m->free.user_data;
1291
1292 for (r = m->rows; r; )
1293 {
1294 Eina_Matrixsparse_Row *r_aux = r;
1295 Eina_Matrixsparse_Cell *c;
1296
1297 c = _eina_matrixsparse_row_cell_idx_get(r, col);
1298 r = r->next;
1299
1300 if (!c)
1301 continue;
1302
1303 if ((r_aux->cols != c) || (r_aux->last_col != c))
1304 {
1305 _eina_matrixsparse_cell_unlink(c);
1306 _eina_matrixsparse_cell_free(c, free_func, user_data);
1307 }
1308 else
1309 {
1310 _eina_matrixsparse_row_unlink(r_aux);
1311 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1312 }
1313 }
1314
1315 return 1;
1316}
1317
1318EAPI Eina_Bool
1319eina_matrixsparse_cell_idx_clear(Eina_Matrixsparse *m,
1320 unsigned long row,
1321 unsigned long col)
1322{
1323 Eina_Matrixsparse_Cell *c;
1324
1325 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1326 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1327 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1328
1329 c = _eina_matrixsparse_cell_idx_get(m, row, col);
1330 if (!c)
1331 return 1;
1332
1333 _eina_matrixsparse_cell_unlink(c);
1334 _eina_matrixsparse_cell_free(c, m->free.func, m->free.user_data);
1335
1336 return 1;
1337}
1338
1339EAPI Eina_Bool
1340eina_matrixsparse_cell_clear(Eina_Matrixsparse_Cell *cell)
1341{
1342 Eina_Matrixsparse *m;
1343
1344 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1345 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1346 EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0);
1347
1348 m = cell->parent->parent;
1349
1350 _eina_matrixsparse_cell_unlink(cell);
1351 _eina_matrixsparse_cell_free(cell, m->free.func, m->free.user_data);
1352 return 1;
1353}
1354
1355EAPI Eina_Iterator *
1356eina_matrixsparse_iterator_new(const Eina_Matrixsparse *m)
1357{
1358 Eina_Matrixsparse_Iterator *it;
1359
1360 it = calloc(1, sizeof(*it));
1361 if (!it)
1362 {
1363 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1364 return NULL;
1365 }
1366
1367 EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR);
1368 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1369
1370 it->m = m;
1371 it->ref.row = m->rows;
1372 it->ref.col = m->rows ? m->rows->cols : NULL;
1373
1374 it->iterator.version = EINA_ITERATOR_VERSION;
1375 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_matrixsparse_iterator_next);
1376 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1377 _eina_matrixsparse_iterator_get_container);
1378 it->iterator.free = FUNC_ITERATOR_FREE(_eina_matrixsparse_iterator_free);
1379 return &it->iterator;
1380}
1381
1382EAPI Eina_Iterator *
1383eina_matrixsparse_iterator_complete_new(const Eina_Matrixsparse *m)
1384{
1385 Eina_Matrixsparse_Iterator_Complete *it;
1386
1387 it = calloc(1, sizeof(*it));
1388 if (!it)
1389 {
1390 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1391 return NULL;
1392 }
1393
1394 EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR);
1395 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1396
1397 it->m = m;
1398 it->idx.row = 0;
1399 it->idx.col = 0;
1400 it->ref.row = m->rows;
1401 it->ref.col = m->rows ? m->rows->cols : NULL;
1402
1403 it->dummy.row.next = it->dummy.row.prev = NULL;
1404 it->dummy.row.cols = it->dummy.row.last_col = it->dummy.row.last_used = NULL;
1405 it->dummy.row.parent = (Eina_Matrixsparse *)m;
1406 EINA_MAGIC_SET(&it->dummy.row, EINA_MAGIC_MATRIXSPARSE_ROW);
1407
1408 it->dummy.col.next = it->dummy.col.prev = NULL;
1409 it->dummy.col.data = NULL;
1410 it->dummy.col.parent = &it->dummy.row;
1411 EINA_MAGIC_SET(&it->dummy.col, EINA_MAGIC_MATRIXSPARSE_CELL);
1412
1413 it->iterator.version = EINA_ITERATOR_VERSION;
1414 it->iterator.next = FUNC_ITERATOR_NEXT(
1415 _eina_matrixsparse_iterator_complete_next);
1416 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1417 _eina_matrixsparse_iterator_complete_get_container);
1418 it->iterator.free = FUNC_ITERATOR_FREE(
1419 _eina_matrixsparse_iterator_complete_free);
1420 return &it->iterator;
1421}
diff --git a/libraries/eina/src/lib/eina_mempool.c b/libraries/eina/src/lib/eina_mempool.c
new file mode 100644
index 0000000..065532e
--- /dev/null
+++ b/libraries/eina/src/lib/eina_mempool.c
@@ -0,0 +1,387 @@
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#include <assert.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "eina_config.h"
29#include "eina_private.h"
30#include "eina_hash.h"
31#include "eina_module.h"
32#include "eina_log.h"
33#include "eina_main.h"
34
35/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
36#include "eina_safety_checks.h"
37#include "eina_mempool.h"
38
39/*============================================================================*
40* Local *
41*============================================================================*/
42
43/**
44 * @cond LOCAL
45 */
46
47static Eina_Hash *_backends;
48static Eina_Array *_modules;
49static int _eina_mempool_log_dom = -1;
50
51#ifdef ERR
52#undef ERR
53#endif
54#define ERR(...) EINA_LOG_DOM_ERR(_eina_mempool_log_dom, __VA_ARGS__)
55
56#ifdef DBG
57#undef DBG
58#endif
59#define DBG(...) EINA_LOG_DOM_DBG(_eina_mempool_log_dom, __VA_ARGS__)
60
61
62static Eina_Mempool *
63_new_va(const char *name,
64 const char *context,
65 const char *options,
66 va_list args)
67{
68 Eina_Mempool_Backend *be;
69 Eina_Mempool *mp;
70
71 Eina_Error err = EINA_ERROR_NOT_MEMPOOL_MODULE;
72
73 eina_error_set(0);
74 be = eina_hash_find(_backends, name);
75 if ((!be) || (!be->init))
76 goto on_error;
77
78 err = EINA_ERROR_OUT_OF_MEMORY;
79 mp = calloc(1, sizeof(Eina_Mempool));
80 if (!mp)
81 goto on_error;
82
83 /* Work around ABI incompability introduced in Eina 1.1 */
84#define SBP(Property) mp->backend.Property = be->Property;
85 SBP(name);
86 SBP(init);
87 SBP(free);
88 SBP(alloc);
89 SBP(realloc);
90 SBP(garbage_collect);
91 SBP(statistics);
92 SBP(shutdown);
93#undef SBP
94
95 if (be->repack)
96 {
97 mp->backend2 = calloc(1, sizeof (Eina_Mempool_Backend_ABI2));
98 if (mp->backend2)
99 mp->backend2->repack = be->repack;
100 }
101
102 mp->backend_data = mp->backend.init(context, options, args);
103
104 return mp;
105
106on_error:
107 eina_error_set(err);
108 return NULL;
109}
110
111/* Built-in backend's prototypes */
112
113#ifdef EINA_STATIC_BUILD_BUDDY
114Eina_Bool buddy_init(void);
115void buddy_shutdown(void);
116#endif
117
118#ifdef EINA_STATIC_BUILD_CHAINED_POOL
119Eina_Bool chained_init(void);
120void chained_shutdown(void);
121#endif
122
123#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
124Eina_Bool ememoa_fixed_init(void);
125void ememoa_fixed_shutdown(void);
126#endif
127
128#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
129Eina_Bool ememoa_unknown_init(void);
130void ememoa_unknown_shutdown(void);
131#endif
132
133#ifdef EINA_STATIC_BUILD_FIXED_BITMAP
134Eina_Bool fixed_bitmap_init(void);
135void fixed_bitmap_shutdown(void);
136#endif
137
138#ifdef EINA_STATIC_BUILD_ONE_BIG
139Eina_Bool one_big_init(void);
140void one_big_shutdown(void);
141#endif
142
143#ifdef EINA_STATIC_BUILD_PASS_THROUGH
144Eina_Bool pass_through_init(void);
145void pass_through_shutdown(void);
146#endif
147
148/**
149 * @endcond
150 */
151
152/*============================================================================*
153* Global *
154*============================================================================*/
155
156/**
157 * @cond LOCAL
158 */
159
160EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0;
161
162static const char EINA_ERROR_NOT_MEMPOOL_MODULE_STR[] =
163 "Not a memory pool module.";
164
165/**
166 * @endcond
167 */
168
169EAPI Eina_Bool
170eina_mempool_register(Eina_Mempool_Backend *be)
171{
172 EINA_SAFETY_ON_NULL_RETURN_VAL(be, 0);
173 DBG("be=%p, name=%p", be, be->name);
174 return eina_hash_add(_backends, be->name, be);
175}
176
177EAPI void
178eina_mempool_unregister(Eina_Mempool_Backend *be)
179{
180 EINA_SAFETY_ON_NULL_RETURN(be);
181 DBG("be=%p, name=%p", be, be->name);
182 eina_hash_del(_backends, be->name, be);
183}
184
185Eina_Bool
186eina_mempool_init(void)
187{
188 char *path;
189
190 _eina_mempool_log_dom = eina_log_domain_register("eina_mempool",
191 EINA_LOG_COLOR_DEFAULT);
192 if (_eina_mempool_log_dom < 0)
193 {
194 EINA_LOG_ERR("Could not register log domain: eina_mempool");
195 return 0;
196 }
197
198 EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_static_register(
199 EINA_ERROR_NOT_MEMPOOL_MODULE_STR);
200 _backends = eina_hash_string_superfast_new(NULL);
201
202 /* dynamic backends */
203 _modules = eina_module_arch_list_get(NULL,
204 PACKAGE_LIB_DIR "/eina/modules/mp",
205 MODULE_ARCH);
206
207 path = eina_module_environment_path_get("HOME", "/.eina/mp/modules/mp");
208 _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
209 if (path)
210 free(path);
211
212 path = eina_module_environment_path_get("EINA_MODULES_MEMPOOL_DIR",
213 "/eina/modules/mp");
214 _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
215 if (path)
216 free(path);
217
218 path = eina_module_symbol_path_get((const void *)eina_init,
219 "/eina/modules/mp");
220 _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
221 if (path)
222 free(path);
223
224 if (!_modules)
225 {
226 ERR("no mempool modules able to be loaded.");
227 eina_hash_free(_backends);
228 goto mempool_init_error;
229 }
230
231 eina_module_list_load(_modules);
232
233 /* builtin backends */
234#ifdef EINA_STATIC_BUILD_BUDDY
235 buddy_init();
236#endif
237#ifdef EINA_STATIC_BUILD_CHAINED_POOL
238 chained_init();
239#endif
240#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
241 ememoa_fixed_init();
242#endif
243#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
244 ememoa_unknown_init();
245#endif
246#ifdef EINA_STATIC_BUILD_FIXED_BITMAP
247 fixed_bitmap_init();
248#endif
249#ifdef EINA_STATIC_BUILD_ONE_BIG
250 one_big_init();
251#endif
252#ifdef EINA_STATIC_BUILD_PASS_THROUGH
253 pass_through_init();
254#endif
255
256 return EINA_TRUE;
257
258mempool_init_error:
259 eina_log_domain_unregister(_eina_mempool_log_dom);
260 _eina_mempool_log_dom = -1;
261
262 return EINA_FALSE;
263}
264
265Eina_Bool
266eina_mempool_shutdown(void)
267{
268 /* builtin backends */
269#ifdef EINA_STATIC_BUILD_BUDDY
270 buddy_shutdown();
271#endif
272#ifdef EINA_STATIC_BUILD_CHAINED_POOL
273 chained_shutdown();
274#endif
275#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
276 ememoa_fixed_shutdown();
277#endif
278#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
279 ememoa_unknown_shutdown();
280#endif
281#ifdef EINA_STATIC_BUILD_FIXED_BITMAP
282 fixed_bitmap_shutdown();
283#endif
284#ifdef EINA_STATIC_BUILD_ONE_BIG
285 one_big_shutdown();
286#endif
287#ifdef EINA_STATIC_BUILD_PASS_THROUGH
288 pass_through_shutdown();
289#endif
290 /* dynamic backends */
291 eina_module_list_free(_modules);
292 if (_modules)
293 eina_array_free(_modules);
294
295 if (_backends)
296 eina_hash_free(_backends);
297
298 eina_log_domain_unregister(_eina_mempool_log_dom);
299 _eina_mempool_log_dom = -1;
300
301 return EINA_TRUE;
302}
303
304/*============================================================================*
305* API *
306*============================================================================*/
307
308EAPI Eina_Mempool *
309eina_mempool_add(const char *name,
310 const char *context,
311 const char *options,
312 ...)
313{
314 Eina_Mempool *mp;
315 va_list args;
316
317 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
318 DBG("name=%s, context=%s, options=%s",
319 name, context ? context : "", options ? options : "");
320
321 va_start(args, options);
322 mp = _new_va(name, context, options, args);
323 va_end(args);
324
325 DBG("name=%s, context=%s, options=%s, mp=%p",
326 name, context ? context : "", options ? options : "", mp);
327
328 return mp;
329}
330
331EAPI void eina_mempool_del(Eina_Mempool *mp)
332{
333 EINA_SAFETY_ON_NULL_RETURN(mp);
334 EINA_SAFETY_ON_NULL_RETURN(mp->backend.shutdown);
335 DBG("mp=%p", mp);
336 mp->backend.shutdown(mp->backend_data);
337 free(mp->backend2);
338 free(mp);
339}
340
341EAPI void eina_mempool_repack(Eina_Mempool *mp, Eina_Mempool_Repack_Cb cb, void *data)
342{
343 EINA_SAFETY_ON_NULL_RETURN(mp);
344 EINA_SAFETY_ON_NULL_RETURN(mp->backend2);
345 EINA_SAFETY_ON_NULL_RETURN(mp->backend2->repack);
346 DBG("mp=%p", mp);
347 mp->backend2->repack(mp->backend_data, cb, data);
348}
349
350EAPI void eina_mempool_gc(Eina_Mempool *mp)
351{
352 EINA_SAFETY_ON_NULL_RETURN(mp);
353 EINA_SAFETY_ON_NULL_RETURN(mp->backend.garbage_collect);
354 DBG("mp=%p", mp);
355 mp->backend.garbage_collect(mp->backend_data);
356}
357
358EAPI void eina_mempool_statistics(Eina_Mempool *mp)
359{
360 EINA_SAFETY_ON_NULL_RETURN(mp);
361 EINA_SAFETY_ON_NULL_RETURN(mp->backend.statistics);
362 DBG("mp=%p", mp);
363 mp->backend.statistics(mp->backend_data);
364}
365
366EAPI unsigned int
367eina_mempool_alignof(unsigned int size)
368{
369 int align;
370
371 if (size <= 2)
372 align = 2;
373 else if (size < 8)
374 align = 4;
375 else
376#if __WORDSIZE == 32
377 align = 8;
378
379#else
380 if (size < 16)
381 align = 8;
382 else
383 align = 16;
384#endif
385
386 return ((size / align) + 1) * align;
387}
diff --git a/libraries/eina/src/lib/eina_mmap.c b/libraries/eina/src/lib/eina_mmap.c
new file mode 100644
index 0000000..fb27bd7
--- /dev/null
+++ b/libraries/eina/src/lib/eina_mmap.c
@@ -0,0 +1,185 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2011 Carsten Haitzler
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_SIGINFO_T
24
25#ifdef STDC_HEADERS
26# include <stdlib.h>
27# include <stddef.h>
28#else
29# ifdef HAVE_STDLIB_H
30# include <stdlib.h>
31# endif
32#endif
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <sys/mman.h>
40#include <limits.h>
41#include <signal.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <unistd.h>
45
46#if HAVE_SIGINFO_H
47# include <siginfo.h>
48#endif
49
50#endif
51
52#include "eina_config.h"
53#include "eina_private.h"
54#include "eina_log.h"
55#include "eina_mmap.h"
56
57/*============================================================================*
58 * Local *
59 *============================================================================*/
60
61static Eina_Bool mmap_safe = EINA_FALSE;
62#ifdef HAVE_SIGINFO_T
63
64static int _eina_mmap_log_dom = -1;
65static int _eina_mmap_zero_fd = -1;
66static long _eina_mmap_pagesize = -1;
67
68#ifdef ERR
69#undef ERR
70#endif
71#define ERR(...) EINA_LOG_DOM_ERR(_eina_mmap_log_dom, __VA_ARGS__)
72
73#ifdef DBG
74#undef DBG
75#endif
76#define DBG(...) EINA_LOG_DOM_DBG(_eina_mmap_log_dom, __VA_ARGS__)
77
78static void
79_eina_mmap_safe_sigbus(int sig __UNUSED__,
80 siginfo_t *siginfo,
81 void *ptr __UNUSED__)
82{
83 unsigned char *addr = (unsigned char *)(siginfo->si_addr);
84 int perrno;
85
86 /* save previous errno */
87 perrno = errno;
88 /* if problems was an unaligned access - complain accordingly and abort */
89 if (siginfo->si_code == BUS_ADRALN)
90 {
91 ERR("Unaligned memory access. SIGBUS!!!");
92 errno = perrno;
93 abort();
94 }
95 /* send this to stderr - not eina_log. Specifically want this on stderr */
96 fprintf(stderr,
97 "EINA: Data at address 0x%lx is invalid. Replacing with zero page.\n",
98 (unsigned long)addr);
99 /* align address to the lower page boundary */
100 addr = (unsigned char *)((long)addr & (~(_eina_mmap_pagesize - 1)));
101 /* mmap a pzge of zero's from /dev/zero in there */
102 if (mmap(addr, _eina_mmap_pagesize,
103 PROT_READ | PROT_WRITE | PROT_EXEC,
104 MAP_PRIVATE | MAP_FIXED,
105 _eina_mmap_zero_fd, 0) == MAP_FAILED)
106 {
107 /* mmap of /dev/zero failed :( */
108 perror("mmap");
109 ERR("Failed to mmap() /dev/zero in place of page. SIGBUS!!!");
110 errno = perrno;
111 abort();
112 }
113 /* restore previous errno */
114 errno = perrno;
115}
116#endif
117
118/*============================================================================*
119 * API *
120 *============================================================================*/
121
122EAPI Eina_Bool
123eina_mmap_safety_enabled_set(Eina_Bool enabled)
124{
125#ifndef HAVE_SIGINFO_T
126 (void) enabled;
127 return EINA_FALSE;
128#else
129 if (_eina_mmap_log_dom < 0)
130 {
131 _eina_mmap_log_dom = eina_log_domain_register("eina_mmap",
132 EINA_LOG_COLOR_DEFAULT);
133 if (_eina_mmap_log_dom < 0)
134 {
135 EINA_LOG_ERR("Could not register log domain: eina_mmap");
136 return EINA_FALSE;
137 }
138 }
139
140 enabled = !!enabled;
141
142 if (mmap_safe == enabled) return mmap_safe;
143 if (enabled)
144 {
145 struct sigaction sa;
146
147 /* find out system page size the cleanest way we can */
148#ifdef _SC_PAGESIZE
149 _eina_mmap_pagesize = sysconf(_SC_PAGESIZE);
150 if (_eina_mmap_pagesize <= 0) return EINA_FALSE;
151#else
152 _eina_mmap_pagesize = 4096;
153#endif
154 /* no zero page device - open it */
155 if (_eina_mmap_zero_fd < 0)
156 {
157 _eina_mmap_zero_fd = open("/dev/zero", O_RDWR);
158 /* if we don;'t have one - fail to set up mmap safety */
159 if (_eina_mmap_zero_fd < 0) return EINA_FALSE;
160 }
161 /* set up signal handler for SIGBUS */
162 sa.sa_sigaction = _eina_mmap_safe_sigbus;
163 sa.sa_flags = SA_RESTART | SA_SIGINFO;
164 sigemptyset(&sa.sa_mask);
165 if (sigaction(SIGBUS, &sa, NULL) == 0) return EINA_FALSE;
166 /* setup of SIGBUS handler failed, lets close zero page dev and fail */
167 close(_eina_mmap_zero_fd);
168 _eina_mmap_zero_fd = -1;
169 return EINA_FALSE;
170 }
171 else
172 {
173 /* reset signal handler to default for SIGBUS */
174 signal(SIGBUS, SIG_DFL);
175 }
176 mmap_safe = enabled;
177 return mmap_safe;
178#endif
179}
180
181EAPI Eina_Bool
182eina_mmap_safety_enabled_get(void)
183{
184 return mmap_safe;
185}
diff --git a/libraries/eina/src/lib/eina_module.c b/libraries/eina/src/lib/eina_module.c
new file mode 100644
index 0000000..0dd19a6
--- /dev/null
+++ b/libraries/eina/src/lib/eina_module.c
@@ -0,0 +1,599 @@
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#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 <stdio.h>
41#include <sys/types.h>
42#include <string.h>
43
44#ifdef HAVE_LIBGEN_H
45# include <libgen.h>
46#endif
47
48#ifdef HAVE_DLOPEN
49# include <dlfcn.h>
50#endif
51
52#ifdef HAVE_EVIL
53# include <Evil.h>
54#endif
55
56#ifdef HAVE_ESCAPE
57# include <Escape.h>
58#endif
59
60#include "eina_config.h"
61#include "eina_private.h"
62#include "eina_error.h"
63#include "eina_file.h"
64#include "eina_log.h"
65
66/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
67#include "eina_safety_checks.h"
68#include "eina_module.h"
69
70/*============================================================================*
71* Local *
72*============================================================================*/
73
74/**
75 * @cond LOCAL
76 */
77
78static int EINA_MODULE_LOG_DOM = -1;
79#ifdef ERR
80#undef ERR
81#endif
82#define ERR(...) EINA_LOG_DOM_ERR(EINA_MODULE_LOG_DOM, __VA_ARGS__)
83
84#ifdef WRN
85#undef WRN
86#endif
87#define WRN(...) EINA_LOG_DOM_WARN(EINA_MODULE_LOG_DOM, __VA_ARGS__)
88
89#ifdef DBG
90#undef DBG
91#endif
92#define DBG(...) EINA_LOG_DOM_DBG(EINA_MODULE_LOG_DOM, __VA_ARGS__)
93
94#ifdef _WIN32
95# define SEP_C '\\'
96# define SEP_S "\\"
97#else
98# define SEP_C '/'
99# define SEP_S "/"
100#endif
101
102#define EINA_MODULE_SYMBOL_INIT "__eina_module_init"
103#define EINA_MODULE_SYMBOL_SHUTDOWN "__eina_module_shutdown"
104
105struct _Eina_Module
106{
107 void *handle;
108 int ref;
109 const char file[];
110};
111
112typedef struct _Dir_List_Get_Cb_Data
113{
114 Eina_Module_Cb cb;
115 void *data;
116 Eina_Array *array;
117} Dir_List_Get_Cb_Data;
118
119typedef struct _Dir_List_Cb_Data
120{
121 Eina_Module_Cb cb;
122 void *data;
123} Dir_List_Cb_Data;
124
125static Eina_Bool _dir_list_get_cb(Eina_Module *m, void *data)
126{
127 Dir_List_Get_Cb_Data *cb_data = data;
128 Eina_Bool ret = EINA_TRUE;
129
130 if (cb_data->cb)
131 ret = cb_data->cb(m, cb_data->data);
132
133 if (ret)
134 eina_array_push(cb_data->array, m);
135
136 return ret;
137}
138
139static void _dir_list_cb(const char *name, const char *path, void *data)
140{
141 Dir_List_Cb_Data *cb_data = data;
142 size_t length;
143
144 length = strlen(name);
145 if (length < sizeof(SHARED_LIB_SUFFIX)) /* x.so */
146 return;
147
148 if (!strcmp(name + length - sizeof(SHARED_LIB_SUFFIX) + 1,
149 SHARED_LIB_SUFFIX))
150 {
151 char *file;
152 Eina_Module *m;
153
154 length = strlen(path) + strlen(name) + 2;
155
156 file = alloca(sizeof (char) * length);
157
158 snprintf(file, length, "%s" SEP_S "%s", path, name);
159 m = eina_module_new(file);
160 if (!m)
161 {
162 return; /* call the user provided cb on this module */
163
164 }
165
166 if (!cb_data->cb(m, cb_data->data))
167 eina_module_free(m);
168 }
169}
170
171static void _dir_arch_list_cb(const char *name, const char *path, void *data)
172{
173 Dir_List_Get_Cb_Data *cb_data = data;
174 Eina_Module *m;
175 char *file = NULL;
176 size_t length;
177
178 length = strlen(path) + 1 + strlen(name) + 1 +
179 strlen((char *)(cb_data->data)) + 1 + sizeof("module") +
180 sizeof(SHARED_LIB_SUFFIX) + 1;
181
182 file = alloca(length);
183 snprintf(file, length, "%s" SEP_S "%s" SEP_S "%s" SEP_S "module" SHARED_LIB_SUFFIX,
184 path, name, (char *)(cb_data->data));
185 m = eina_module_new(file);
186 if (!m)
187 return;
188
189 eina_array_push(cb_data->array, m);
190}
191
192/**
193 * @endcond
194 */
195
196
197/*============================================================================*
198* Global *
199*============================================================================*/
200
201/**
202 * @cond LOCAL
203 */
204
205static const char EINA_ERROR_WRONG_MODULE_STR[] =
206 "Wrong file format or no file module found";
207static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] =
208 "Module initialisation function failed";
209
210EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0;
211EAPI Eina_Error EINA_ERROR_MODULE_INIT_FAILED = 0;
212
213/**
214 * @endcond
215 */
216
217/**
218 * @internal
219 * @brief Initialize the module loader module.
220 *
221 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
222 *
223 * This function sets up the module loader module of Eina. It is
224 * called by eina_init().
225 *
226 * This function sets up the module module of Eina. It also registers
227 * the errors #EINA_ERROR_WRONG_MODULE and
228 * #EINA_ERROR_MODULE_INIT_FAILED.
229 *
230 * @see eina_init()
231 */
232Eina_Bool
233eina_module_init(void)
234{
235 EINA_MODULE_LOG_DOM = eina_log_domain_register
236 ("eina_module", EINA_LOG_COLOR_DEFAULT);
237 if (EINA_MODULE_LOG_DOM < 0)
238 {
239 EINA_LOG_ERR("Could not register log domain: eina_module");
240 return EINA_FALSE;
241 }
242
243#define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
244 EEMR(EINA_ERROR_WRONG_MODULE);
245 EEMR(EINA_ERROR_MODULE_INIT_FAILED);
246#undef EEMR
247
248 return EINA_TRUE;
249}
250
251/**
252 * @internal
253 * @brief Shut down the module loader module.
254 *
255 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
256 *
257 * This function shuts down the module loader module set up by
258 * eina_module_init(). It is called by eina_shutdown().
259 *
260 * @see eina_shutdown()
261 */
262Eina_Bool
263eina_module_shutdown(void)
264{
265 /* TODO should we store every module when "new" is called and
266 * delete the list of modules here
267 */
268
269 eina_log_domain_unregister(EINA_MODULE_LOG_DOM);
270 EINA_MODULE_LOG_DOM = -1;
271 return EINA_TRUE;
272}
273
274/*============================================================================*
275* API *
276*============================================================================*/
277
278EAPI Eina_Module *eina_module_new(const char *file)
279{
280 Eina_Module *m;
281 size_t len;
282
283 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
284 /* TODO check that the file exists. Update doc too */
285
286 len = strlen(file);
287 EINA_SAFETY_ON_FALSE_RETURN_VAL(len > 0, NULL);
288
289 m = malloc(sizeof(Eina_Module) + len + 1);
290 if (!m)
291 {
292 ERR("could not malloc(%lu)",
293 (unsigned long)(sizeof(Eina_Module) + len + 1));
294 return NULL;
295 }
296
297 memcpy((char *)m->file, file, len + 1);
298 m->ref = 0;
299 m->handle = NULL;
300 DBG("m=%p, file=%s", m, file);
301
302 return m;
303}
304
305EAPI Eina_Bool eina_module_free(Eina_Module *m)
306{
307 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
308
309 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
310
311 if (m->handle)
312 if (eina_module_unload(m) == EINA_FALSE)
313 return EINA_FALSE;
314
315 free(m);
316 return EINA_TRUE;
317}
318
319EAPI Eina_Bool eina_module_load(Eina_Module *m)
320{
321#ifdef HAVE_DLOPEN
322 void *dl_handle;
323 Eina_Module_Init *initcall;
324
325 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
326
327 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
328
329 if (m->handle)
330 goto loaded;
331
332 dl_handle = dlopen(m->file, RTLD_NOW);
333 if (!dl_handle)
334 {
335 WRN("could not dlopen(\"%s\", RTLD_NOW): %s", m->file, dlerror());
336 eina_error_set(EINA_ERROR_WRONG_MODULE);
337 return EINA_FALSE;
338 }
339
340 initcall = dlsym(dl_handle, EINA_MODULE_SYMBOL_INIT);
341 if ((!initcall) || (!(*initcall)))
342 goto ok;
343
344 if ((*initcall)() == EINA_TRUE)
345 goto ok;
346
347 WRN("could not find eina's entry symbol %s inside module %s",
348 EINA_MODULE_SYMBOL_INIT, m->file);
349 eina_error_set(EINA_ERROR_MODULE_INIT_FAILED);
350 dlclose(dl_handle);
351 return EINA_FALSE;
352ok:
353 DBG("successfully loaded %s", m->file);
354 m->handle = dl_handle;
355loaded:
356 m->ref++;
357 DBG("ref %d", m->ref);
358
359 eina_error_set(0);
360 return EINA_TRUE;
361#else
362 (void) m;
363 return EINA_FALSE;
364#endif
365}
366
367EAPI Eina_Bool eina_module_unload(Eina_Module *m)
368{
369#ifdef HAVE_DLOPEN
370 Eina_Module_Shutdown *shut;
371 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
372
373 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
374
375 m->ref--;
376 if (!m->ref)
377 {
378 shut = dlsym(m->handle, EINA_MODULE_SYMBOL_SHUTDOWN);
379 if ((shut) && (*shut))
380 (*shut)();
381
382 dlclose(m->handle);
383 m->handle = NULL;
384 DBG("unloaded module %s", m->file);
385 return EINA_TRUE;
386 }
387
388 return EINA_FALSE;
389#else
390 (void) m;
391 return EINA_FALSE;
392#endif
393}
394
395EAPI void *eina_module_symbol_get(const Eina_Module *m, const char *symbol)
396{
397#ifdef HAVE_DLOPEN
398 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
399 EINA_SAFETY_ON_NULL_RETURN_VAL(m->handle, NULL);
400 return dlsym(m->handle, symbol);
401#else
402 (void) m;
403 (void) symbol;
404 return NULL;
405#endif
406}
407
408EAPI const char *eina_module_file_get(const Eina_Module *m)
409{
410 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
411 return m->file;
412}
413
414EAPI char *eina_module_symbol_path_get(const void *symbol, const char *sub_dir)
415{
416#ifdef HAVE_DLADDR
417 Dl_info eina_dl;
418
419 EINA_SAFETY_ON_NULL_RETURN_VAL(symbol, NULL);
420
421 if (dladdr(symbol, &eina_dl))
422 {
423 char *pos = strrchr(eina_dl.dli_fname, SEP_C);
424 if (pos)
425 {
426 char *path;
427 int l0;
428 int l1;
429 int l2 = 0;
430
431 l0 = strlen(eina_dl.dli_fname);
432 l1 = strlen(pos);
433 if (sub_dir && (*sub_dir != '\0'))
434 l2 = strlen(sub_dir);
435
436 path = malloc(l0 - l1 + l2 + 1);
437 if (path)
438 {
439 memcpy(path, eina_dl.dli_fname, l0 - l1);
440 if (sub_dir && (*sub_dir != '\0'))
441 memcpy(path + l0 - l1, sub_dir, l2);
442
443 path[l0 - l1 + l2] = '\0';
444 return path;
445 }
446 }
447 }
448#else
449 (void) symbol;
450 (void) sub_dir;
451#endif /* ! HAVE_DLADDR */
452
453 return NULL;
454}
455
456EAPI char *eina_module_environment_path_get(const char *env,
457 const char *sub_dir)
458{
459 const char *env_dir;
460
461 EINA_SAFETY_ON_NULL_RETURN_VAL(env, NULL);
462
463 env_dir = getenv(env);
464 if (env_dir)
465 {
466 char *path;
467 size_t l1;
468 size_t l2 = 0;
469
470 l1 = strlen(env_dir);
471 if (sub_dir && (*sub_dir != '\0'))
472 l2 = strlen(sub_dir);
473
474 path = (char *)malloc(l1 + l2 + 1);
475 if (path)
476 {
477 memcpy(path, env_dir, l1);
478 if (sub_dir && (*sub_dir != '\0'))
479 memcpy(path + l1, sub_dir, l2);
480
481 path[l1 + l2] = '\0';
482
483 return path;
484 }
485 }
486
487 return NULL;
488}
489
490EAPI Eina_Array *eina_module_arch_list_get(Eina_Array *array,
491 const char *path,
492 const char *arch)
493{
494 Dir_List_Get_Cb_Data list_get_cb_data;
495
496 if ((!path) || (!arch))
497 return array;
498
499 list_get_cb_data.array = array ? array : eina_array_new(4);
500 list_get_cb_data.cb = NULL;
501 list_get_cb_data.data = (void *)arch;
502
503 eina_file_dir_list(path, 0, &_dir_arch_list_cb, &list_get_cb_data);
504
505 return list_get_cb_data.array;
506}
507
508EAPI Eina_Array *eina_module_list_get(Eina_Array *array,
509 const char *path,
510 Eina_Bool recursive,
511 Eina_Module_Cb cb,
512 void *data)
513{
514 Dir_List_Get_Cb_Data list_get_cb_data;
515 Dir_List_Cb_Data list_cb_data;
516
517 if (!path)
518 return array;
519
520 list_get_cb_data.array = array ? array : eina_array_new(4);
521 list_get_cb_data.cb = cb;
522 list_get_cb_data.data = data;
523
524 list_cb_data.cb = &_dir_list_get_cb;
525 list_cb_data.data = &list_get_cb_data;
526
527 eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data);
528
529 return list_get_cb_data.array;
530}
531
532EAPI Eina_Module *
533eina_module_find(const Eina_Array *array, const char *module)
534{
535 unsigned int i;
536 Eina_Array_Iterator iterator;
537 Eina_Module *m;
538
539 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
540 {
541 char *file_m;
542 char *tmp;
543 ssize_t len;
544
545 /* basename() can modify its argument, so we first get a copie */
546 /* do not use strdupa, as opensolaris does not have it */
547 len = strlen(eina_module_file_get(m));
548 tmp = alloca(len + 1);
549 memcpy(tmp, eina_module_file_get(m), len + 1);
550 file_m = basename(tmp);
551 len = strlen(file_m);
552 len -= sizeof(SHARED_LIB_SUFFIX) - 1;
553 if (len <= 0)
554 continue;
555
556 if (!strncmp(module, file_m, len))
557 return m;;
558 }
559
560 return NULL;
561}
562
563EAPI void eina_module_list_load(Eina_Array *array)
564{
565 Eina_Array_Iterator iterator;
566 Eina_Module *m;
567 unsigned int i;
568
569 EINA_SAFETY_ON_NULL_RETURN(array);
570 DBG("array %p, count %u", array, array->count);
571 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
572 eina_module_load(m);
573}
574
575EAPI void eina_module_list_unload(Eina_Array *array)
576{
577 Eina_Array_Iterator iterator;
578 Eina_Module *m;
579 unsigned int i;
580
581 EINA_SAFETY_ON_NULL_RETURN(array);
582 DBG("array %p, count %u", array, array->count);
583 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
584 eina_module_unload(m);
585}
586
587EAPI void eina_module_list_free(Eina_Array *array)
588{
589 Eina_Array_Iterator iterator;
590 Eina_Module *m;
591 unsigned int i;
592
593 EINA_SAFETY_ON_NULL_RETURN(array);
594 DBG("array %p, count %u", array, array->count);
595 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
596 eina_module_free(m);
597
598 eina_array_flush(array);
599}
diff --git a/libraries/eina/src/lib/eina_prefix.c b/libraries/eina/src/lib/eina_prefix.c
new file mode 100644
index 0000000..9445222
--- /dev/null
+++ b/libraries/eina/src/lib/eina_prefix.c
@@ -0,0 +1,727 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2011 Carsten Haitzler
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 STDC_HEADERS
24# include <stdlib.h>
25# include <stddef.h>
26#else
27# ifdef HAVE_STDLIB_H
28# include <stdlib.h>
29# endif
30#endif
31#ifdef HAVE_ALLOCA_H
32# include <alloca.h>
33#elif defined __GNUC__
34# define alloca __builtin_alloca
35#elif defined _AIX
36# define alloca __alloca
37#elif defined _MSC_VER
38# include <malloc.h>
39# define alloca _alloca
40#else
41# ifndef HAVE_ALLOCA
42# ifdef __cplusplus
43extern "C"
44# endif
45void *alloca (size_t);
46# endif
47#endif
48
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <sys/types.h>
53#include <sys/stat.h>
54#include <limits.h>
55
56#ifdef HAVE_UNISTD_H
57# include <unistd.h>
58#endif
59
60#ifdef HAVE_DLADDR
61# include <dlfcn.h>
62#endif
63
64#ifdef HAVE_EVIL
65# include <Evil.h>
66#endif
67
68#ifdef HAVE_ESCAPE
69# include <Escape.h>
70#endif
71
72#include "eina_config.h"
73#include "eina_private.h"
74#include "eina_log.h"
75#include "eina_prefix.h"
76
77#ifdef _WIN32
78# define PSEP_C ';'
79# define DSEP_C '\\'
80# define DSEP_S "\\"
81#else
82# define PSEP_C ':'
83# define DSEP_C '/'
84# define DSEP_S "/"
85#endif /* _WIN32 */
86
87/*============================================================================*
88 * Local *
89 *============================================================================*/
90
91/**
92 * @cond LOCAL
93 */
94
95struct _Eina_Prefix
96{
97 char *exe_path;
98
99 char *prefix_path;
100 char *prefix_path_bin;
101 char *prefix_path_data;
102 char *prefix_path_lib;
103 char *prefix_path_locale;
104
105 unsigned char fallback : 1;
106 unsigned char no_common_prefix : 1;
107 unsigned char env_used : 1;
108};
109
110#define STRDUP_REP(x, y) do { if (x) free(x); x = strdup(y); } while (0)
111#define IF_FREE_NULL(p) do { if (p) { free(p); p = NULL; } } while (0)
112
113#ifndef EINA_LOG_COLOR_DEFAULT
114#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
115#endif
116
117#ifdef ERR
118#undef ERR
119#endif
120#define ERR(...) EINA_LOG_DOM_ERR(_eina_prefix_log_dom, __VA_ARGS__)
121
122#ifdef WRN
123#undef WRN
124#endif
125#define WRN(...) EINA_LOG_DOM_WARN(_eina_prefix_log_dom, __VA_ARGS__)
126
127#ifdef INF
128#undef INF
129#endif
130#define INF(...) EINA_LOG_DOM_INFO(_eina_prefix_log_dom, __VA_ARGS__)
131
132#ifdef DBG
133#undef DBG
134#endif
135#define DBG(...) EINA_LOG_DOM_DBG(_eina_prefix_log_dom, __VA_ARGS__)
136
137static int _eina_prefix_log_dom = -1;
138
139static int
140_fallback(Eina_Prefix *pfx, const char *pkg_bin, const char *pkg_lib,
141 const char *pkg_data, const char *pkg_locale, const char *envprefix)
142{
143 char *p;
144
145 STRDUP_REP(pfx->prefix_path, pkg_bin);
146 if (!pfx->prefix_path) return 0;
147 p = strrchr(pfx->prefix_path, DSEP_C);
148 if (p) *p = 0;
149 STRDUP_REP(pfx->prefix_path_bin, pkg_bin);
150 STRDUP_REP(pfx->prefix_path_lib, pkg_lib);
151 STRDUP_REP(pfx->prefix_path_data, pkg_data);
152 STRDUP_REP(pfx->prefix_path_locale, pkg_locale);
153 fprintf(stderr,
154 "WARNING: Could not determine its installed prefix for '%s'\n"
155 " so am falling back on the compiled in default:\n"
156 " %s\n"
157 " implied by the following:\n"
158 " bindir = %s\n"
159 " libdir = %s\n"
160 " datadir = %s\n"
161 " localedir = %s\n"
162 " Try setting the following environment variables:\n"
163 " %s_PREFIX - points to the base prefix of install\n"
164 " or the next 4 variables\n"
165 " %s_BIN_DIR - provide a specific binary directory\n"
166 " %s_LIB_DIR - provide a specific library directory\n"
167 " %s_DATA_DIR - provide a specific data directory\n"
168 " %s_LOCALE_DIR - provide a specific locale directory\n"
169 , envprefix,
170 pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale,
171 envprefix, envprefix, envprefix, envprefix, envprefix);
172 pfx->fallback = 1;
173 return 1;
174}
175
176#ifndef _WIN32
177static int
178_try_proc(Eina_Prefix *pfx, void *symbol)
179{
180 FILE *f;
181 char buf[4096];
182
183 DBG("Try /proc/self/maps");
184 f = fopen("/proc/self/maps", "rb");
185 if (!f) return 0;
186 DBG("Exists /proc/self/maps");
187 while (fgets(buf, sizeof(buf), f))
188 {
189 int len;
190 char *p, mode[5] = "";
191 unsigned long ptr1 = 0, ptr2 = 0;
192
193 len = strlen(buf);
194 if (buf[len - 1] == '\n')
195 {
196 buf[len - 1] = 0;
197 len--;
198 }
199 if (sscanf(buf, "%lx-%lx %4s", &ptr1, &ptr2, mode) == 3)
200 {
201 if (!strcmp(mode, "r-xp"))
202 {
203 if (((void *)ptr1 <= symbol) && (symbol < (void *)ptr2))
204 {
205 DBG("Found in /proc/self/maps: %s", buf);
206 p = strchr(buf, '/');
207 if (p)
208 {
209 DBG("Found in /proc/self/maps: found last /");
210 if (len > 10)
211 {
212 if (!strcmp(buf + len - 10, " (deleted)"))
213 buf[len - 10] = 0;
214 }
215 STRDUP_REP(pfx->exe_path, p);
216 INF("Found in /proc/self/maps: guess exe path is %s", pfx->exe_path);
217 fclose(f);
218 return 1;
219 }
220 else break;
221 }
222 }
223 }
224 }
225 fclose(f);
226 WRN("Failed in /proc/self/maps");
227 return 0;
228}
229#endif
230
231static int
232_try_argv(Eina_Prefix *pfx, const char *argv0)
233{
234 char *path, *p, *cp, *s;
235 int len, lenexe;
236 char buf[PATH_MAX], buf2[PATH_MAX], buf3[PATH_MAX];
237
238 DBG("Try argv0 = %s", argv0);
239 /* 1. is argv0 abs path? */
240#ifdef _WIN32
241 if (argv0[0] && (argv0[1] == ':'))
242#else
243 if (argv0[0] == DSEP_C)
244#endif
245 {
246 DBG("Match arvg0 is full path: %s", argv0);
247 STRDUP_REP(pfx->exe_path, argv0);
248 if (access(pfx->exe_path, X_OK) == 0)
249 {
250 INF("Executable argv0 = %s", argv0);
251 return 1;
252 }
253 IF_FREE_NULL(pfx->exe_path);
254 DBG("Non existent argv0: %s", argv0);
255 return 0;
256 }
257 /* 2. relative path */
258 if (strchr(argv0, DSEP_C))
259 {
260 DBG("Relative path argv0: %s", argv0);
261 if (getcwd(buf3, sizeof(buf3)))
262 {
263 snprintf(buf2, sizeof(buf2), "%s" DSEP_S "%s", buf3, argv0);
264 DBG("Relative to CWD: %s", buf2);
265 if (realpath(buf2, buf))
266 {
267 DBG("Realpath is: %s", buf);
268 STRDUP_REP(pfx->exe_path, buf);
269 if (access(pfx->exe_path, X_OK) == 0)
270 {
271 INF("Path %s is executable", pfx->exe_path);
272 return 1;
273 }
274 DBG("Fail check for executable: %s", pfx->exe_path);
275 IF_FREE_NULL(pfx->exe_path);
276 }
277 }
278 }
279 /* 3. argv0 no path - look in PATH */
280 DBG("Look for argv0=%s in $PATH", argv0);
281 path = getenv("PATH");
282 if (!path) return 0;
283 p = path;
284 cp = p;
285 lenexe = strlen(argv0);
286 while ((p = strchr(cp, PSEP_C)))
287 {
288 len = p - cp;
289 s = malloc(len + 1 + lenexe + 1);
290 if (s)
291 {
292 strncpy(s, cp, len);
293 s[len] = DSEP_C;
294 strcpy(s + len + 1, argv0);
295 DBG("Try path: %s", s);
296 if (realpath(s, buf))
297 {
298 DBG("Realpath is: %s", buf);
299 if (access(buf, X_OK) == 0)
300 {
301 STRDUP_REP(pfx->exe_path, buf);
302 INF("Path %s is executable", pfx->exe_path);
303 free(s);
304 return 1;
305 }
306 }
307 free(s);
308 }
309 cp = p + 1;
310 }
311 /* 4. big problems. arg[0] != executable - weird execution */
312 return 0;
313}
314
315static int
316_get_env_var(char **var, const char *env, const char *prefix, const char *dir)
317{
318 char buf[PATH_MAX];
319 const char *s = getenv(env);
320
321 DBG("Try env var %s", env);
322 if (s)
323 {
324 INF("Have env %s = %s", env, s);
325 STRDUP_REP(*var, s);
326 return 1;
327 }
328 else if (prefix)
329 {
330 snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", prefix, dir);
331 INF("Have prefix %s = %s", prefix, buf);
332 STRDUP_REP(*var, buf);
333 return 1;
334 }
335 return 0;
336}
337
338static int
339_get_env_vars(Eina_Prefix *pfx,
340 const char *envprefix,
341 const char *bindir,
342 const char *libdir,
343 const char *datadir,
344 const char *localedir)
345{
346 char env[1024];
347 const char *s;
348 int ret = 0;
349
350 snprintf(env, sizeof(env), "%s_PREFIX", envprefix);
351 if ((s = getenv(env))) STRDUP_REP(pfx->prefix_path, s);
352 snprintf(env, sizeof(env), "%s_BIN_DIR", envprefix);
353 ret += _get_env_var(&pfx->prefix_path_bin, env, s, bindir);
354 snprintf(env, sizeof(env), "%s_LIB_DIR", envprefix);
355 ret += _get_env_var(&pfx->prefix_path_lib, env, s, libdir);
356 snprintf(env, sizeof(env), "%s_DATA_DIR", envprefix);
357 ret += _get_env_var(&pfx->prefix_path_data, env, s, datadir);
358 snprintf(env, sizeof(env), "%s_LOCALE_DIR", envprefix);
359 ret += _get_env_var(&pfx->prefix_path_locale, env, s, localedir);
360 return ret;
361}
362
363/**
364 * @endcond
365 */
366
367
368/*============================================================================*
369 * Global *
370 *============================================================================*/
371
372
373/*============================================================================*
374 * API *
375 *============================================================================*/
376
377
378EAPI Eina_Prefix *
379eina_prefix_new(const char *argv0, void *symbol, const char *envprefix,
380 const char *sharedir, const char *magicsharefile,
381 const char *pkg_bin, const char *pkg_lib,
382 const char *pkg_data, const char *pkg_locale)
383{
384 Eina_Prefix *pfx;
385 char *p, buf[4096], *tmp, *magic = NULL;
386 struct stat st;
387 const char *p1, *p2;
388 const char *pkg_bin_p = NULL;
389 const char *pkg_lib_p = NULL;
390 const char *pkg_data_p = NULL;
391 const char *pkg_locale_p = NULL;
392 const char *bindir = "bin";
393 const char *libdir = "lib";
394 const char *datadir = "share";
395 const char *localedir = "share";
396
397 DBG("EINA PREFIX: argv0=%s, symbol=%p, magicsharefile=%s, envprefix=%s",
398 argv0, symbol, magicsharefile, envprefix);
399 pfx = calloc(1, sizeof(Eina_Prefix));
400 if (!pfx) return NULL;
401
402 /* if provided with a share dir use datadir/sharedir as the share dir */
403 if (sharedir)
404 {
405 int len;
406
407 len = snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", datadir, sharedir);
408 if (len > 0)
409 {
410#ifdef _WIN32
411 /* on win32 convert / to \ for path here */
412 for (p = buf + strlen(datadir) + strlen(DSEP_S); *p; p++)
413 {
414 if (*p == '/') *p = DSEP_C;
415 }
416#endif
417 tmp = alloca(len + 1);
418 strcpy(tmp, buf);
419 datadir = tmp;
420 }
421 }
422 if (magicsharefile)
423 {
424 magic = alloca(strlen(magicsharefile));
425 strcpy(magic, magicsharefile);
426#ifdef _WIN32
427 /* on win32 convert / to \ for path here */
428 for (p = magic; *p; p++)
429 {
430 if (*p == '/') *p = DSEP_C;
431 }
432#endif
433 }
434
435 /* look at compile-time package bin/lib/datadir etc. and figure out the
436 * bin, lib and data dirs from these, if possible. i.e.
437 * bin = /usr/local/bin
438 * lib = /usr/local/lib
439 * data = /usr/local/share/enlightenment
440 * thus they all have a common prefix string of /usr/local/ and
441 * bindir = bin
442 * libdir = lib
443 * datadir = share/enlightenment
444 * this addresses things like libdir is lib64 or lib32 or other such
445 * junk distributions like to do so then:
446 * bin = /usr/local/bin
447 * lib = /usr/local/lib64
448 * data = /usr/local/share/enlightenment
449 * then
450 * bindir = bin
451 * libdir = lib64
452 * datadir = share/enlightennment
453 * in theory this should also work with debians new multiarch style like
454 * bindir = bin
455 * libdir = lib/i386-linux-gnu
456 * or
457 * libdir = lib/x86_64-linux-gnu
458 * all with a common prefix that can be relocated
459 */
460 /* 1. check last common char in bin and lib strings */
461 for (p1 = pkg_bin, p2 = pkg_lib; *p1 && *p2; p1++, p2++)
462 {
463 if (*p1 != *p2)
464 {
465 pkg_bin_p = p1;
466 pkg_lib_p = p2;
467 break;
468 }
469 }
470 /* 1. check last common char in bin and data strings */
471 for (p1 = pkg_bin, p2 = pkg_data; *p1 && *p2; p1++, p2++)
472 {
473 if (*p1 != *p2)
474 {
475 pkg_data_p = p2;
476 break;
477 }
478 }
479 /* 1. check last common char in bin and locale strings */
480 for (p1 = pkg_bin, p2 = pkg_locale; *p1 && *p2; p1++, p2++)
481 {
482 if (*p1 != *p2)
483 {
484 pkg_locale_p = p2;
485 break;
486 }
487 }
488 /* 2. if all the common string offsets match we compiled with a common prefix */
489 if (((pkg_bin_p - pkg_bin) == (pkg_lib_p - pkg_lib))
490 && ((pkg_bin_p - pkg_bin) == (pkg_data_p - pkg_data))
491 && ((pkg_bin_p - pkg_bin) == (pkg_locale_p - pkg_locale))
492 )
493 {
494 bindir = pkg_bin_p;
495 libdir = pkg_lib_p;
496 datadir = pkg_data_p;
497 localedir = pkg_locale_p;
498 DBG("Prefix relative bindir = %s", bindir);
499 DBG("Prefix relative libdir = %s", libdir);
500 DBG("Prefix relative datadir = %s", datadir);
501 DBG("Prefix relative localedir = %s", localedir);
502 }
503 /* 3. some galoot thought it awesome not to give us a common prefix at compile time
504 * so fall back to the compile time directories. we are no longer relocatable */
505 else
506 {
507 STRDUP_REP(pfx->prefix_path_bin, pkg_bin);
508 STRDUP_REP(pfx->prefix_path_lib, pkg_lib);
509 STRDUP_REP(pfx->prefix_path_data, pkg_data);
510 STRDUP_REP(pfx->prefix_path_locale, pkg_locale);
511 pfx->no_common_prefix = 1;
512 DBG("Can't work out a common prefix - compiled in fallback");
513 }
514
515 /* if user provides env vars - then use that or also more specific sub
516 * dirs for bin, lib, data and locale */
517 if ((envprefix) &&
518 (_get_env_vars(pfx, envprefix, bindir, libdir, datadir, localedir) > 0))
519 {
520 pfx->env_used = 1;
521 return pfx;
522 }
523
524#ifdef HAVE_DLADDR
525 DBG("Try dladdr on %p", symbol);
526 if (symbol)
527 {
528 Dl_info info_dl;
529
530 if (dladdr(symbol, &info_dl))
531 {
532 DBG("Dlinfo worked");
533 if (info_dl.dli_fname)
534 {
535 DBG("Dlinfo dli_fname = %s", info_dl.dli_fname);
536# ifdef _WIN32
537 if (info_dl.dli_fname[0] && (info_dl.dli_fname[1] == ':'))
538# else
539 if (info_dl.dli_fname[0] == DSEP_C)
540# endif
541 {
542 INF("Dlsym gave full path = %s", info_dl.dli_fname);
543 STRDUP_REP(pfx->exe_path, info_dl.dli_fname);
544 }
545 }
546 }
547 }
548#endif
549 /* no env var - examine process and possible argv0 */
550 if ((argv0) && (!pfx->exe_path) && (symbol))
551 {
552#ifndef _WIN32
553 if (!_try_proc(pfx, symbol))
554 {
555#endif
556 if (!_try_argv(pfx, argv0))
557 {
558 _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale,
559 envprefix);
560 return pfx;
561 }
562#ifndef _WIN32
563 }
564#endif
565 }
566 if (!pfx->exe_path)
567 {
568 WRN("Fallback - nothing found");
569 _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix);
570 return pfx;
571 }
572 /* _exe_path is now a full absolute path TO this exe - figure out rest */
573 /* if
574 * exe = /blah/whatever/bin/exe
575 * or
576 * exe = /blah/whatever/lib/libexe.so
577 * then
578 * prefix = /blah/whatever
579 * bin_dir = /blah/whatever/bin
580 * data_dir = /blah/whatever/share/enlightenment
581 * lib_dir = /blah/whatever/lib
582 */
583 DBG("From exe %s figure out the rest", pfx->exe_path);
584 p = strrchr(pfx->exe_path, DSEP_C);
585 if (p)
586 {
587 p--;
588 while (p >= pfx->exe_path)
589 {
590 if (*p == DSEP_C)
591 {
592 pfx->prefix_path = malloc(p - pfx->exe_path + 1);
593 if (pfx->prefix_path)
594 {
595 strncpy(pfx->prefix_path, pfx->exe_path,
596 p - pfx->exe_path);
597 pfx->prefix_path[p - pfx->exe_path] = 0;
598 DBG("Have prefix = %s", pfx->prefix_path);
599
600 /* bin */
601 snprintf(buf, sizeof(buf), "%s" DSEP_S "%s",
602 pfx->prefix_path, bindir);
603 STRDUP_REP(pfx->prefix_path_bin, buf);
604 DBG("Have bin = %s", pfx->prefix_path_bin);
605 /* lib */
606 snprintf(buf, sizeof(buf), "%s" DSEP_S "%s",
607 pfx->prefix_path, libdir);
608 STRDUP_REP(pfx->prefix_path_lib, buf);
609 DBG("Have lib = %s", pfx->prefix_path_lib);
610 /* locale */
611 snprintf(buf, sizeof(buf), "%s" DSEP_S "%s",
612 pfx->prefix_path, localedir);
613 STRDUP_REP(pfx->prefix_path_locale, buf);
614 DBG("Have locale = %s", pfx->prefix_path_locale);
615 /* check if magic file is there - then our guess is right */
616 if (magic)
617 {
618 DBG("Magic = %s", magic);
619 snprintf(buf, sizeof(buf),
620 "%s" DSEP_S "%s" DSEP_S "%s",
621 pfx->prefix_path, datadir, magic);
622 DBG("Check in %s", buf);
623 }
624 if ((!magic) || (stat(buf, &st) == 0))
625 {
626 if (buf[0])
627 DBG("Magic path %s stat passed", buf);
628 else
629 DBG("No magic file");
630 snprintf(buf, sizeof(buf), "%s" DSEP_S "%s",
631 pfx->prefix_path, datadir);
632 STRDUP_REP(pfx->prefix_path_data, buf);
633 }
634 /* magic file not there. time to start hunting! */
635 else
636 {
637 WRN("Magic failed");
638 _fallback(pfx, pkg_bin, pkg_lib, pkg_data,
639 pkg_locale, envprefix);
640 }
641 }
642 else
643 {
644 WRN("No Prefix path (alloc fail)");
645 _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale,
646 envprefix);
647 }
648 return pfx;
649 }
650 p--;
651 }
652 }
653 WRN("Final fallback");
654 _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix);
655 return pfx;
656}
657
658EAPI void
659eina_prefix_free(Eina_Prefix *pfx)
660{
661 if (!pfx) return;
662
663 IF_FREE_NULL(pfx->exe_path);
664 IF_FREE_NULL(pfx->prefix_path);
665 IF_FREE_NULL(pfx->prefix_path_bin);
666 IF_FREE_NULL(pfx->prefix_path_data);
667 IF_FREE_NULL(pfx->prefix_path_lib);
668 IF_FREE_NULL(pfx->prefix_path_locale);
669 free(pfx);
670}
671
672EAPI const char *
673eina_prefix_get(Eina_Prefix *pfx)
674{
675 if (!pfx) return "";
676 return pfx->prefix_path;
677}
678
679EAPI const char *
680eina_prefix_bin_get(Eina_Prefix *pfx)
681{
682 if (!pfx) return "";
683 return pfx->prefix_path_bin;
684}
685
686EAPI const char *
687eina_prefix_lib_get(Eina_Prefix *pfx)
688{
689 if (!pfx) return "";
690 return pfx->prefix_path_lib;
691}
692
693EAPI const char *
694eina_prefix_data_get(Eina_Prefix *pfx)
695{
696 if (!pfx) return "";
697 return pfx->prefix_path_data;
698}
699
700EAPI const char *
701eina_prefix_locale_get(Eina_Prefix *pfx)
702{
703 if (!pfx) return "";
704 return pfx->prefix_path_locale;
705}
706
707Eina_Bool
708eina_prefix_init(void)
709{
710 _eina_prefix_log_dom = eina_log_domain_register("eina_prefix",
711 EINA_LOG_COLOR_DEFAULT);
712 if (_eina_prefix_log_dom < 0)
713 {
714 EINA_LOG_ERR("Could not register log domain: eina_prefix");
715 return EINA_FALSE;
716 }
717
718 return EINA_TRUE;
719}
720
721Eina_Bool
722eina_prefix_shutdown(void)
723{
724 eina_log_domain_unregister(_eina_prefix_log_dom);
725 _eina_prefix_log_dom = -1;
726 return EINA_TRUE;
727}
diff --git a/libraries/eina/src/lib/eina_private.h b/libraries/eina/src/lib/eina_private.h
new file mode 100644
index 0000000..d390397
--- /dev/null
+++ b/libraries/eina/src/lib/eina_private.h
@@ -0,0 +1,140 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Carsten Haitzler, Vincent Torri, 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#ifndef EINA_PRIVATE_H_
20#define EINA_PRIVATE_H_
21
22#include <stdarg.h>
23
24#include "eina_magic.h"
25#include "eina_iterator.h"
26#include "eina_accessor.h"
27
28#ifndef MIN
29# define MIN(x, y) (((x) > (y)) ? (y) : (x))
30#endif
31
32#ifndef MAX
33# define MAX(x, y) (((x) > (y)) ? (x) : (y))
34#endif
35
36#ifndef ABS
37# define ABS(x) ((x) < 0 ? -(x) : (x))
38#endif
39
40#ifndef CLAMP
41# define CLAMP(x, min, \
42 max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
43#endif
44
45#define EINA_INLIST_JUMP_SIZE 256
46
47#define READBUFSIZ 65536
48
49#define EINA_LOG_COLOR_DEFAULT "\033[36m"
50
51/* eina magic types */
52#define EINA_MAGIC_SHARE 0x98761234
53#define EINA_MAGIC_SHARE_HEAD 0x98761235
54#define EINA_MAGIC_STRINGSHARE_NODE 0x98761254
55#define EINA_MAGIC_USTRINGSHARE_NODE 0x98761255
56#define EINA_MAGIC_BINSHARE_NODE 0x98761256
57
58#define EINA_MAGIC_LIST 0x98761237
59#define EINA_MAGIC_LIST_ITERATOR 0x98761238
60#define EINA_MAGIC_LIST_ACCESSOR 0x98761239
61#define EINA_MAGIC_LIST_ACCOUNTING 0x9876123a
62
63#define EINA_MAGIC_ARRAY 0x9876123b
64#define EINA_MAGIC_ARRAY_ITERATOR 0x9876123c
65#define EINA_MAGIC_ARRAY_ACCESSOR 0x9876123d
66
67#define EINA_MAGIC_HASH 0x9876123e
68#define EINA_MAGIC_HASH_ITERATOR 0x9876123f
69
70#define EINA_MAGIC_TILER 0x98761240
71#define EINA_MAGIC_TILER_ITERATOR 0x98761241
72
73#define EINA_MAGIC_MATRIXSPARSE 0x98761242
74#define EINA_MAGIC_MATRIXSPARSE_ROW 0x98761243
75#define EINA_MAGIC_MATRIXSPARSE_CELL 0x98761244
76#define EINA_MAGIC_MATRIXSPARSE_ITERATOR 0x98761245
77#define EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR 0x98761246
78#define EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR 0x98761247
79#define EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR 0x98761248
80#define EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR 0x98761249
81
82#define EINA_MAGIC_STRBUF 0x98761250
83#define EINA_MAGIC_USTRBUF 0x98761257
84#define EINA_MAGIC_BINBUF 0x98761258
85
86#define EINA_MAGIC_QUADTREE 0x98761251
87#define EINA_MAGIC_QUADTREE_ROOT 0x98761252
88#define EINA_MAGIC_QUADTREE_ITEM 0x98761253
89
90#define EINA_MAGIC_SIMPLE_XML_TAG 0x98761260
91#define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261
92#define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262
93
94#define EINA_MAGIC_CLASS 0x9877CB30
95
96/* undef the following, we want out version */
97#undef FREE
98#define FREE(ptr) \
99 do { \
100 free(ptr); \
101 ptr = NULL; \
102 } while(0);
103
104#undef IF_FREE
105#define IF_FREE(ptr) \
106 do { \
107 if (ptr) { \
108 free(ptr); \
109 ptr = NULL; \
110 } \
111 } while(0);
112
113#undef IF_FN_DEL
114#define IF_FN_DEL(_fn, ptr) \
115 do { \
116 if (ptr) { \
117 _fn(ptr); \
118 ptr = NULL; \
119 } \
120 } while(0);
121
122#define MAGIC_FREE(ptr) \
123 do { \
124 if (ptr) { \
125 EINA_MAGIC_SET(ptr, EINA_MAGIC_NONE); \
126 FREE(ptr); \
127 } \
128 } while(0);
129
130#ifdef EFL_HAVE_THREADS
131extern Eina_Bool _threads_activated;
132
133void eina_share_common_threads_init(void);
134void eina_share_common_threads_shutdown(void);
135void eina_log_threads_init(void);
136void eina_log_threads_shutdown(void);
137#endif
138
139#endif /* EINA_PRIVATE_H_ */
140
diff --git a/libraries/eina/src/lib/eina_quadtree.c b/libraries/eina/src/lib/eina_quadtree.c
new file mode 100644
index 0000000..daf03d0
--- /dev/null
+++ b/libraries/eina/src/lib/eina_quadtree.c
@@ -0,0 +1,935 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2010 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 * @page tutorial_quadtree_page QuadTree Tutorial
21 *
22 * to be written...
23 *
24 */
25
26#ifdef HAVE_CONFIG_H
27# include "config.h"
28#endif
29
30#include <stdlib.h>
31#include <stdio.h>
32
33#ifdef HAVE_EVIL
34# include <Evil.h>
35#endif
36
37#include "eina_quadtree.h"
38#include "eina_magic.h"
39#include "eina_mempool.h"
40#include "eina_list.h"
41#include "eina_inlist.h"
42#include "eina_trash.h"
43#include "eina_log.h"
44#include "eina_rectangle.h"
45
46#include "eina_private.h"
47
48typedef struct _Eina_QuadTree_Root Eina_QuadTree_Root;
49
50static const char EINA_MAGIC_QUADTREE_STR[] = "Eina QuadTree";
51static const char EINA_MAGIC_QUADTREE_ROOT_STR[] = "Eina QuadTree Root";
52static const char EINA_MAGIC_QUADTREE_ITEM_STR[] = "Eina QuadTree Item";
53
54#define EINA_MAGIC_CHECK_QUADTREE(d, ...) \
55 do { \
56 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE)) \
57 { \
58 EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE); \
59 return __VA_ARGS__; \
60 } \
61 } while(0);
62
63#define EINA_MAGIC_CHECK_QUADTREE_ROOT(d, ...) \
64 do { \
65 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE_ROOT)) \
66 { \
67 EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE_ROOT); \
68 return __VA_ARGS__; \
69 } \
70 } while(0);
71
72#define EINA_MAGIC_CHECK_QUADTREE_ITEM(d, ...) \
73 do { \
74 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE_ITEM)) \
75 { \
76 EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE_ITEM); \
77 return __VA_ARGS__; \
78 } \
79 } while(0);
80
81struct _Eina_QuadTree
82{
83 Eina_QuadTree_Root *root;
84
85 Eina_List *hidden;
86
87 size_t root_count;
88 size_t items_count;
89
90 Eina_Trash *items_trash;
91 Eina_Trash *root_trash;
92
93 Eina_Inlist *change;
94 Eina_Inlist *cached;
95 Eina_Rectangle target;
96
97 size_t index;
98
99 struct
100 {
101 Eina_Quad_Callback v;
102 Eina_Quad_Callback h;
103 } func;
104
105 struct
106 {
107 size_t w;
108 size_t h;
109 } geom;
110
111 Eina_Bool resize : 1;
112 Eina_Bool lost : 1;
113
114 EINA_MAGIC
115};
116
117struct _Eina_QuadTree_Root
118{
119 Eina_QuadTree_Root *parent;
120 Eina_QuadTree_Root *left;
121 Eina_QuadTree_Root *right;
122
123 Eina_List *both;
124
125 Eina_Bool sorted : 1;
126
127 EINA_MAGIC
128};
129
130struct _Eina_QuadTree_Item
131{
132 EINA_INLIST;
133
134 Eina_QuadTree *quad;
135 Eina_QuadTree_Root *root;
136
137 const void *object;
138
139 size_t index;
140
141 Eina_Bool change : 1;
142 Eina_Bool delete_me : 1;
143 Eina_Bool visible : 1;
144 Eina_Bool hidden : 1;
145
146 EINA_MAGIC
147};
148
149static int _eina_quadtree_log_dom = -1;
150static Eina_Mempool *eina_quadtree_root_mp = NULL;
151static Eina_Mempool *_eina_quadtree_items_mp = NULL;
152
153#ifdef ERR
154#undef ERR
155#endif
156#define ERR(...) EINA_LOG_DOM_ERR(_eina_quadtree_log_dom, __VA_ARGS__)
157
158#ifdef DBG
159#undef DBG
160#endif
161#define DBG(...) EINA_LOG_DOM_DBG(_eina_quadtree_log_dom, __VA_ARGS__)
162
163
164static int
165_eina_quadtree_item_cmp(const void *a, const void *b)
166{
167 const Eina_QuadTree_Item *i = a;
168 const Eina_QuadTree_Item *j = b;
169
170 return i->index - j->index;
171}
172
173static Eina_QuadTree_Root *
174eina_quadtree_root_free(Eina_QuadTree *q, Eina_QuadTree_Root *root)
175{
176 Eina_QuadTree_Item *item;
177
178 if (!root)
179 return NULL;
180
181 EINA_MAGIC_CHECK_QUADTREE_ROOT(root, NULL);
182
183 EINA_LIST_FREE(root->both, item)
184 eina_mempool_free(_eina_quadtree_items_mp, item);
185
186 root->left = eina_quadtree_root_free(q, root->left);
187 root->right = eina_quadtree_root_free(q, root->right);
188
189 EINA_MAGIC_SET(root, 0);
190 eina_mempool_free(eina_quadtree_root_mp, root);
191
192 return NULL;
193}
194
195static Eina_QuadTree_Root *
196eina_quadtree_root_rebuild_pre(Eina_QuadTree *q,
197 Eina_Inlist **change,
198 Eina_QuadTree_Root *root)
199{
200 Eina_QuadTree_Item *item;
201
202 if (!root)
203 return NULL;
204
205 EINA_LIST_FREE(root->both, item)
206 {
207 if (item->visible)
208 *change = eina_inlist_append(*change, EINA_INLIST_GET(item));
209 else if (!item->hidden)
210 {
211 q->hidden = eina_list_append(q->hidden, item);
212 item->hidden = EINA_TRUE;
213 item->root = NULL;
214 }
215 }
216
217 root->left = eina_quadtree_root_rebuild_pre(q, change, root->left);
218 root->right = eina_quadtree_root_rebuild_pre(q, change, root->right);
219
220 EINA_MAGIC_SET(root, 0);
221 if (q->root_count > 50)
222 eina_mempool_free(eina_quadtree_root_mp, root);
223 else
224 {
225 eina_trash_push(&q->root_trash, root);
226 q->root_count++;
227 }
228
229 return NULL;
230}
231
232static size_t
233_eina_quadtree_split(Eina_Inlist *objects,
234 Eina_QuadTree_Root *root,
235 Eina_Inlist **left,
236 Eina_Inlist **right,
237 Eina_Quad_Callback func,
238 int border,
239 int middle)
240{
241 Eina_QuadTree_Item *object;
242
243 middle /= 2;
244
245 if (middle <= 4)
246 while (objects)
247 {
248 object = EINA_INLIST_CONTAINER_GET(objects, Eina_QuadTree_Item);
249 objects = objects->next;
250
251 object->change = EINA_FALSE;
252 if (!object->visible)
253 {
254 if (!object->hidden)
255 {
256 object->hidden = EINA_TRUE;
257 object->quad->hidden = eina_list_append(
258 object->quad->hidden,
259 object);
260 }
261
262 continue;
263 }
264
265 if (object->hidden)
266 {
267 object->hidden = EINA_FALSE;
268 object->quad->hidden = eina_list_remove(object->quad->hidden,
269 object);
270 }
271
272 if (!object->delete_me)
273 {
274 if (root->sorted)
275 root->both = eina_list_sorted_insert(root->both,
276 _eina_quadtree_item_cmp,
277 object);
278 else
279 root->both = eina_list_append(root->both, object);
280
281 object->root = root;
282 }
283 else
284 eina_quadtree_del(object);
285 }
286 else
287 while (objects)
288 {
289 object = EINA_INLIST_CONTAINER_GET(objects, Eina_QuadTree_Item);
290 objects = objects->next;
291
292 object->change = EINA_FALSE;
293 if (!object->visible)
294 {
295 if (!object->hidden)
296 {
297 object->hidden = EINA_TRUE;
298 object->quad->hidden = eina_list_append(
299 object->quad->hidden,
300 object);
301 }
302
303 continue;
304 }
305
306 if (object->hidden)
307 {
308 object->hidden = EINA_FALSE;
309 object->quad->hidden = eina_list_remove(object->quad->hidden,
310 object);
311 }
312
313 if (!object->delete_me)
314 {
315 switch (func(object->object, border + middle))
316 {
317 case EINA_QUAD_LEFT:
318 *left = eina_inlist_append(*left, EINA_INLIST_GET(object));
319 break;
320
321 case EINA_QUAD_RIGHT:
322 *right =
323 eina_inlist_append(*right, EINA_INLIST_GET(object));
324 break;
325
326 case EINA_QUAD_BOTH:
327 root->both = eina_list_append(root->both, object);
328 object->root = root;
329 break;
330
331 default:
332 abort();
333 }
334 }
335 else
336 eina_quadtree_del(object);
337 }
338
339 return middle;
340}
341
342
343static Eina_QuadTree_Root *
344_eina_quadtree_update(Eina_QuadTree *q, Eina_QuadTree_Root *parent,
345 Eina_QuadTree_Root *root, Eina_Inlist *objects,
346 Eina_Bool direction, Eina_Rectangle *size)
347{
348 Eina_Inlist *right = NULL;
349 Eina_Inlist *left = NULL;
350 size_t w2;
351 size_t h2;
352
353 if (!objects)
354 return root;
355
356 if (!root)
357 {
358 root = eina_trash_pop(&q->root_trash);
359 if (!root)
360 root = eina_mempool_malloc(eina_quadtree_root_mp, sizeof (Eina_QuadTree_Root));
361 else
362 q->root_count--;
363
364 if (!root)
365 /* FIXME: NOT GOOD TIMING, WE ARE GOING TO LEAK MORE MEMORY */
366 return NULL;
367
368 root->parent = parent;
369 root->both = NULL;
370 root->left = NULL;
371 root->right = NULL;
372 root->sorted = EINA_TRUE;
373
374 EINA_MAGIC_SET(root, EINA_MAGIC_QUADTREE_ROOT);
375 }
376
377 w2 = 0;
378 h2 = 0;
379
380 if (direction)
381 w2 = _eina_quadtree_split(objects, root,
382 &left, &right,
383 q->func.h, size->x, size->w);
384 else
385 h2 = _eina_quadtree_split(objects, root,
386 &left, &right,
387 q->func.v, size->y, size->h);
388
389 size->w -= w2; size->h -= h2;
390 root->left = _eina_quadtree_update(q, root,
391 root->left, left,
392 !direction, size);
393 size->x += w2; size->y += h2;
394 root->right = _eina_quadtree_update(q, root,
395 root->right, right,
396 !direction, size);
397 size->x -= w2; size->y -= h2;
398 size->w += w2; size->h += h2;
399
400 return root;
401}
402
403static Eina_Inlist *
404_eina_quadtree_merge(Eina_Inlist *result,
405 Eina_List *both)
406{
407 Eina_QuadTree_Item *item;
408 Eina_QuadTree_Item *b;
409 Eina_Inlist *moving;
410
411 if (!both)
412 return result;
413
414 if (!result)
415 {
416 Eina_List *l;
417
418 EINA_LIST_FOREACH(both, l, item)
419 if (item->visible)
420 result = eina_inlist_append(result, EINA_INLIST_GET(item));
421
422 return result;
423 }
424
425 moving = result;
426
427 item = EINA_INLIST_CONTAINER_GET(moving, Eina_QuadTree_Item);
428 b = eina_list_data_get(both);
429
430 while (both && moving)
431 {
432 if (!b->visible)
433 {
434 both = eina_list_next(both);
435 b = eina_list_data_get(both);
436 continue;
437 }
438
439 if (_eina_quadtree_item_cmp(item, b) < 0)
440 {
441 /* moving is still lower than item, so we can continue to the next one. */
442 moving = moving->next;
443 item = EINA_INLIST_CONTAINER_GET(moving, Eina_QuadTree_Item);
444 }
445 else
446 {
447 /* we just get above the limit of both, so insert it */
448 result = eina_inlist_prepend_relative(result,
449 EINA_INLIST_GET(b),
450 moving);
451 both = eina_list_next(both);
452 b = eina_list_data_get(both);
453 }
454 }
455
456 item = EINA_INLIST_CONTAINER_GET(result->last, Eina_QuadTree_Item);
457
458 while (both)
459 {
460 b = eina_list_data_get(both);
461 if (b->visible)
462 {
463 if (_eina_quadtree_item_cmp(item, b) < 0)
464 break;
465
466 result = eina_inlist_prepend_relative(result,
467 EINA_INLIST_GET(b),
468 result->last);
469 }
470
471 both = eina_list_next(both);
472 }
473
474 while (both)
475 {
476 b = eina_list_data_get(both);
477 if (b->visible)
478 result = eina_inlist_append(result, EINA_INLIST_GET(b));
479
480 both = eina_list_next(both);
481 }
482
483 return result;
484}
485
486static Eina_Inlist *
487_eina_quadtree_collide(Eina_Inlist *result,
488 Eina_QuadTree_Root *root,
489 Eina_Bool direction, Eina_Rectangle *size,
490 Eina_Rectangle *target)
491{
492 if (!root)
493 return result;
494
495 if (!root->sorted)
496 {
497 root->both = eina_list_sort(root->both, -1, _eina_quadtree_item_cmp);
498 root->sorted = EINA_TRUE;
499 }
500
501 result = _eina_quadtree_merge(result, root->both);
502 DBG("%p: %i in both for (%i, %i - %i, %i)",
503 root, eina_list_count(root->both),
504 size->x, size->y, size->w, size->h);
505
506 if (direction)
507 {
508 int middle = size->w / 2;
509
510 size->w -= middle;
511 if (eina_spans_intersect(size->x, size->w, target->x, target->w))
512 result = _eina_quadtree_collide(result, root->left,
513 !direction, size,
514 target);
515
516 size->x += middle;
517 if (eina_spans_intersect(size->x, size->w, target->x, target->w))
518 result = _eina_quadtree_collide(result, root->right,
519 !direction, size,
520 target);
521
522 size->x -= middle;
523 size->w += middle;
524 }
525 else
526 {
527 int middle = size->h / 2;
528
529 size->h -= middle;
530 if (eina_spans_intersect(size->y, size->h, target->y, target->h))
531 result = _eina_quadtree_collide(result, root->left,
532 !direction, size,
533 target);
534
535 size->y += middle;
536 if (eina_spans_intersect(size->y, size->h, target->y, target->h))
537 result = _eina_quadtree_collide(result, root->right,
538 !direction, size,
539 target);
540
541 size->y -= middle;
542 size->h += middle;
543 }
544
545 return result;
546}
547
548static void
549_eina_quadtree_remove(Eina_QuadTree_Item *object)
550{
551 if (!object->root)
552 return;
553
554 object->root->both = eina_list_remove(object->root->both, object);
555 if (object->root->both)
556 goto end;
557
558 if (object->root->left)
559 goto end;
560
561 if (object->root->right)
562 goto end;
563
564 /* The root is not useful anymore... */
565 if (object->root->parent)
566 {
567 if (object->root->parent->left == object->root)
568 object->root->parent->left = NULL;
569 else
570 object->root->parent->right = NULL;
571
572 object->root->parent = NULL;
573 }
574 else
575 object->quad->root = NULL;
576
577 if (object->quad->root_count > 50)
578 eina_mempool_free(eina_quadtree_root_mp, object->root);
579 else
580 {
581 eina_trash_push(&object->quad->root_trash, object->root);
582 object->quad->root_count++;
583 }
584
585end:
586 object->root = NULL;
587}
588
589EAPI Eina_QuadTree *
590eina_quadtree_new(size_t w, size_t h,
591 Eina_Quad_Callback vertical, Eina_Quad_Callback horizontal)
592{
593 Eina_QuadTree *result;
594
595 if (!vertical || !horizontal || h == 0 || w == 0)
596 return NULL;
597
598 result = calloc(1, sizeof (Eina_QuadTree));
599 if (!result)
600 return NULL;
601
602 result->func.v = vertical;
603 result->func.h = horizontal;
604
605 result->geom.w = w;
606 result->geom.h = h;
607
608 result->change = NULL;
609
610 result->lost = EINA_TRUE;
611
612 EINA_MAGIC_SET(result, EINA_MAGIC_QUADTREE);
613
614 return result;
615}
616
617EAPI void
618eina_quadtree_free(Eina_QuadTree *q)
619{
620 Eina_QuadTree_Item *item;
621
622 if (!q)
623 return;
624
625 EINA_MAGIC_CHECK_QUADTREE(q);
626
627 while (q->change)
628 {
629 item = EINA_INLIST_CONTAINER_GET(q->change, Eina_QuadTree_Item);
630 q->change = q->change->next;
631 if (!item->hidden)
632 eina_mempool_free(_eina_quadtree_items_mp, item);
633 }
634
635 EINA_LIST_FREE(q->hidden, item)
636 eina_mempool_free(_eina_quadtree_items_mp, item);
637
638 eina_quadtree_root_free(q, q->root);
639
640 while (q->items_trash)
641 {
642 item = eina_trash_pop(&q->items_trash);
643 eina_mempool_free(_eina_quadtree_items_mp, item);
644 }
645
646 while (q->root_trash)
647 {
648 Eina_QuadTree_Root *root;
649
650 root = eina_trash_pop(&q->root_trash);
651 eina_mempool_free(eina_quadtree_root_mp, root);
652 }
653
654 EINA_MAGIC_SET(q, 0);
655 free(q);
656}
657
658EAPI Eina_QuadTree_Item *
659eina_quadtree_add(Eina_QuadTree *q, const void *object)
660{
661 Eina_QuadTree_Item *result;
662
663 EINA_MAGIC_CHECK_QUADTREE(q, NULL);
664
665 if (!object)
666 return NULL;
667
668 result = eina_trash_pop(&q->items_trash);
669 if (!result)
670 result = eina_mempool_malloc(_eina_quadtree_items_mp, sizeof (Eina_QuadTree_Item));
671 else
672 q->items_count--;
673
674 if (!result)
675 return NULL;
676
677 result->quad = q;
678 result->root = NULL;
679 result->object = object;
680
681 result->index = q->index++;
682
683 result->change = EINA_TRUE;
684 result->delete_me = EINA_FALSE;
685 result->visible = EINA_TRUE;
686 result->hidden = EINA_FALSE;
687
688 EINA_MAGIC_SET(result, EINA_MAGIC_QUADTREE_ITEM);
689
690 /* Insertion is delayed until we really need to use it */
691 q->change = eina_inlist_append(q->change, EINA_INLIST_GET(result));
692
693 return result;
694}
695
696EAPI Eina_Bool
697eina_quadtree_del(Eina_QuadTree_Item *object)
698{
699 if (!object)
700 return EINA_FALSE;
701
702 EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE);
703
704 _eina_quadtree_remove(object);
705
706 if (object->change)
707 {
708 /* This object is still in the update array, delaying it's removal !*/
709 object->delete_me = EINA_TRUE;
710 object->visible = EINA_TRUE;
711 return EINA_TRUE;
712 }
713
714 if (object->hidden)
715 {
716 object->quad->hidden = eina_list_remove(object->quad->hidden, object);
717 object->hidden = EINA_TRUE;
718 }
719
720 /* This object is not anymore inside the tree, we can remove it now !*/
721 EINA_MAGIC_SET(object, 0);
722 if (object->quad->items_count > 256)
723 eina_mempool_free(_eina_quadtree_items_mp, object);
724 else
725 {
726 object->quad->items_count++;
727 eina_trash_push(&object->quad->items_trash, object);
728 }
729
730 return EINA_TRUE;
731}
732
733EAPI Eina_Bool
734eina_quadtree_change(Eina_QuadTree_Item *object)
735{
736 EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE);
737
738 if (object->delete_me || !object->visible)
739 return EINA_FALSE;
740
741 if (object->quad->resize)
742 return EINA_TRUE;
743
744 /* Delaying change until needed */
745 if (!object->change)
746 object->quad->change = eina_inlist_append(object->quad->change,
747 EINA_INLIST_GET(object));
748
749 object->change = EINA_TRUE;
750
751 _eina_quadtree_remove(object);
752
753 return EINA_TRUE;
754}
755
756EAPI Eina_Bool
757eina_quadtree_hide(Eina_QuadTree_Item *object)
758{
759 EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE);
760
761 object->visible = EINA_FALSE;
762
763 return EINA_TRUE;
764}
765
766EAPI Eina_Bool
767eina_quadtree_show(Eina_QuadTree_Item *object)
768{
769 EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE);
770
771 object->quad->lost = EINA_TRUE;
772
773 if (object->visible)
774 return EINA_TRUE;
775
776 object->visible = EINA_TRUE;
777 if (!object->change)
778 return eina_quadtree_change(object);
779
780 return EINA_TRUE;
781}
782
783EAPI Eina_Inlist *
784eina_quadtree_collide(Eina_QuadTree *q, int x, int y, int w, int h)
785{
786 Eina_Rectangle canvas;
787
788 EINA_MAGIC_CHECK_QUADTREE(q, NULL);
789
790 /* Now we need the tree to be up to date, so it's time */
791 if (q->resize) /* Full rebuild needed ! */
792 {
793 DBG("resizing quadtree");
794 q->root = eina_quadtree_root_rebuild_pre(q, &q->change, q->root);
795 q->resize = EINA_FALSE;
796 }
797
798 EINA_RECTANGLE_SET(&canvas, 0, 0, q->geom.w, q->geom.h);
799
800 if (q->change)
801 {
802 DBG("updating quadtree content");
803 q->root = _eina_quadtree_update(q, NULL, q->root, q->change,
804 EINA_FALSE, &canvas);
805 q->change = NULL;
806 q->lost = EINA_TRUE;
807 }
808
809 if (q->target.x != x
810 || q->target.y != y
811 || q->target.w != w
812 || q->target.h != h)
813 {
814 DBG("new target");
815 EINA_RECTANGLE_SET(&q->target, x, y, w, h);
816 q->lost = EINA_TRUE;
817 }
818
819 if (q->lost)
820 {
821 DBG("computing collide");
822 q->cached = _eina_quadtree_collide(NULL, q->root,
823 EINA_FALSE, &canvas,
824 &q->target);
825 q->lost = EINA_FALSE;
826 }
827
828 return q->cached;
829}
830
831EAPI void *
832eina_quadtree_object(Eina_Inlist *item)
833{
834 Eina_QuadTree_Item *qi;
835
836 if (!item)
837 return NULL;
838
839 qi = EINA_INLIST_CONTAINER_GET(item, Eina_QuadTree_Item);
840 if (!qi)
841 return NULL;
842
843 EINA_MAGIC_CHECK_QUADTREE_ITEM(qi, NULL);
844
845 if (!qi->visible)
846 return NULL;
847
848 return (void *)qi->object;
849}
850
851EAPI void
852eina_quadtree_resize(Eina_QuadTree *q, size_t w, size_t h)
853{
854 EINA_MAGIC_CHECK_QUADTREE(q);
855
856 if (q->geom.w == w
857 && q->geom.h == h)
858 return;
859
860 q->resize = EINA_TRUE;
861 q->geom.w = w;
862 q->geom.h = h;
863}
864
865EAPI void
866eina_quadtree_cycle(Eina_QuadTree *q)
867{
868 EINA_MAGIC_CHECK_QUADTREE(q);
869
870 q->index = 0;
871}
872
873EAPI void
874eina_quadtree_increase(Eina_QuadTree_Item *object)
875{
876 size_t tmp;
877
878 tmp = object->quad->index++;
879 if (object->index == tmp)
880 return;
881
882 object->index = tmp;
883 if (object->root)
884 object->root->sorted = EINA_FALSE;
885}
886
887Eina_Bool
888eina_quadtree_init(void)
889{
890 const char *choice, *tmp;
891
892 _eina_quadtree_log_dom = eina_log_domain_register("eina_quadtree",
893 EINA_LOG_COLOR_DEFAULT);
894 if (_eina_quadtree_log_dom < 0)
895 {
896 EINA_LOG_ERR("Could not register log domain: eina_quadtree");
897 return EINA_FALSE;
898 }
899
900#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
901 EMS(EINA_MAGIC_QUADTREE);
902 EMS(EINA_MAGIC_QUADTREE_ROOT);
903 EMS(EINA_MAGIC_QUADTREE_ITEM);
904#undef EMS
905
906#ifdef EINA_DEFAULT_MEMPOOL
907 choice = "pass_through";
908#else
909 choice = "chained_mempool";
910#endif
911 tmp = getenv("EINA_MEMPOOL");
912 if (tmp && tmp[0])
913 choice = tmp;
914
915 _eina_quadtree_items_mp = eina_mempool_add(choice, "QuadTree Item", NULL,
916 sizeof (Eina_QuadTree_Item), 320);
917 eina_quadtree_root_mp = eina_mempool_add(choice, "QuadTree Root", NULL,
918 sizeof (Eina_QuadTree_Root), 32);
919
920 return EINA_TRUE;
921}
922
923Eina_Bool
924eina_quadtree_shutdown(void)
925{
926 eina_mempool_del(eina_quadtree_root_mp);
927 eina_mempool_del(_eina_quadtree_items_mp);
928
929 eina_log_domain_unregister(_eina_quadtree_log_dom);
930 _eina_quadtree_log_dom = -1;
931 return EINA_TRUE;
932}
933
934
935
diff --git a/libraries/eina/src/lib/eina_rbtree.c b/libraries/eina/src/lib/eina_rbtree.c
new file mode 100644
index 0000000..c0c9f9e
--- /dev/null
+++ b/libraries/eina/src/lib/eina_rbtree.c
@@ -0,0 +1,518 @@
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#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "eina_config.h"
28#include "eina_private.h"
29#include "eina_array.h"
30
31/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
32#include "eina_safety_checks.h"
33#include "eina_rbtree.h"
34
35/*============================================================================*
36* Local *
37*============================================================================*/
38
39#define EINA_RBTREE_ITERATOR_PREFIX_MASK 0x1
40#define EINA_RBTREE_ITERATOR_INFIX_MASK 0x2
41#define EINA_RBTREE_ITERATOR_POSTFIX_MASK 0x4
42
43typedef struct _Eina_Iterator_Rbtree Eina_Iterator_Rbtree;
44typedef struct _Eina_Iterator_Rbtree_List Eina_Iterator_Rbtree_List;
45
46struct _Eina_Iterator_Rbtree
47{
48 Eina_Iterator iterator;
49
50 Eina_Array *stack;
51
52 unsigned char mask;
53};
54
55struct _Eina_Iterator_Rbtree_List
56{
57 Eina_Rbtree *tree;
58
59 Eina_Rbtree_Direction dir : 1;
60 Eina_Bool up : 1;
61};
62
63static Eina_Iterator_Rbtree_List *
64_eina_rbtree_iterator_list_new(const Eina_Rbtree *tree)
65{
66 Eina_Iterator_Rbtree_List *new;
67
68 eina_error_set(0);
69 new = malloc(sizeof (Eina_Iterator_Rbtree_List));
70 if (!new)
71 {
72 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
73 return NULL;
74 }
75
76 new->tree = (Eina_Rbtree *)tree;
77 new->dir = EINA_RBTREE_RIGHT;
78 new->up = EINA_FALSE;
79
80 return new;
81}
82
83static Eina_Rbtree *
84_eina_rbtree_iterator_get_content(Eina_Iterator_Rbtree *it)
85{
86 if (eina_array_count_get(it->stack) <= 0)
87 return NULL;
88
89 return eina_array_data_get(it->stack, 0);
90}
91
92static void
93_eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it)
94{
95 Eina_Iterator_Rbtree_List *item;
96 Eina_Array_Iterator et;
97 unsigned int i;
98
99 EINA_ARRAY_ITER_NEXT(it->stack, i, item, et)
100 free(item);
101
102 eina_array_free(it->stack);
103 free(it);
104}
105
106static Eina_Bool
107_eina_rbtree_iterator_next(Eina_Iterator_Rbtree *it, void **data)
108{
109 Eina_Iterator_Rbtree_List *last;
110 Eina_Iterator_Rbtree_List *new;
111 Eina_Rbtree *tree;
112
113 if (eina_array_count_get(it->stack) <= 0)
114 return EINA_FALSE;
115
116 last = eina_array_data_get(it->stack, eina_array_count_get(it->stack) - 1);
117 tree = last->tree;
118
119 if (!last->tree || last->up == EINA_TRUE)
120 {
121 last = eina_array_pop(it->stack);
122 while (last->dir == EINA_RBTREE_LEFT
123 || !last->tree)
124 {
125 if (tree)
126 if ((it->mask & EINA_RBTREE_ITERATOR_POSTFIX_MASK) ==
127 EINA_RBTREE_ITERATOR_POSTFIX_MASK)
128 {
129 free(last);
130
131 if (eina_array_count_get(it->stack) > 0)
132 {
133 last = eina_array_data_get(it->stack,
134 eina_array_count_get(
135 it->
136 stack)
137 - 1);
138 last->up = EINA_TRUE;
139 }
140
141 goto onfix;
142 }
143
144 free(last);
145
146 last = eina_array_pop(it->stack);
147 if (!last)
148 return EINA_FALSE;
149
150 tree = last->tree;
151 }
152
153 last->dir = EINA_RBTREE_LEFT;
154 last->up = EINA_FALSE;
155
156 eina_array_push(it->stack, last);
157
158 if ((it->mask & EINA_RBTREE_ITERATOR_INFIX_MASK) ==
159 EINA_RBTREE_ITERATOR_INFIX_MASK)
160 goto onfix;
161 }
162
163 new = _eina_rbtree_iterator_list_new(last->tree->son[last->dir]);
164 if (!new)
165 return EINA_FALSE;
166
167 eina_array_push(it->stack, new);
168
169 if (last->dir == EINA_RBTREE_RIGHT)
170 if ((it->mask & EINA_RBTREE_ITERATOR_PREFIX_MASK) ==
171 EINA_RBTREE_ITERATOR_PREFIX_MASK)
172 goto onfix;
173
174 return _eina_rbtree_iterator_next(it, data);
175
176onfix:
177 *data = tree;
178 return EINA_TRUE;
179}
180
181static Eina_Iterator *
182_eina_rbtree_iterator_build(const Eina_Rbtree *root, unsigned char mask)
183{
184 Eina_Iterator_Rbtree_List *first;
185 Eina_Iterator_Rbtree *it;
186
187 eina_error_set(0);
188 it = calloc(1, sizeof (Eina_Iterator_Rbtree));
189 if (!it)
190 {
191 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
192 return NULL;
193 }
194
195 it->stack = eina_array_new(8);
196 if (!it->stack)
197 goto on_error2;
198
199 first = _eina_rbtree_iterator_list_new(root);
200 if (!first)
201 goto on_error;
202
203 eina_array_push(it->stack, first);
204
205 it->mask = mask;
206
207 it->iterator.version = EINA_ITERATOR_VERSION;
208 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_rbtree_iterator_next);
209 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
210 _eina_rbtree_iterator_get_content);
211 it->iterator.free = FUNC_ITERATOR_FREE(_eina_rbtree_iterator_free);
212
213 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
214
215 return &it->iterator;
216
217on_error:
218 eina_array_free(it->stack);
219on_error2:
220 free(it);
221
222 return NULL;
223}
224
225static void
226_eina_rbtree_node_init(Eina_Rbtree *node)
227{
228 if (!node)
229 return;
230
231 node->son[0] = NULL;
232 node->son[1] = NULL;
233
234 node->color = EINA_RBTREE_RED;
235}
236
237static inline Eina_Bool
238_eina_rbtree_is_red(Eina_Rbtree *node)
239{
240 return !!node && node->color == EINA_RBTREE_RED;
241}
242
243static inline Eina_Rbtree *
244_eina_rbtree_inline_single_rotation(Eina_Rbtree *node,
245 Eina_Rbtree_Direction dir)
246{
247 Eina_Rbtree *save = node->son[!dir];
248
249 node->son[!dir] = save->son[dir];
250 save->son[dir] = node;
251
252 node->color = EINA_RBTREE_RED;
253 save->color = EINA_RBTREE_BLACK;
254
255 return save;
256}
257
258static inline Eina_Rbtree *
259_eina_rbtree_inline_double_rotation(Eina_Rbtree *node,
260 Eina_Rbtree_Direction dir)
261{
262 node->son[!dir] = _eina_rbtree_inline_single_rotation(node->son[!dir], !dir);
263 return _eina_rbtree_inline_single_rotation(node, dir);
264}
265
266/*============================================================================*
267* Global *
268*============================================================================*/
269
270/*============================================================================*
271* API *
272*============================================================================*/
273
274EAPI Eina_Rbtree *
275eina_rbtree_inline_insert(Eina_Rbtree *root,
276 Eina_Rbtree *node,
277 Eina_Rbtree_Cmp_Node_Cb cmp,
278 const void *data)
279{
280 Eina_Rbtree head;
281 Eina_Rbtree *g, *t; /* Grandparent & parent */
282 Eina_Rbtree *p, *q; /* Iterator & parent */
283 /* WARNING:
284 Compiler is not able to understand the underlying algorithm and don't know that
285 first top node is always black, so it will never use last before running the loop
286 one time.
287 */
288 Eina_Rbtree_Direction dir, last;
289
290 EINA_SAFETY_ON_NULL_RETURN_VAL(node, root);
291 EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root);
292
293 if (!node)
294 return root;
295
296 _eina_rbtree_node_init(node);
297
298 if (!root)
299 {
300 root = node;
301 goto end_add;
302 }
303
304 memset(&head, 0, sizeof (Eina_Rbtree));
305 last = dir = EINA_RBTREE_LEFT;
306
307 /* Set up helpers */
308 t = &head;
309 g = p = NULL;
310 q = t->son[1] = root;
311
312 /* Search down the tree */
313 for (;; )
314 {
315 if (!q)
316 /* Insert new node at the bottom */
317 p->son[dir] = q = node;
318 else if (_eina_rbtree_is_red(q->son[0])
319 && _eina_rbtree_is_red(q->son[1]))
320 {
321 /* Color flip */
322 q->color = EINA_RBTREE_RED;
323 q->son[0]->color = EINA_RBTREE_BLACK;
324 q->son[1]->color = EINA_RBTREE_BLACK;
325 }
326
327 /* Fix red violation */
328 if (_eina_rbtree_is_red(q) && _eina_rbtree_is_red(p))
329 {
330 Eina_Rbtree_Direction dir2;
331
332 dir2 = (t->son[1] == g) ? EINA_RBTREE_RIGHT : EINA_RBTREE_LEFT;
333
334 if (q == p->son[last])
335 t->son[dir2] = _eina_rbtree_inline_single_rotation(g, !last);
336 else
337 t->son[dir2] = _eina_rbtree_inline_double_rotation(g, !last);
338 }
339
340 /* Stop if found */
341 if (q == node)
342 break;
343
344 last = dir;
345 dir = cmp(q, node, (void *)data);
346
347 /* Update helpers */
348 if ( g )
349 t = g;
350
351 g = p, p = q;
352 q = q->son[dir];
353 }
354
355 root = head.son[1];
356
357end_add:
358 /* Make root black */
359 root->color = EINA_RBTREE_BLACK;
360
361 return root;
362}
363
364EAPI Eina_Rbtree *
365eina_rbtree_inline_remove(Eina_Rbtree *root,
366 Eina_Rbtree *node,
367 Eina_Rbtree_Cmp_Node_Cb cmp,
368 const void *data)
369{
370 Eina_Rbtree head;
371 Eina_Rbtree *q, *p;
372 Eina_Rbtree *f = NULL;
373 Eina_Rbtree_Direction dir;
374
375 EINA_SAFETY_ON_NULL_RETURN_VAL(node, root);
376 EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root);
377
378 if (!root || !node)
379 return root;
380
381 memset(&head, 0, sizeof(Eina_Rbtree));
382
383 dir = EINA_RBTREE_RIGHT;
384 q = &head;
385 p = NULL;
386 q->son[EINA_RBTREE_RIGHT] = root;
387
388 /* Search and push a red down */
389 while (q->son[dir])
390 {
391 Eina_Rbtree_Direction last = dir;
392 Eina_Rbtree *g;
393
394 /* Update helpers */
395 g = p; p = q;
396 q = q->son[dir];
397 dir = cmp(q, node, (void *)data);
398
399 /* Save parent node found */
400 if (q == node)
401 f = p;
402
403 /* Push the red node down */
404 if (!_eina_rbtree_is_red(q)
405 && !_eina_rbtree_is_red(q->son[dir]))
406 {
407 if (_eina_rbtree_is_red(q->son[!dir]))
408 q = p->son[last] = _eina_rbtree_inline_single_rotation(q, dir);
409 else if (!_eina_rbtree_is_red(q->son[!dir]))
410 {
411 Eina_Rbtree *s = p->son[!last];
412
413 if (s)
414 {
415 if (!_eina_rbtree_is_red(s->son[EINA_RBTREE_LEFT])
416 && !_eina_rbtree_is_red(s->son[EINA_RBTREE_RIGHT]))
417 {
418/* Color flip */
419 p->color = EINA_RBTREE_BLACK;
420 p->son[EINA_RBTREE_LEFT]->color = EINA_RBTREE_RED;
421 p->son[EINA_RBTREE_RIGHT]->color = EINA_RBTREE_RED;
422 }
423 else
424 {
425 Eina_Rbtree_Direction dir2;
426
427 dir2 = g->son[1] ==
428 p ? EINA_RBTREE_RIGHT : EINA_RBTREE_LEFT;
429
430 if (_eina_rbtree_is_red(s->son[last]))
431 {
432 g->son[dir2] =
433 _eina_rbtree_inline_double_rotation(p, last);
434 if (f == g)
435 {
436 p = g->son[dir2]->son[last];
437 f = g->son[dir2];
438 }
439 }
440 else if (_eina_rbtree_is_red(s->son[!last]))
441 {
442 g->son[dir2] =
443 _eina_rbtree_inline_single_rotation(p, last);
444 if (f == g)
445 {
446 p = g->son[dir2]->son[last];
447 f = g->son[dir2];
448 }
449 }
450
451/* Ensure correct coloring */
452 q->color = g->son[dir2]->color = EINA_RBTREE_RED;
453 g->son[dir2]->son[EINA_RBTREE_LEFT]->color =
454 EINA_RBTREE_BLACK;
455 g->son[dir2]->son[EINA_RBTREE_RIGHT]->color =
456 EINA_RBTREE_BLACK;
457 }
458 }
459 }
460 }
461 }
462
463 /* Replace and remove if found */
464 if (f)
465 {
466 /* 'q' should take the place of 'node' parent */
467 f->son[f->son[1] == node] = q;
468
469 /* Switch the link from the parent to q's son */
470 p->son[p->son[1] == q] = q->son[!q->son[0]];
471
472 /* Put q at the place of node */
473 q->son[0] = node->son[0];
474 q->son[1] = node->son[1];
475 q->color = node->color;
476
477 /* Reset node link */
478 node->son[0] = NULL;
479 node->son[1] = NULL;
480 }
481
482 root = head.son[1];
483 if (root)
484 root->color = EINA_RBTREE_BLACK;
485
486 return root;
487}
488
489EAPI Eina_Iterator *
490eina_rbtree_iterator_prefix(const Eina_Rbtree *root)
491{
492 return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_PREFIX_MASK);
493}
494
495EAPI Eina_Iterator *
496eina_rbtree_iterator_infix(const Eina_Rbtree *root)
497{
498 return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_INFIX_MASK);
499}
500
501EAPI Eina_Iterator *
502eina_rbtree_iterator_postfix(const Eina_Rbtree *root)
503{
504 return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_POSTFIX_MASK);
505}
506
507EAPI void
508eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data)
509{
510 if (!root)
511 return;
512
513 EINA_SAFETY_ON_NULL_RETURN(func);
514
515 eina_rbtree_delete(root->son[0], func, data);
516 eina_rbtree_delete(root->son[1], func, data);
517 func(root, data);
518}
diff --git a/libraries/eina/src/lib/eina_rectangle.c b/libraries/eina/src/lib/eina_rectangle.c
new file mode 100644
index 0000000..7f0a619
--- /dev/null
+++ b/libraries/eina/src/lib/eina_rectangle.c
@@ -0,0 +1,568 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Cedric BAIL, Carsten Haitzler
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
26#ifdef HAVE_EVIL
27# include <Evil.h>
28#endif
29
30#include "eina_config.h"
31#include "eina_private.h"
32#include "eina_magic.h"
33#include "eina_inlist.h"
34#include "eina_mempool.h"
35#include "eina_list.h"
36#include "eina_trash.h"
37#include "eina_log.h"
38
39/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
40#include "eina_safety_checks.h"
41#include "eina_rectangle.h"
42
43/*============================================================================*
44* Local *
45*============================================================================*/
46
47/**
48 * @cond LOCAL
49 */
50
51#define EINA_RECTANGLE_POOL_MAGIC 0x1578FCB0
52#define EINA_RECTANGLE_ALLOC_MAGIC 0x1578FCB1
53
54#define BUCKET_THRESHOLD 110
55
56typedef struct _Eina_Rectangle_Alloc Eina_Rectangle_Alloc;
57
58struct _Eina_Rectangle_Pool
59{
60 Eina_Inlist *head;
61 Eina_List *empty;
62 void *data;
63
64 Eina_Trash *bucket;
65 unsigned int bucket_count;
66
67 unsigned int references;
68 int w;
69 int h;
70
71 Eina_Bool sorted;
72 EINA_MAGIC
73};
74
75struct _Eina_Rectangle_Alloc
76{
77 EINA_INLIST;
78 Eina_Rectangle_Pool *pool;
79 EINA_MAGIC
80};
81
82#define EINA_MAGIC_CHECK_RECTANGLE_POOL(d) \
83 do { \
84 if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_POOL_MAGIC)) { \
85 EINA_MAGIC_FAIL((d), EINA_RECTANGLE_POOL_MAGIC); } \
86 } while (0)
87
88#define EINA_MAGIC_CHECK_RECTANGLE_ALLOC(d) \
89 do { \
90 if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_ALLOC_MAGIC)) { \
91 EINA_MAGIC_FAIL((d), EINA_RECTANGLE_ALLOC_MAGIC); } \
92 } while (0)
93
94static Eina_Mempool *_eina_rectangle_alloc_mp = NULL;
95static Eina_Mempool *_eina_rectangle_mp = NULL;
96
97static Eina_Trash *_eina_rectangles = NULL;
98static unsigned int _eina_rectangles_count = 0;
99static int _eina_rectangle_log_dom = -1;
100
101#ifdef ERR
102#undef ERR
103#endif
104#define ERR(...) EINA_LOG_DOM_ERR(_eina_rectangle_log_dom, __VA_ARGS__)
105
106#ifdef DBG
107#undef DBG
108#endif
109#define DBG(...) EINA_LOG_DOM_DBG(_eina_rectangle_log_dom, __VA_ARGS__)
110
111static int
112_eina_rectangle_cmp(const Eina_Rectangle *r1, const Eina_Rectangle *r2)
113{
114 return (r2->w * r2->h) - (r1->w * r1->h);
115}
116
117static Eina_List *
118_eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle *r)
119{
120 Eina_Rectangle *match;
121 Eina_List *l;
122 int xw;
123 int yh;
124
125 if (r->w == 0 || r->h == 0)
126 {
127 eina_rectangle_free(r);
128 return empty;
129 }
130
131start_again:
132 xw = r->x + r->w;
133 yh = r->y + r->h;
134
135 EINA_LIST_FOREACH(empty, l, match)
136 {
137 if (match->x == r->x && match->w == r->w
138 && (match->y == yh || r->y == match->y + match->h))
139 {
140 if (match->y > r->y)
141 match->y = r->y;
142
143 match->h += r->h;
144
145 eina_rectangle_free(r);
146
147 empty = eina_list_remove_list(empty, l);
148
149 r = match;
150
151 goto start_again;
152 }
153 else if (match->y == r->y && match->h == r->h
154 && (match->x == xw || r->x == match->x + match->w))
155 {
156 if (match->x > r->x)
157 match->x = r->x;
158
159 match->w += r->w;
160
161 eina_rectangle_free(r);
162
163 empty = eina_list_remove_list(empty, l);
164
165 r = match;
166
167 goto start_again;
168 }
169 }
170
171 return eina_list_append(empty, r);
172}
173
174static Eina_List *
175_eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y)
176{
177 Eina_Rectangle *r;
178 Eina_List *l;
179
180 EINA_LIST_FOREACH(empty, l, r)
181 {
182 if (r->w >= w && r->h >= h)
183 {
184 /* Remove l from empty */
185 empty = eina_list_remove_list(empty, l);
186 /* Remember x and y */
187 *x = r->x;
188 *y = r->y;
189 /* Split r in 2 rectangle if needed (only the empty one) and insert them */
190 if (r->w == w)
191 {
192 r->y += h;
193 r->h -= h;
194 }
195 else if (r->h == h)
196 {
197 r->x += w;
198 r->w -= w;
199 }
200 else
201 {
202 int rx1, ry1, rw1, rh1;
203 int x2, y2, w2, h2;
204
205 rx1 = r->x + w;
206 ry1 = r->y;
207 rw1 = r->w - w;
208 /* h1 could be h or r->h */
209 x2 = r->x;
210 y2 = r->y + h;
211 /* w2 could be w or r->w */
212 h2 = r->h - h;
213
214 if (rw1 * r->h > h2 * r->w)
215 {
216 rh1 = r->h;
217 w2 = w;
218 }
219 else
220 {
221 rh1 = h;
222 w2 = r->w;
223 }
224
225 EINA_RECTANGLE_SET(r, rx1, ry1, rw1, rh1);
226 empty = _eina_rectangle_merge_list(empty, r);
227
228 r = eina_rectangle_new(x2, y2, w2, h2);
229 }
230
231 if (r)
232 {
233 empty = _eina_rectangle_merge_list(empty, r); /* Return empty */
234
235 }
236
237 return empty;
238 }
239 }
240
241 *x = -1;
242 *y = -1;
243 return empty;
244}
245
246/**
247 * @endcond
248 */
249
250/*============================================================================*
251* Global *
252*============================================================================*/
253
254Eina_Bool
255eina_rectangle_init(void)
256{
257 const char *choice, *tmp;
258
259 _eina_rectangle_log_dom = eina_log_domain_register("eina_rectangle",
260 EINA_LOG_COLOR_DEFAULT);
261 if (_eina_rectangle_log_dom < 0)
262 {
263 EINA_LOG_ERR("Could not register log domain: eina_rectangle");
264 return EINA_FALSE;
265 }
266
267#ifdef EINA_DEFAULT_MEMPOOL
268 choice = "pass_through";
269#else
270 choice = "chained_mempool";
271#endif
272 tmp = getenv("EINA_MEMPOOL");
273 if (tmp && tmp[0])
274 choice = tmp;
275
276 _eina_rectangle_alloc_mp = eina_mempool_add
277 (choice, "rectangle-alloc", NULL,
278 sizeof(Eina_Rectangle_Alloc) + sizeof(Eina_Rectangle), 1024);
279 if (!_eina_rectangle_alloc_mp)
280 {
281 ERR("Mempool for rectangle cannot be allocated in rectangle init.");
282 goto init_error;
283 }
284
285 _eina_rectangle_mp = eina_mempool_add
286 (choice, "rectangle", NULL, sizeof(Eina_Rectangle), 256);
287 if (!_eina_rectangle_mp)
288 {
289 ERR("Mempool for rectangle cannot be allocated in rectangle init.");
290 goto init_error;
291 }
292
293 return EINA_TRUE;
294
295init_error:
296 eina_log_domain_unregister(_eina_rectangle_log_dom);
297 _eina_rectangle_log_dom = -1;
298
299 return EINA_FALSE;
300}
301
302Eina_Bool
303eina_rectangle_shutdown(void)
304{
305 Eina_Rectangle *del;
306
307 while ((del = eina_trash_pop(&_eina_rectangles)))
308 eina_mempool_free(_eina_rectangle_mp, del);
309 _eina_rectangles_count = 0;
310
311 eina_mempool_del(_eina_rectangle_alloc_mp);
312 eina_mempool_del(_eina_rectangle_mp);
313
314 eina_log_domain_unregister(_eina_rectangle_log_dom);
315 _eina_rectangle_log_dom = -1;
316
317 return EINA_TRUE;
318}
319
320/*============================================================================*
321* API *
322*============================================================================*/
323
324EAPI Eina_Rectangle *
325eina_rectangle_new(int x, int y, int w, int h)
326{
327 Eina_Rectangle *rect;
328
329 if (_eina_rectangles)
330 {
331 rect = eina_trash_pop(&_eina_rectangles);
332 _eina_rectangles_count--;
333 }
334 else
335 rect = eina_mempool_malloc(_eina_rectangle_mp, sizeof (Eina_Rectangle));
336
337 if (!rect)
338 return NULL;
339
340 EINA_RECTANGLE_SET(rect, x, y, w, h);
341
342 return rect;
343}
344
345EAPI void
346eina_rectangle_free(Eina_Rectangle *rect)
347{
348 EINA_SAFETY_ON_NULL_RETURN(rect);
349
350 if (_eina_rectangles_count > BUCKET_THRESHOLD)
351 eina_mempool_free(_eina_rectangle_mp, rect);
352 else
353 {
354 eina_trash_push(&_eina_rectangles, rect);
355 _eina_rectangles_count++;
356 }
357}
358
359EAPI Eina_Rectangle_Pool *
360eina_rectangle_pool_new(int w, int h)
361{
362 Eina_Rectangle_Pool *new;
363
364 new = malloc(sizeof (Eina_Rectangle_Pool));
365 if (!new)
366 return NULL;
367
368 new->head = NULL;
369 new->empty = eina_list_append(NULL, eina_rectangle_new(0, 0, w, h));
370 new->references = 0;
371 new->sorted = EINA_FALSE;
372 new->w = w;
373 new->h = h;
374 new->bucket = NULL;
375 new->bucket_count = 0;
376
377 EINA_MAGIC_SET(new, EINA_RECTANGLE_POOL_MAGIC);
378 DBG("pool=%p, size=(%d, %d)", new, w, h);
379
380 return new;
381}
382
383EAPI void
384eina_rectangle_pool_free(Eina_Rectangle_Pool *pool)
385{
386 Eina_Rectangle_Alloc *del;
387
388 EINA_SAFETY_ON_NULL_RETURN(pool);
389 DBG("pool=%p, size=(%d, %d), references=%u",
390 pool, pool->w, pool->h, pool->references);
391 while (pool->head)
392 {
393 del = (Eina_Rectangle_Alloc *)pool->head;
394
395 pool->head = (EINA_INLIST_GET(del))->next;
396
397 EINA_MAGIC_SET(del, EINA_MAGIC_NONE);
398 eina_mempool_free(_eina_rectangle_alloc_mp, del);
399 }
400
401 while (pool->bucket)
402 {
403 del = eina_trash_pop(&pool->bucket);
404 eina_mempool_free(_eina_rectangle_alloc_mp, del);
405 }
406
407 MAGIC_FREE(pool);
408}
409
410EAPI int
411eina_rectangle_pool_count(Eina_Rectangle_Pool *pool)
412{
413 EINA_SAFETY_ON_NULL_RETURN_VAL(pool, 0);
414 return pool->references;
415}
416
417EAPI Eina_Rectangle *
418eina_rectangle_pool_request(Eina_Rectangle_Pool *pool, int w, int h)
419{
420 Eina_Rectangle_Alloc *new;
421 Eina_Rectangle *rect;
422 int x;
423 int y;
424
425 EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL);
426
427 DBG("pool=%p, size=(%d, %d), references=%u",
428 pool, pool->w, pool->h, pool->references);
429
430 if (w <= 0 || h <= 0)
431 return NULL;
432
433 if (w > pool->w || h > pool->h)
434 return NULL;
435
436 /* Sort empty if dirty */
437 if (pool->sorted)
438 {
439 pool->empty =
440 eina_list_sort(pool->empty, 0, EINA_COMPARE_CB(_eina_rectangle_cmp));
441 pool->sorted = EINA_TRUE;
442 }
443
444 pool->empty = _eina_rectangle_empty_space_find(pool->empty, w, h, &x, &y);
445 if (x == -1)
446 return NULL;
447
448 pool->sorted = EINA_FALSE;
449
450 if (pool->bucket_count > 0)
451 {
452 new = eina_trash_pop(&pool->bucket);
453 pool->bucket_count--;
454 }
455 else
456 new = eina_mempool_malloc(_eina_rectangle_alloc_mp,
457 sizeof (Eina_Rectangle_Alloc) +
458 sizeof (Eina_Rectangle));
459
460 if (!new)
461 return NULL;
462
463 rect = (Eina_Rectangle *)(new + 1);
464 eina_rectangle_coords_from(rect, x, y, w, h);
465
466 pool->head = eina_inlist_prepend(pool->head, EINA_INLIST_GET(new));
467 pool->references++;
468
469 new->pool = pool;
470
471 EINA_MAGIC_SET(new, EINA_RECTANGLE_ALLOC_MAGIC);
472 DBG("rect=%p pool=%p, size=(%d, %d), references=%u",
473 rect, pool, pool->w, pool->h, pool->references);
474
475 return rect;
476}
477
478EAPI void
479eina_rectangle_pool_release(Eina_Rectangle *rect)
480{
481 Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1;
482 Eina_Rectangle *r;
483
484 EINA_SAFETY_ON_NULL_RETURN(rect);
485
486 EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era);
487 EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool);
488
489 DBG("rect=%p pool=%p, size=(%d, %d), references=%u",
490 rect, era->pool, era->pool->w, era->pool->h, era->pool->references);
491
492 era->pool->references--;
493 era->pool->head = eina_inlist_remove(era->pool->head, EINA_INLIST_GET(era));
494
495 r = eina_rectangle_new(rect->x, rect->y, rect->w, rect->h);
496 if (r)
497 {
498 era->pool->empty = _eina_rectangle_merge_list(era->pool->empty, r);
499 era->pool->sorted = EINA_FALSE;
500 }
501
502 if (era->pool->bucket_count < BUCKET_THRESHOLD)
503 {
504 Eina_Rectangle_Pool *pool;
505
506 pool = era->pool;
507
508 pool->bucket_count++;
509 eina_trash_push(&pool->bucket, era);
510 }
511 else
512 {
513 EINA_MAGIC_SET(era, EINA_MAGIC_NONE);
514 eina_mempool_free(_eina_rectangle_alloc_mp, era);
515 }
516}
517
518EAPI Eina_Rectangle_Pool *
519eina_rectangle_pool_get(Eina_Rectangle *rect)
520{
521 Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1;
522
523 EINA_SAFETY_ON_NULL_RETURN_VAL(rect, NULL);
524
525 EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era);
526 EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool);
527
528 return era->pool;
529}
530
531EAPI void
532eina_rectangle_pool_data_set(Eina_Rectangle_Pool *pool, const void *data)
533{
534 EINA_MAGIC_CHECK_RECTANGLE_POOL(pool);
535 EINA_SAFETY_ON_NULL_RETURN(pool);
536
537 DBG("data=%p pool=%p, size=(%d, %d), references=%u",
538 data, pool, pool->w, pool->h, pool->references);
539
540 pool->data = (void *)data;
541}
542
543EAPI void *
544eina_rectangle_pool_data_get(Eina_Rectangle_Pool *pool)
545{
546 EINA_MAGIC_CHECK_RECTANGLE_POOL(pool);
547 EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL);
548
549 return pool->data;
550}
551
552EAPI Eina_Bool
553eina_rectangle_pool_geometry_get(Eina_Rectangle_Pool *pool, int *w, int *h)
554{
555 if (!pool)
556 return EINA_FALSE;
557
558 EINA_MAGIC_CHECK_RECTANGLE_POOL(pool);
559 EINA_SAFETY_ON_NULL_RETURN_VAL(pool, EINA_FALSE);
560
561 if (w)
562 *w = pool->w;
563
564 if (h)
565 *h = pool->h;
566
567 return EINA_TRUE;
568}
diff --git a/libraries/eina/src/lib/eina_safety_checks.c b/libraries/eina/src/lib/eina_safety_checks.c
new file mode 100644
index 0000000..eed7c59
--- /dev/null
+++ b/libraries/eina/src/lib/eina_safety_checks.c
@@ -0,0 +1,90 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Gustavo Sverzut Barbieri
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 "eina_private.h"
24#include "eina_error.h"
25#include "eina_log.h"
26#include "eina_safety_checks.h"
27
28/*============================================================================*
29* Local *
30*============================================================================*/
31
32/*============================================================================*
33* Global *
34*============================================================================*/
35
36/**
37 * @internal
38 * @brief Shut down the safety checks module.
39 *
40 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
41 *
42 * This function shuts down the error module set up by
43 * eina_safety_checks_init(). It is called by eina_shutdown().
44 *
45 * @see eina_shutdown()
46 */
47Eina_Bool
48eina_safety_checks_shutdown(void)
49{
50 return EINA_TRUE;
51}
52
53/*============================================================================*
54* API *
55*============================================================================*/
56
57/**
58 * @cond LOCAL
59 */
60
61EAPI Eina_Error EINA_ERROR_SAFETY_FAILED = 0;
62
63static const char EINA_ERROR_SAFETY_FAILED_STR[] = "Safety check failed.";
64
65/**
66 * @endcond
67 */
68
69/**
70 * @internal
71 * @brief Initialize the safety checks module.
72 *
73 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
74 *
75 * This function sets up the safety checks module of Eina. It is
76 * called by eina_init().
77 *
78 * @see eina_init()
79 */
80Eina_Bool
81eina_safety_checks_init(void)
82{
83 EINA_ERROR_SAFETY_FAILED = eina_error_msg_static_register(
84 EINA_ERROR_SAFETY_FAILED_STR);
85 return EINA_TRUE;
86}
87
88/**
89 * @}
90 */
diff --git a/libraries/eina/src/lib/eina_sched.c b/libraries/eina/src/lib/eina_sched.c
new file mode 100644
index 0000000..8c7f7fe
--- /dev/null
+++ b/libraries/eina/src/lib/eina_sched.c
@@ -0,0 +1,94 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2010 ProFUSION embedded systems
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_POSIX_THREADS
24# include <pthread.h>
25# ifdef __linux__
26# include <sched.h>
27# include <sys/time.h>
28# include <sys/resource.h>
29# include <errno.h>
30# endif
31#endif
32
33#ifdef EFL_HAVE_WIN32_THREADS
34# ifndef WIN32_LEAN_AND_MEAN
35# define WIN32_LEAN_AND_MEAN
36# endif
37# include <windows.h>
38# undef WIN32_LEAN_AND_MEAN
39#endif
40
41#include "eina_sched.h"
42#include "eina_log.h"
43
44#define RTNICENESS 5
45#define NICENESS 5
46
47EAPI void
48eina_sched_prio_drop(void)
49{
50#ifdef EFL_HAVE_POSIX_THREADS
51 struct sched_param param;
52 int pol, prio, ret;
53 pthread_t pthread_id;
54
55 pthread_id = pthread_self();
56 ret = pthread_getschedparam(pthread_id, &pol, &param);
57 if (ret)
58 {
59 EINA_LOG_ERR("Unable to query sched parameters");
60 return;
61 }
62
63 if (EINA_UNLIKELY(pol == SCHED_RR || pol == SCHED_FIFO))
64 {
65 prio = sched_get_priority_max(pol);
66 param.sched_priority += RTNICENESS;
67 if (prio > 0 && param.sched_priority > prio)
68 param.sched_priority = prio;
69
70 pthread_setschedparam(pthread_id, pol, &param);
71 }
72# ifdef __linux__
73 else
74 {
75 errno = 0;
76 prio = getpriority(PRIO_PROCESS, 0);
77 if (errno == 0)
78 {
79 prio += NICENESS;
80 if (prio > 19)
81 prio = 19;
82
83 setpriority(PRIO_PROCESS, 0, prio);
84 }
85 }
86# endif
87#elif defined EFL_HAVE_WIN32_THREADS
88 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
89 EINA_LOG_ERR("Can not set thread priority");
90#else
91 EINA_LOG_ERR("Eina does not have support for threads enabled"
92 "or it doesn't support setting scheduler priorities");
93#endif
94}
diff --git a/libraries/eina/src/lib/eina_share_common.c b/libraries/eina/src/lib/eina_share_common.c
new file mode 100644
index 0000000..90e1868
--- /dev/null
+++ b/libraries/eina/src/lib/eina_share_common.c
@@ -0,0 +1,977 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010
3 * Carsten Haitzler,
4 * Jorge Luis Zapata Muga,
5 * Cedric Bail,
6 * Gustavo Sverzut Barbieri
7 * Tom Hacohen
8 * Brett Nash
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library;
22 * if not, see <http://www.gnu.org/licenses/>.
23 *
24 * This file incorporates work covered by the following copyright and
25 * permission notice:
26 *
27 * Copyright (C) 2008 Peter Wehrfritz
28 *
29 * Permission is hereby granted, free of charge, to any person obtaining a copy
30 * of this software and associated documentation files (the "Software"), to
31 * deal in the Software without restriction, including without limitation the
32 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
33 * sell copies of the Software, and to permit persons to whom the Software is
34 * furnished to do so, subject to the following conditions:
35 *
36 * The above copyright notice and this permission notice shall be included in
37 * all copies of the Software and its Copyright notices. In addition publicly
38 * documented acknowledgment must be given that this software has been used if no
39 * source code of this software is made available publicly. This includes
40 * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
41 * documents or any documentation provided with any product containing this
42 * software. This License does not apply to any software that links to the
43 * libraries provided by this software (statically or dynamically), but only to
44 * the software provided.
45 *
46 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
47 * and it's intent.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
52 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
53 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
54 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55 */
56
57#ifdef HAVE_CONFIG_H
58# include "config.h"
59#endif
60
61#include <stdlib.h>
62#include <stdio.h>
63#include <string.h>
64#include <stddef.h>
65
66#ifdef EFL_HAVE_POSIX_THREADS
67# include <pthread.h>
68#endif
69
70#ifdef HAVE_EVIL
71# include <Evil.h>
72#endif
73
74#include "eina_config.h"
75#include "eina_private.h"
76#include "eina_hash.h"
77#include "eina_rbtree.h"
78#include "eina_error.h"
79#include "eina_log.h"
80#include "eina_lock.h"
81
82/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
83#include "eina_safety_checks.h"
84#include "eina_share_common.h"
85
86/*============================================================================*
87* Local *
88*============================================================================*/
89
90/**
91 * @cond LOCAL
92 */
93
94#define EINA_SHARE_COMMON_BUCKETS 256
95#define EINA_SHARE_COMMON_MASK 0xFF
96
97static const char EINA_MAGIC_SHARE_STR[] = "Eina Share";
98static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head";
99
100static int _eina_share_common_count = 0;
101
102#define EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(d, unlock, ...) \
103 do { \
104 if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_SHARE_HEAD)) \
105 { \
106 EINA_MAGIC_FAIL((d), EINA_MAGIC_SHARE_HEAD); \
107 unlock; \
108 return __VA_ARGS__; \
109 } \
110 } while (0)
111
112#define EINA_MAGIC_CHECK_SHARE_COMMON_NODE(d, _node_magic, unlock) \
113 do { \
114 if (!EINA_MAGIC_CHECK((d), _node_magic)) \
115 { \
116 EINA_MAGIC_FAIL((d), _node_magic); \
117 unlock; \
118 } \
119 } while (0)
120
121#ifdef EINA_SHARE_USAGE
122typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population;
123#endif
124
125typedef struct _Eina_Share_Common Eina_Share_Common;
126typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node;
127typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head;
128
129int _eina_share_common_log_dom = -1;
130
131struct _Eina_Share
132{
133 Eina_Share_Common *share;
134 Eina_Magic node_magic;
135#ifdef EINA_SHARE_COMMON_USAGE
136 Eina_Share_Common_Population population;
137 int max_node_population;
138#endif
139};
140
141struct _Eina_Share_Common
142{
143 Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS];
144
145 EINA_MAGIC
146};
147
148struct _Eina_Share_Common_Node
149{
150 Eina_Share_Common_Node *next;
151
152 EINA_MAGIC
153
154 unsigned int length;
155 unsigned int references;
156 char str[];
157};
158
159struct _Eina_Share_Common_Head
160{
161 EINA_RBTREE;
162 EINA_MAGIC
163
164 int hash;
165
166#ifdef EINA_SHARE_COMMON_USAGE
167 int population;
168#endif
169
170 Eina_Share_Common_Node *head;
171 Eina_Share_Common_Node builtin_node;
172};
173
174Eina_Bool _share_common_threads_activated = EINA_FALSE;
175
176static Eina_Lock _mutex_big;
177
178#ifdef EINA_SHARE_COMMON_USAGE
179struct _Eina_Share_Common_Population
180{
181 int count;
182 int max;
183};
184
185static Eina_Share_Common_Population population = { 0, 0 };
186
187static Eina_Share_Common_Population population_group[4] =
188{
189 { 0, 0 },
190 { 0, 0 },
191 { 0, 0 },
192 { 0, 0 }
193};
194
195static void
196_eina_share_common_population_init(Eina_Share *share)
197{
198 unsigned int i;
199
200 for (i = 0;
201 i < sizeof (share->population_group) /
202 sizeof (share->population_group[0]);
203 ++i)
204 {
205 share->population_group[i].count = 0;
206 share->population_group[i].max = 0;
207 }
208}
209
210static void
211_eina_share_common_population_shutdown(Eina_Share *share)
212{
213 unsigned int i;
214
215 share->max_node_population = 0;
216 share->population.count = 0;
217 share->population.max = 0;
218
219 for (i = 0;
220 i < sizeof (share->population_group) /
221 sizeof (share->population_group[0]);
222 ++i)
223 {
224 share->population_group[i].count = 0;
225 share->population_group[i].max = 0;
226 }
227}
228
229static void
230_eina_share_common_population_stats(Eina_Share *share)
231{
232 unsigned int i;
233
234 fprintf(stderr, "eina share_common statistic:\n");
235 fprintf(stderr,
236 " * maximum shared strings : %i\n",
237 share->population.max);
238 fprintf(stderr,
239 " * maximum shared strings per node : %i\n",
240 share->max_node_population);
241
242 for (i = 0;
243 i < sizeof (share->population_group) /
244 sizeof (share->population_group[0]);
245 ++i)
246 fprintf(stderr,
247 "DDD: %i strings of length %i, max strings: %i\n",
248 share->population_group[i].count,
249 i,
250 share->population_group[i].max);
251}
252
253void
254eina_share_common_population_add(Eina_Share *share, int slen)
255{
256 eina_lock_take(&_mutex_big);
257
258 share->population.count++;
259 if (share->population.count > share->population.max)
260 share->population.max = share->population.count;
261
262 if (slen < 4)
263 {
264 share->population_group[slen].count++;
265 if (share->population_group[slen].count >
266 share->population_group[slen].max)
267 share->population_group[slen].max =
268 share->population_group[slen].count;
269 }
270
271 eina_lock_release(&_mutex_big);
272}
273
274void
275eina_share_common_population_del(Eina_Share *share, int slen)
276{
277 eina_lock_take(&_mutex_big);
278
279 share->population.count--;
280 if (slen < 4)
281 share->population_group[slen].count--;
282
283 eina_lock_release(&_mutex_big);
284}
285
286static void
287_eina_share_common_population_head_init(Eina_Share *share,
288 Eina_Share_Common_Head *head)
289{
290 head->population = 1;
291}
292
293static void
294_eina_share_common_population_head_add(Eina_Share *share,
295 Eina_Share_Common_Head *head)
296{
297 head->population++;
298 if (head->population > share->max_node_population)
299 share->max_node_population = head->population;
300}
301
302static void
303_eina_share_common_population_head_del(Eina_Share *share,
304 Eina_Share_Common_Head *head)
305{
306 head->population--;
307}
308
309#else /* EINA_SHARE_COMMON_USAGE undefined */
310
311static void _eina_share_common_population_init(__UNUSED__ Eina_Share *share) {
312}
313static void _eina_share_common_population_shutdown(__UNUSED__ Eina_Share *share)
314{
315}
316static void _eina_share_common_population_stats(__UNUSED__ Eina_Share *share) {
317}
318void eina_share_common_population_add(__UNUSED__ Eina_Share *share,
319 __UNUSED__ int slen) {
320}
321void eina_share_common_population_del(__UNUSED__ Eina_Share *share,
322 __UNUSED__ int slen) {
323}
324static void _eina_share_common_population_head_init(
325 __UNUSED__ Eina_Share *share,
326 __UNUSED__ Eina_Share_Common_Head *head) {
327}
328static void _eina_share_common_population_head_add(
329 __UNUSED__ Eina_Share *share,
330 __UNUSED__
331 Eina_Share_Common_Head *head) {
332}
333static void _eina_share_common_population_head_del(
334 __UNUSED__ Eina_Share *share,
335 __UNUSED__
336 Eina_Share_Common_Head *head) {
337}
338#endif
339
340static int
341_eina_share_common_cmp(const Eina_Share_Common_Head *ed,
342 const int *hash,
343 __UNUSED__ int length,
344 __UNUSED__ void *data)
345{
346 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0);
347
348 return ed->hash - *hash;
349}
350
351static Eina_Rbtree_Direction
352_eina_share_common_node(const Eina_Share_Common_Head *left,
353 const Eina_Share_Common_Head *right,
354 __UNUSED__ void *data)
355{
356 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left, , 0);
357 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0);
358
359 if (left->hash - right->hash < 0)
360 return EINA_RBTREE_LEFT;
361
362 return EINA_RBTREE_RIGHT;
363}
364
365static void
366_eina_share_common_head_free(Eina_Share_Common_Head *ed, __UNUSED__ void *data)
367{
368 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, );
369
370 while (ed->head)
371 {
372 Eina_Share_Common_Node *el = ed->head;
373
374 ed->head = ed->head->next;
375 if (el != &ed->builtin_node)
376 MAGIC_FREE(el);
377 }
378 MAGIC_FREE(ed);
379}
380
381static void
382_eina_share_common_node_init(Eina_Share_Common_Node *node,
383 const char *str,
384 int slen,
385 unsigned int null_size,
386 Eina_Magic node_magic)
387{
388 EINA_MAGIC_SET(node, node_magic);
389 node->references = 1;
390 node->length = slen;
391 memcpy(node->str, str, slen);
392 memset(node->str + slen, 0, null_size); /* Nullify the null */
393
394 (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */
395}
396
397static Eina_Share_Common_Head *
398_eina_share_common_head_alloc(int slen)
399{
400 Eina_Share_Common_Head *head;
401 const size_t head_size = offsetof(Eina_Share_Common_Head, builtin_node.str);
402
403 head = malloc(head_size + slen);
404 if (!head)
405 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
406
407 return head;
408}
409
410static const char *
411_eina_share_common_add_head(Eina_Share *share,
412 Eina_Share_Common_Head **p_bucket,
413 int hash,
414 const char *str,
415 unsigned int slen,
416 unsigned int null_size)
417{
418 Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket;
419 Eina_Share_Common_Head *head;
420
421 head = _eina_share_common_head_alloc(slen + null_size);
422 if (!head)
423 return NULL;
424
425 EINA_MAGIC_SET(head, EINA_MAGIC_SHARE_HEAD);
426 head->hash = hash;
427 head->head = &head->builtin_node;
428 _eina_share_common_node_init(head->head,
429 str,
430 slen,
431 null_size,
432 share->node_magic);
433 head->head->next = NULL;
434
435 _eina_share_common_population_head_init(share, head);
436
437 *p_tree = eina_rbtree_inline_insert
438 (*p_tree, EINA_RBTREE_GET(head),
439 EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL);
440
441 return head->head->str;
442}
443
444static void
445_eina_share_common_del_head(Eina_Share_Common_Head **p_bucket,
446 Eina_Share_Common_Head *head)
447{
448 Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket;
449
450 *p_tree = eina_rbtree_inline_remove
451 (*p_tree, EINA_RBTREE_GET(head),
452 EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL);
453
454 MAGIC_FREE(head);
455}
456
457
458static inline Eina_Bool
459_eina_share_common_node_eq(const Eina_Share_Common_Node *node,
460 const char *str,
461 unsigned int slen)
462{
463 return ((node->length == slen) &&
464 (memcmp(node->str, str, slen) == 0));
465}
466
467static Eina_Share_Common_Node *
468_eina_share_common_head_find(Eina_Share_Common_Head *head,
469 const char *str,
470 unsigned int slen)
471{
472 Eina_Share_Common_Node *node, *prev;
473
474 node = head->head;
475 if (_eina_share_common_node_eq(node, str, slen))
476 return node;
477
478 prev = node;
479 node = node->next;
480 for (; node; prev = node, node = node->next)
481 if (_eina_share_common_node_eq(node, str, slen))
482 {
483 /* promote node, make hot items be at the beginning */
484 prev->next = node->next;
485 node->next = head->head;
486 head->head = node;
487 return node;
488 }
489
490 return NULL;
491}
492
493static Eina_Bool
494_eina_share_common_head_remove_node(Eina_Share_Common_Head *head,
495 const Eina_Share_Common_Node *node)
496{
497 Eina_Share_Common_Node *cur, *prev;
498
499 if (head->head == node)
500 {
501 head->head = node->next;
502 return 1;
503 }
504
505 prev = head->head;
506 cur = head->head->next;
507 for (; cur; prev = cur, cur = cur->next)
508 if (cur == node)
509 {
510 prev->next = cur->next;
511 return 1;
512 }
513
514 return 0;
515}
516
517static Eina_Share_Common_Head *
518_eina_share_common_find_hash(Eina_Share_Common_Head *bucket, int hash)
519{
520 return (Eina_Share_Common_Head *)eina_rbtree_inline_lookup
521 (EINA_RBTREE_GET(bucket), &hash, 0,
522 EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL);
523}
524
525static Eina_Share_Common_Node *
526_eina_share_common_node_alloc(unsigned int slen, unsigned int null_size)
527{
528 Eina_Share_Common_Node *node;
529 const size_t node_size = offsetof(Eina_Share_Common_Node, str);
530
531 node = malloc(node_size + slen + null_size);
532 if (!node)
533 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
534
535 return node;
536}
537
538static Eina_Share_Common_Node *
539_eina_share_common_node_from_str(const char *str, Eina_Magic node_magic)
540{
541 Eina_Share_Common_Node *node;
542 const size_t offset = offsetof(Eina_Share_Common_Node, str);
543
544 node = (Eina_Share_Common_Node *)(str - offset);
545 EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node = NULL);
546 return node;
547
548 (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */
549}
550
551static Eina_Bool
552eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__,
553 Eina_Share_Common_Head *head,
554 struct dumpinfo *fdata)
555{
556 Eina_Share_Common_Node *node;
557
558 fdata->used += sizeof(Eina_Share_Common_Head);
559 for (node = head->head; node; node = node->next)
560 {
561 printf("DDD: %5i %5i ", node->length, node->references);
562 printf("'%.*s'\n", node->length, ((char *)node) + sizeof(Eina_Share_Common_Node));
563 fdata->used += sizeof(Eina_Share_Common_Node);
564 fdata->used += node->length;
565 fdata->saved += (node->references - 1) * node->length;
566 fdata->dups += node->references - 1;
567 fdata->unique++;
568 }
569
570 return EINA_TRUE;
571}
572
573/**
574 * @endcond
575 */
576
577
578/*============================================================================*
579* Global *
580*============================================================================*/
581
582/**
583 * @internal
584 * @brief Initialize the share_common module.
585 *
586 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
587 *
588 * This function sets up the share_common module of Eina. It is called by
589 * eina_init().
590 *
591 * @see eina_init()
592 */
593Eina_Bool
594eina_share_common_init(Eina_Share **_share,
595 Eina_Magic node_magic,
596 const char *node_magic_STR)
597{
598 Eina_Share *share;
599
600 share = *_share = calloc(sizeof(Eina_Share), 1);
601 if (!share) goto on_error;
602
603 if (_eina_share_common_log_dom < 0) /*Only register if not already */
604 _eina_share_common_log_dom = eina_log_domain_register(
605 "eina_share",
606 EINA_LOG_COLOR_DEFAULT);
607
608 if (_eina_share_common_log_dom < 0)
609 {
610 EINA_LOG_ERR("Could not register log domain: eina_share_common");
611 goto on_error;
612 }
613
614 share->share = calloc(1, sizeof(Eina_Share_Common));
615 if (!share->share)
616 {
617 if (_eina_share_common_log_dom > 0)
618 {
619 eina_log_domain_unregister(_eina_share_common_log_dom);
620 _eina_share_common_log_dom = -1;
621 }
622
623 goto on_error;
624 }
625
626 share->node_magic = node_magic;
627#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
628 EMS(EINA_MAGIC_SHARE);
629 EMS(EINA_MAGIC_SHARE_HEAD);
630 EMS(node_magic);
631#undef EMS
632 EINA_MAGIC_SET(share->share, EINA_MAGIC_SHARE);
633
634 _eina_share_common_population_init(share);
635
636 /* below is the common part among other all eina_share_common user */
637 if (_eina_share_common_count++ != 0)
638 return EINA_TRUE;
639
640 eina_lock_new(&_mutex_big);
641 return EINA_TRUE;
642
643 on_error:
644 _eina_share_common_count--;
645 return EINA_FALSE;
646}
647
648/**
649 * @internal
650 * @brief Shut down the share_common module.
651 *
652 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
653 *
654 * This function shuts down the share_common module set up by
655 * eina_share_common_init(). It is called by eina_shutdown().
656 *
657 * @see eina_shutdown()
658 */
659Eina_Bool
660eina_share_common_shutdown(Eina_Share **_share)
661{
662 unsigned int i;
663 Eina_Share *share = *_share;
664
665 eina_lock_take(&_mutex_big);
666
667 _eina_share_common_population_stats(share);
668
669 /* remove any string still in the table */
670 for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++)
671 {
672 eina_rbtree_delete(EINA_RBTREE_GET(
673 share->share->buckets[i]),
674 EINA_RBTREE_FREE_CB(
675 _eina_share_common_head_free), NULL);
676 share->share->buckets[i] = NULL;
677 }
678 MAGIC_FREE(share->share);
679
680 _eina_share_common_population_shutdown(share);
681 if (_eina_share_common_log_dom > 0) /* Only free if necessary */
682 {
683 eina_log_domain_unregister(_eina_share_common_log_dom);
684 _eina_share_common_log_dom = -1;
685 }
686
687 eina_lock_release(&_mutex_big);
688
689 free(*_share);
690 *_share = NULL;
691
692 /* below is the common part among other all eina_share_common user */
693 if (--_eina_share_common_count != 0)
694 return EINA_TRUE;
695
696 eina_lock_free(&_mutex_big);
697
698 return EINA_TRUE;
699}
700
701#ifdef EFL_HAVE_THREADS
702
703/**
704 * @internal
705 * @brief Activate the share_common mutexes.
706 *
707 * This function activate the mutexes in the eina share_common module. It is called by
708 * eina_threads_init().
709 *
710 * @see eina_threads_init()
711 */
712void
713eina_share_common_threads_init(void)
714{
715 _share_common_threads_activated = EINA_TRUE;
716}
717
718/**
719 * @internal
720 * @brief Shut down the share_common mutexes.
721 *
722 * This function shuts down the mutexes in the share_common module.
723 * It is called by eina_threads_shutdown().
724 *
725 * @see eina_threads_shutdown()
726 */
727void
728eina_share_common_threads_shutdown(void)
729{
730 _share_common_threads_activated = EINA_FALSE;
731}
732
733#endif
734
735/*============================================================================*
736* API *
737*============================================================================*/
738
739/**
740 * @cond LOCAL
741 */
742
743const char *
744eina_share_common_add_length(Eina_Share *share,
745 const char *str,
746 unsigned int slen,
747 unsigned int null_size)
748{
749 Eina_Share_Common_Head **p_bucket, *ed;
750 Eina_Share_Common_Node *el;
751 int hash_num, hash;
752
753 if (!str)
754 return NULL;
755
756 eina_share_common_population_add(share, slen);
757
758 if (slen <= 0)
759 return NULL;
760
761 hash = eina_hash_superfast(str, slen);
762 hash_num = hash & 0xFF;
763 hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
764
765 eina_lock_take(&_mutex_big);
766 p_bucket = share->share->buckets + hash_num;
767
768 ed = _eina_share_common_find_hash(*p_bucket, hash);
769 if (!ed)
770 {
771 const char *s = _eina_share_common_add_head(share,
772 p_bucket,
773 hash,
774 str,
775 slen,
776 null_size);
777 eina_lock_release(&_mutex_big);
778 return s;
779 }
780
781 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), NULL);
782
783 el = _eina_share_common_head_find(ed, str, slen);
784 if (el)
785 {
786 EINA_MAGIC_CHECK_SHARE_COMMON_NODE(el,
787 share->node_magic,
788 eina_lock_release(&_mutex_big));
789 el->references++;
790 eina_lock_release(&_mutex_big);
791 return el->str;
792 }
793
794 el = _eina_share_common_node_alloc(slen, null_size);
795 if (!el)
796 {
797 eina_lock_release(&_mutex_big);
798 return NULL;
799 }
800
801 _eina_share_common_node_init(el, str, slen, null_size, share->node_magic);
802 el->next = ed->head;
803 ed->head = el;
804 _eina_share_common_population_head_add(share, ed);
805
806 eina_lock_release(&_mutex_big);
807
808 return el->str;
809}
810
811const char *
812eina_share_common_ref(Eina_Share *share, const char *str)
813{
814 Eina_Share_Common_Node *node;
815
816 if (!str)
817 return NULL;
818
819 eina_lock_take(&_mutex_big);
820 node = _eina_share_common_node_from_str(str, share->node_magic);
821 if (!node)
822 {
823 eina_lock_release(&_mutex_big);
824 return str;
825 }
826 node->references++;
827
828 eina_lock_release(&_mutex_big);
829
830 eina_share_common_population_add(share, node->length);
831
832 return str;
833}
834
835
836void
837eina_share_common_del(Eina_Share *share, const char *str)
838{
839 unsigned int slen;
840 Eina_Share_Common_Head *ed;
841 Eina_Share_Common_Head **p_bucket;
842 Eina_Share_Common_Node *node;
843 int hash_num, hash;
844
845 if (!str)
846 return;
847
848 eina_lock_take(&_mutex_big);
849
850 node = _eina_share_common_node_from_str(str, share->node_magic);
851 if (!node)
852 goto on_error;
853
854 slen = node->length;
855 eina_share_common_population_del(share, slen);
856 if (node->references > 1)
857 {
858 node->references--;
859 eina_lock_release(&_mutex_big);
860 return;
861 }
862
863 node->references = 0;
864
865 hash = eina_hash_superfast(str, slen);
866 hash_num = hash & 0xFF;
867 hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
868
869 p_bucket = share->share->buckets + hash_num;
870 ed = _eina_share_common_find_hash(*p_bucket, hash);
871 if (!ed)
872 goto on_error;
873
874 EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big));
875
876 if (!_eina_share_common_head_remove_node(ed, node))
877 goto on_error;
878
879 if (node != &ed->builtin_node)
880 MAGIC_FREE(node);
881
882 if (!ed->head)
883 _eina_share_common_del_head(p_bucket, ed);
884 else
885 _eina_share_common_population_head_del(share, ed);
886
887 eina_lock_release(&_mutex_big);
888
889 return;
890
891on_error:
892 eina_lock_release(&_mutex_big);
893 /* possible segfault happened before here, but... */
894 CRITICAL("EEEK trying to del non-shared share_common \"%s\"", str);
895}
896
897int
898eina_share_common_length(__UNUSED__ Eina_Share *share, const char *str)
899{
900 const Eina_Share_Common_Node *node;
901
902 if (!str)
903 return -1;
904
905 node = _eina_share_common_node_from_str(str, share->node_magic);
906 if (!node) return 0;
907 return node->length;
908}
909
910void
911eina_share_common_dump(Eina_Share *share, void (*additional_dump)(
912 struct dumpinfo *), int used)
913{
914 Eina_Iterator *it;
915 unsigned int i;
916 struct dumpinfo di;
917
918 if (!share)
919 return;
920
921 di.used = used;
922 di.saved = 0;
923 di.dups = 0;
924 di.unique = 0;
925 printf("DDD: len ref string\n");
926 printf("DDD:-------------------\n");
927
928 eina_lock_take(&_mutex_big);
929 for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++)
930 {
931 if (!share->share->buckets[i])
932 {
933 continue; // printf("DDD: BUCKET # %i (HEAD=%i, NODE=%i)\n", i,
934
935 }
936
937// sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node));
938 it = eina_rbtree_iterator_prefix(
939 (Eina_Rbtree *)share->share->buckets[i]);
940 eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di);
941 eina_iterator_free(it);
942 }
943 if (additional_dump)
944 additional_dump(&di);
945
946#ifdef EINA_SHARE_COMMON_USAGE
947 /* One character strings are not counted in the hash. */
948 di.saved += share->population_group[0].count * sizeof(char);
949 di.saved += share->population_group[1].count * sizeof(char) * 2;
950#endif
951 printf("DDD:-------------------\n");
952 printf("DDD: usage (bytes) = %i, saved = %i (%3.0f%%)\n",
953 di.used, di.saved, di.used ? (di.saved * 100.0 / di.used) : 0.0);
954 printf("DDD: unique: %d, duplicates: %d (%3.0f%%)\n",
955 di.unique, di.dups, di.unique ? (di.dups * 100.0 / di.unique) : 0.0);
956
957#ifdef EINA_SHARE_COMMON_USAGE
958 printf("DDD: Allocated strings: %i\n", share->population.count);
959 printf("DDD: Max allocated strings: %i\n", share->population.max);
960
961 for (i = 0;
962 i < sizeof (share->population_group) /
963 sizeof (share->population_group[0]);
964 ++i)
965 fprintf(stderr,
966 "DDD: %i strings of length %i, max strings: %i\n",
967 share->population_group[i].count,
968 i,
969 share->population_group[i].max);
970#endif
971
972 eina_lock_release(&_mutex_big);
973}
974
975/**
976 * @endcond
977 */
diff --git a/libraries/eina/src/lib/eina_share_common.h b/libraries/eina/src/lib/eina_share_common.h
new file mode 100644
index 0000000..002c652
--- /dev/null
+++ b/libraries/eina/src/lib/eina_share_common.h
@@ -0,0 +1,103 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, 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 * This file incorporates work covered by the following copyright and
19 * permission notice:
20 *
21 * Copyright (C) 2008 Peter Wehrfritz
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to
25 * deal in the Software without restriction, including without limitation the
26 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
27 * sell copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies of the Software and its Copyright notices. In addition publicly
32 * documented acknowledgment must be given that this software has been used if no
33 * source code of this software is made available publicly. This includes
34 * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
35 * documents or any documentation provided with any product containing this
36 * software. This License does not apply to any software that links to the
37 * libraries provided by this software (statically or dynamically), but only to
38 * the software provided.
39 *
40 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
41 * and it's intent.
42 *
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
46 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
47 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 */
50
51#ifndef EINA_SHARE_COMMON_H_
52#define EINA_SHARE_COMMON_H_
53
54#include "eina_types.h"
55#include "eina_magic.h"
56
57typedef struct _Eina_Share Eina_Share;
58
59struct dumpinfo
60{
61 int used, saved, dups, unique;
62};
63
64Eina_Bool eina_share_common_init(Eina_Share **share,
65 Eina_Magic node_magic,
66 const char *node_magic_STR);
67Eina_Bool eina_share_common_shutdown(Eina_Share **share);
68const char *eina_share_common_add_length(Eina_Share *share,
69 const char *str,
70 unsigned int slen,
71 unsigned int null_size)
72EINA_WARN_UNUSED_RESULT;
73const char *eina_share_common_ref(Eina_Share *share, const char *str);
74void eina_share_common_del(Eina_Share *share, const char *str);
75int eina_share_common_length(Eina_Share *share,
76 const char *str) EINA_CONST
77EINA_WARN_UNUSED_RESULT;
78void eina_share_common_dump(Eina_Share *share, void (*additional_dump)(
79 struct dumpinfo *), int used);
80
81
82/* Population functions */
83void eina_share_common_population_add(Eina_Share *share, int slen);
84void eina_share_common_population_del(Eina_Share *share, int slen);
85
86/* Share logging */
87#ifdef CRITICAL
88#undef CRITICAL
89#endif
90#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_common_log_dom, __VA_ARGS__)
91
92#ifdef ERR
93#undef ERR
94#endif
95#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_common_log_dom, __VA_ARGS__)
96
97#ifdef DBG
98#undef DBG
99#endif
100#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_common_log_dom, __VA_ARGS__)
101extern int _eina_share_common_log_dom;
102
103#endif /* EINA_STRINGSHARE_H_ */
diff --git a/libraries/eina/src/lib/eina_simple_xml_parser.c b/libraries/eina/src/lib/eina_simple_xml_parser.c
new file mode 100644
index 0000000..08a8259
--- /dev/null
+++ b/libraries/eina/src/lib/eina_simple_xml_parser.c
@@ -0,0 +1,1070 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2011 Gustavo Sverzut Barbieri
3 * 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 <strings.h>
42#include <string.h>
43#include <ctype.h>
44
45#ifdef HAVE_EVIL
46# include <Evil.h>
47#endif
48
49#include "eina_private.h"
50#include "eina_log.h"
51#include "eina_mempool.h"
52#include "eina_stringshare.h"
53#include "eina_strbuf.h"
54#include "eina_simple_xml_parser.h"
55
56/*============================================================================*
57 * Local *
58 *============================================================================*/
59
60/**
61 * @cond LOCAL
62 */
63
64static Eina_Mempool *_eina_simple_xml_tag_mp = NULL;
65static Eina_Mempool *_eina_simple_xml_attribute_mp = NULL;
66static int _eina_simple_xml_log_dom = -1;
67
68static const char EINA_MAGIC_SIMPLE_XML_TAG_STR[] = "Eina Simple XML Tag";
69static const char EINA_MAGIC_SIMPLE_XML_DATA_STR[] = "Eina Simple XML Data";
70static const char EINA_MAGIC_SIMPLE_XML_ATTRIBUTE_STR[] = "Eina Simple XML Attribute";
71
72#define EINA_MAGIC_CHECK_TAG(d, ...) \
73 do { \
74 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_TAG)) \
75 { \
76 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_TAG); \
77 return __VA_ARGS__; \
78 } \
79 } while(0)
80
81#define EINA_MAGIC_CHECK_DATA(d, ...) \
82 do { \
83 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_DATA)) \
84 { \
85 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_DATA); \
86 return __VA_ARGS__; \
87 } \
88 } while(0)
89
90#define EINA_MAGIC_CHECK_ATTRIBUTE(d, ...) \
91 do { \
92 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE)) \
93 { \
94 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE); \
95 return __VA_ARGS__; \
96 } \
97 } while(0)
98
99
100#ifndef EINA_LOG_COLOR_DEFAULT
101#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
102#endif
103
104#ifdef ERR
105#undef ERR
106#endif
107#define ERR(...) EINA_LOG_DOM_ERR(_eina_simple_xml_log_dom, __VA_ARGS__)
108
109#ifdef WRN
110#undef WRN
111#endif
112#define WRN(...) EINA_LOG_DOM_WARN(_eina_simple_xml_log_dom, __VA_ARGS__)
113
114#ifdef DBG
115#undef DBG
116#endif
117#define DBG(...) EINA_LOG_DOM_DBG(_eina_simple_xml_log_dom, __VA_ARGS__)
118
119
120static inline const char *
121_eina_simple_xml_whitespace_find(const char *itr, const char *itr_end)
122{
123 for (; itr < itr_end; itr++)
124 if (isspace(*itr)) break;
125 return itr;
126}
127
128static inline const char *
129_eina_simple_xml_whitespace_skip(const char *itr, const char *itr_end)
130{
131 for (; itr < itr_end; itr++)
132 if (!isspace(*itr)) break;
133 return itr;
134}
135
136static inline const char *
137_eina_simple_xml_whitespace_unskip(const char *itr, const char *itr_start)
138{
139 for (itr--; itr > itr_start; itr--)
140 if (!isspace(*itr)) break;
141 return itr + 1;
142}
143
144static inline const char *
145_eina_simple_xml_tag_start_find(const char *itr, const char *itr_end)
146{
147 return memchr(itr, '<', itr_end - itr);
148}
149
150static inline const char *
151_eina_simple_xml_tag_end_find(const char *itr, const char *itr_end)
152{
153 for (; itr < itr_end; itr++)
154 if ((*itr == '>') || (*itr == '<')) /* consider < also ends a tag */
155 return itr;
156 return NULL;
157}
158
159/**
160 * @endcond
161 */
162
163/*============================================================================*
164 * Global *
165 *============================================================================*/
166
167
168/**
169 * @internal
170 * @brief Initialize the simple xml parser module.
171 *
172 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
173 *
174 * This function sets up the simple xml parser module of Eina. It is called by
175 * eina_init().
176 *
177 * @see eina_init()
178 */
179Eina_Bool
180eina_simple_xml_init(void)
181{
182 const char *choice, *tmp;
183
184 _eina_simple_xml_log_dom = eina_log_domain_register("eina_simple_xml",
185 EINA_LOG_COLOR_DEFAULT);
186 if (_eina_simple_xml_log_dom < 0)
187 {
188 EINA_LOG_ERR("Could not register log domain: eina_simple_xml");
189 return EINA_FALSE;
190 }
191
192#ifdef EINA_DEFAULT_MEMPOOL
193 choice = "pass_through";
194#else
195 choice = "chained_mempool";
196#endif
197 tmp = getenv("EINA_MEMPOOL");
198 if (tmp && tmp[0])
199 choice = tmp;
200
201 _eina_simple_xml_tag_mp = eina_mempool_add
202 (choice, "simple_xml_tag", NULL,
203 sizeof(Eina_Simple_XML_Node_Tag), 320);
204 if (!_eina_simple_xml_tag_mp)
205 {
206 ERR("Mempool for simple_xml_tag cannot be allocated in init.");
207 goto on_init_fail;
208 }
209
210 _eina_simple_xml_attribute_mp = eina_mempool_add
211 (choice, "simple_xml_attribute", NULL,
212 sizeof(Eina_Simple_XML_Attribute), 80);
213 if (!_eina_simple_xml_attribute_mp)
214 {
215 ERR("Mempool for simple_xml_attribute cannot be allocated in init.");
216 eina_mempool_del(_eina_simple_xml_tag_mp);
217 goto on_init_fail;
218 }
219
220#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
221 EMS(EINA_MAGIC_SIMPLE_XML_TAG);
222 EMS(EINA_MAGIC_SIMPLE_XML_DATA);
223 EMS(EINA_MAGIC_SIMPLE_XML_ATTRIBUTE);
224#undef EMS
225
226 return EINA_TRUE;
227
228on_init_fail:
229 eina_log_domain_unregister(_eina_simple_xml_log_dom);
230 _eina_simple_xml_log_dom = -1;
231 return EINA_FALSE;
232}
233
234/**
235 * @internal
236 * @brief Shut down the simple xml parser module.
237 *
238 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
239 *
240 * This function shuts down the simple xml parser module set
241 * up by eina_simple_xml_init(). It is called by
242 * eina_shutdown().
243 *
244 * @see eina_shutdown()
245 */
246Eina_Bool
247eina_simple_xml_shutdown(void)
248{
249 eina_mempool_del(_eina_simple_xml_attribute_mp);
250 eina_mempool_del(_eina_simple_xml_tag_mp);
251
252 eina_log_domain_unregister(_eina_simple_xml_log_dom);
253 _eina_simple_xml_log_dom = -1;
254 return EINA_TRUE;
255}
256
257
258/*============================================================================*
259 * API *
260 *============================================================================*/
261
262
263EAPI Eina_Bool
264eina_simple_xml_parse(const char *buf, unsigned buflen, Eina_Bool strip, Eina_Simple_XML_Cb func, const void *data)
265{
266 const char *itr = buf, *itr_end = buf + buflen;
267
268 if (!buf) return EINA_FALSE;
269 if (!func) return EINA_FALSE;
270
271#define CB(type, start, end) \
272 do \
273 { \
274 size_t _sz = end - start; \
275 Eina_Bool _ret; \
276 _ret = func((void*)data, type, start, start - buf, _sz); \
277 if (!_ret) return EINA_FALSE; \
278 } \
279 while (0)
280
281 while (itr < itr_end)
282 {
283 if (itr[0] == '<')
284 {
285 if (itr + 1 >= itr_end)
286 {
287 CB(EINA_SIMPLE_XML_ERROR, itr, itr_end);
288 return EINA_FALSE;
289 }
290 else
291 {
292 Eina_Simple_XML_Type type;
293 size_t toff;
294 const char *p;
295
296 if (itr[1] == '/')
297 {
298 type = EINA_SIMPLE_XML_CLOSE;
299 toff = 1;
300 }
301 else if (itr[1] == '?')
302 {
303 type = EINA_SIMPLE_XML_PROCESSING;
304 toff = 1;
305 }
306 else if (itr[1] == '!')
307 {
308 if ((itr + sizeof("<!DOCTYPE>") - 1 < itr_end) &&
309 (!memcmp(itr + 2, "DOCTYPE",
310 sizeof("DOCTYPE") - 1)) &&
311 ((itr[2 + sizeof("DOCTYPE") - 1] == '>') ||
312 (isspace(itr[2 + sizeof("DOCTYPE") - 1]))))
313 {
314 type = EINA_SIMPLE_XML_DOCTYPE;
315 toff = sizeof("!DOCTYPE") - 1;
316 }
317 else if ((itr + sizeof("<!---->") - 1 < itr_end) &&
318 (!memcmp(itr + 2, "--", sizeof("--") - 1)))
319 {
320 type = EINA_SIMPLE_XML_COMMENT;
321 toff = sizeof("!--") - 1;
322 }
323 else if ((itr + sizeof("<![CDATA[]]>") - 1 < itr_end) &&
324 (!memcmp(itr + 2, "[CDATA[",
325 sizeof("[CDATA[") - 1)))
326 {
327 type = EINA_SIMPLE_XML_CDATA;
328 toff = sizeof("![CDATA[") - 1;
329 }
330 else
331 {
332 type = EINA_SIMPLE_XML_OPEN;
333 toff = 0;
334 }
335 }
336 else
337 {
338 type = EINA_SIMPLE_XML_OPEN;
339 toff = 0;
340 }
341
342 p = _eina_simple_xml_tag_end_find(itr + 1 + toff, itr_end);
343 if (p)
344 {
345 if (type == EINA_SIMPLE_XML_CDATA)
346 {
347 /* must end with ]]> */
348 while ((p) && (memcmp(p - 2, "]]>", 3)))
349 p = _eina_simple_xml_tag_end_find(p + 1, itr_end);
350 }
351
352 if ((p) && (*p == '<'))
353 {
354 type = EINA_SIMPLE_XML_ERROR;
355 toff = 0;
356 }
357 }
358
359 if (p)
360 {
361 const char *start, *end;
362
363 start = itr + 1 + toff;
364 end = p;
365
366 switch (type)
367 {
368 case EINA_SIMPLE_XML_OPEN:
369 if (p[-1] == '/')
370 {
371 type = EINA_SIMPLE_XML_OPEN_EMPTY;
372 end--;
373 }
374 break;
375 case EINA_SIMPLE_XML_CDATA:
376 if (!memcmp(p - 2, "]]", 2)) end -= 2;
377 break;
378 case EINA_SIMPLE_XML_PROCESSING:
379 if (p[-1] == '?') end--;
380 break;
381 case EINA_SIMPLE_XML_COMMENT:
382 if (!memcmp(p - 2, "--", 2)) end -= 2;
383 break;
384 case EINA_SIMPLE_XML_OPEN_EMPTY:
385 case EINA_SIMPLE_XML_CLOSE:
386 case EINA_SIMPLE_XML_DATA:
387 case EINA_SIMPLE_XML_ERROR:
388 case EINA_SIMPLE_XML_DOCTYPE:
389 case EINA_SIMPLE_XML_IGNORED:
390 break;
391 }
392
393 if ((strip) && (type != EINA_SIMPLE_XML_ERROR))
394 {
395 start = _eina_simple_xml_whitespace_skip
396 (start, end);
397 end = _eina_simple_xml_whitespace_unskip
398 (end, start + 1);
399 }
400
401 CB(type, start, end);
402
403 if (type != EINA_SIMPLE_XML_ERROR)
404 itr = p + 1;
405 else
406 itr = p;
407 }
408 else
409 {
410 CB(EINA_SIMPLE_XML_ERROR, itr, itr_end);
411 return EINA_FALSE;
412 }
413 }
414 }
415 else
416 {
417 const char *p, *end;
418
419 if (strip)
420 {
421 p = _eina_simple_xml_whitespace_skip(itr, itr_end);
422 if (p)
423 {
424 CB(EINA_SIMPLE_XML_IGNORED, itr, p);
425 itr = p;
426 }
427 }
428
429 p = _eina_simple_xml_tag_start_find(itr, itr_end);
430 if (!p) p = itr_end;
431
432 end = p;
433 if (strip)
434 end = _eina_simple_xml_whitespace_unskip(end, itr);
435
436 if (itr != end)
437 CB(EINA_SIMPLE_XML_DATA, itr, end);
438
439 if ((strip) && (end < p))
440 CB(EINA_SIMPLE_XML_IGNORED, end, p);
441
442 itr = p;
443 }
444 }
445
446#undef CB
447
448 return EINA_TRUE;
449}
450
451EAPI const char *
452eina_simple_xml_tag_attributes_find(const char *buf, unsigned buflen)
453{
454 const char *itr = buf, *itr_end = buf + buflen;
455
456 for (; itr < itr_end; itr++)
457 {
458 if (!isspace(*itr))
459 {
460 /* user skip tagname and already gave it the attributes */
461 if (*itr == '=')
462 return buf;
463 }
464 else
465 {
466 itr = _eina_simple_xml_whitespace_skip(itr + 1, itr_end);
467 if (itr == itr_end)
468 return NULL;
469 return itr;
470 }
471 }
472
473 return NULL;
474}
475
476EAPI Eina_Bool
477eina_simple_xml_attributes_parse(const char *buf, unsigned buflen, Eina_Simple_XML_Attribute_Cb func, const void *data)
478{
479 const char *itr = buf, *itr_end = buf + buflen;
480 char *tmpbuf = alloca(buflen + 1);
481
482 if (!buf) return EINA_FALSE;
483 if (!func) return EINA_FALSE;
484
485 while (itr < itr_end)
486 {
487 const char *p = _eina_simple_xml_whitespace_skip(itr, itr_end);
488 const char *key, *key_end, *value, *value_end;
489 char *tval;
490
491 if (p == itr_end) return EINA_TRUE;
492
493 key = p;
494 for (key_end = key; key_end < itr_end; key_end++)
495 if ((*key_end == '=') || (isspace(*key_end))) break;
496 if (key_end == itr_end) return EINA_FALSE;
497 if (key_end == key) continue;
498
499 if (*key_end == '=') value = key_end + 1;
500 else
501 {
502 value = memchr(key_end, '=', itr_end - key_end);
503 if (!value) return EINA_FALSE;
504 value++;
505 }
506 for (; value < itr_end; value++)
507 if (!isspace(*value)) break;
508 if (value == itr_end) return EINA_FALSE;
509
510 if ((*value == '"') || (*value == '\''))
511 {
512 value_end = memchr(value + 1, *value, itr_end - value);
513 if (!value_end) return EINA_FALSE;
514 value++;
515 }
516 else
517 {
518 value_end = _eina_simple_xml_whitespace_find(value, itr_end);
519 }
520
521 memcpy(tmpbuf, key, key_end - key);
522 tmpbuf[key_end - key] = '\0';
523
524 tval = tmpbuf + (key_end - key) + 1;
525 memcpy(tval, value, value_end - value);
526 tval[value_end - value] = '\0';
527
528 if (!func((void*)data, tmpbuf, tval))
529 return EINA_FALSE;
530
531 itr = value_end + 1;
532 }
533 return EINA_TRUE;
534}
535
536/* Node loader *************************************************************/
537
538EAPI Eina_Simple_XML_Attribute *
539eina_simple_xml_attribute_new(Eina_Simple_XML_Node_Tag *parent, const char *key, const char *value)
540{
541 Eina_Simple_XML_Attribute *attr;
542
543 if (!key) return NULL;
544
545 attr = eina_mempool_malloc(_eina_simple_xml_attribute_mp, sizeof(*attr));
546 if (!attr)
547 {
548 ERR("could not allocate memory for attribute from mempool");
549 return NULL;
550 }
551
552 EINA_MAGIC_SET(attr, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE);
553 attr->parent = parent;
554 attr->key = eina_stringshare_add(key);
555 attr->value = eina_stringshare_add(value ? value : "");
556
557 if (parent)
558 parent->attributes = eina_inlist_append
559 (parent->attributes, EINA_INLIST_GET(attr));
560
561 return attr;
562}
563
564EAPI void
565eina_simple_xml_attribute_free(Eina_Simple_XML_Attribute *attr)
566{
567 EINA_MAGIC_CHECK_ATTRIBUTE(attr);
568
569 if (attr->parent)
570 attr->parent->attributes = eina_inlist_remove
571 (attr->parent->attributes, EINA_INLIST_GET(attr));
572
573 eina_stringshare_del(attr->key);
574 eina_stringshare_del(attr->value);
575 EINA_MAGIC_SET(attr, EINA_MAGIC_NONE);
576 eina_mempool_free(_eina_simple_xml_attribute_mp, attr);
577}
578
579static void
580_eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node)
581{
582 if (node->base.parent)
583 node->base.parent->children = eina_inlist_remove
584 (node->base.parent->children, EINA_INLIST_GET(&node->base));
585
586 EINA_MAGIC_SET(&node->base, EINA_MAGIC_NONE);
587 free(node);
588}
589
590EAPI Eina_Simple_XML_Node_Tag *
591eina_simple_xml_node_tag_new(Eina_Simple_XML_Node_Tag *parent, const char *name)
592{
593 Eina_Simple_XML_Node_Tag *n;
594
595 if (!name) return NULL;
596
597 n = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*n));
598 if (!n)
599 {
600 ERR("could not allocate memory for node from mempool");
601 return NULL;
602 }
603
604 memset(n, 0, sizeof(*n));
605
606 EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_TAG);
607
608 n->base.type = EINA_SIMPLE_XML_NODE_TAG;
609 n->base.parent = parent;
610 n->name = eina_stringshare_add(name);
611
612 if (parent)
613 parent->children = eina_inlist_append
614 (parent->children, EINA_INLIST_GET(&n->base));
615
616 return n;
617}
618
619void
620_eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag)
621{
622 while (tag->children)
623 {
624 Eina_Simple_XML_Node *n = EINA_INLIST_CONTAINER_GET
625 (tag->children, Eina_Simple_XML_Node);
626 if (n->type == EINA_SIMPLE_XML_NODE_TAG)
627 _eina_simple_xml_node_tag_free((Eina_Simple_XML_Node_Tag *)n);
628 else
629 _eina_simple_xml_node_data_free((Eina_Simple_XML_Node_Data *)n);
630 }
631
632 while (tag->attributes)
633 {
634 Eina_Simple_XML_Attribute *a = EINA_INLIST_CONTAINER_GET
635 (tag->attributes, Eina_Simple_XML_Attribute);
636 eina_simple_xml_attribute_free(a);
637 }
638
639 if (tag->base.parent)
640 tag->base.parent->children = eina_inlist_remove
641 (tag->base.parent->children, EINA_INLIST_GET(&tag->base));
642
643 eina_stringshare_del(tag->name);
644 EINA_MAGIC_SET(&tag->base, EINA_MAGIC_NONE);
645 eina_mempool_free(_eina_simple_xml_tag_mp, tag);
646}
647
648EAPI void
649eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag)
650{
651 EINA_MAGIC_CHECK_TAG(&tag->base);
652 if (tag->base.type != EINA_SIMPLE_XML_NODE_TAG)
653 {
654 ERR("expected tag node!");
655 return;
656 }
657 _eina_simple_xml_node_tag_free(tag);
658}
659
660static Eina_Simple_XML_Node_Data *
661_eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, Eina_Simple_XML_Node_Type type, const char *content, unsigned length)
662{
663 Eina_Simple_XML_Node_Data *n = malloc(sizeof(*n) + length + 1);
664
665 if (!content) return NULL;
666
667 if (!n)
668 {
669 ERR("could not allocate memory for node");
670 return NULL;
671 }
672
673 EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_DATA);
674 n->base.type = type;
675 n->base.parent = parent;
676
677 n->length = length;
678 memcpy(n->data, content, length);
679 n->data[length] = '\0';
680
681 if (parent)
682 parent->children = eina_inlist_append
683 (parent->children, EINA_INLIST_GET(&n->base));
684
685 return n;
686}
687
688EAPI Eina_Simple_XML_Node_Data *
689eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
690{
691 return _eina_simple_xml_node_data_new
692 (parent, EINA_SIMPLE_XML_NODE_DATA, contents, length);
693}
694
695EAPI void
696eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node)
697{
698 EINA_MAGIC_CHECK_DATA(&node->base);
699 if (node->base.type != EINA_SIMPLE_XML_NODE_DATA)
700 {
701 ERR("expected node of type: data!");
702 return;
703 }
704 _eina_simple_xml_node_data_free(node);
705}
706
707EAPI Eina_Simple_XML_Node_CData *
708eina_simple_xml_node_cdata_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
709{
710 return _eina_simple_xml_node_data_new
711 (parent, EINA_SIMPLE_XML_NODE_CDATA, contents, length);
712}
713
714EAPI void
715eina_simple_xml_node_cdata_free(Eina_Simple_XML_Node_Data *node)
716{
717 EINA_MAGIC_CHECK_DATA(&node->base);
718 if (node->base.type != EINA_SIMPLE_XML_NODE_CDATA)
719 {
720 ERR("expected node of type: cdata!");
721 return;
722 }
723 _eina_simple_xml_node_data_free(node);
724}
725
726EAPI Eina_Simple_XML_Node_Processing *
727eina_simple_xml_node_processing_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
728{
729 return _eina_simple_xml_node_data_new
730 (parent, EINA_SIMPLE_XML_NODE_PROCESSING, contents, length);
731}
732
733EAPI void
734eina_simple_xml_node_processing_free(Eina_Simple_XML_Node_Data *node)
735{
736 EINA_MAGIC_CHECK_DATA(&node->base);
737 if (node->base.type != EINA_SIMPLE_XML_NODE_PROCESSING)
738 {
739 ERR("expected node of type: processing!");
740 return;
741 }
742 _eina_simple_xml_node_data_free(node);
743}
744
745EAPI Eina_Simple_XML_Node_Doctype *
746eina_simple_xml_node_doctype_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
747{
748 return _eina_simple_xml_node_data_new
749 (parent, EINA_SIMPLE_XML_NODE_DOCTYPE, contents, length);
750}
751
752EAPI void
753eina_simple_xml_node_doctype_free(Eina_Simple_XML_Node_Data *node)
754{
755 EINA_MAGIC_CHECK_DATA(&node->base);
756 if (node->base.type != EINA_SIMPLE_XML_NODE_DOCTYPE)
757 {
758 ERR("expected node of type: doctype!");
759 return;
760 }
761 _eina_simple_xml_node_data_free(node);
762}
763
764EAPI Eina_Simple_XML_Node_Comment *
765eina_simple_xml_node_comment_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
766{
767 return _eina_simple_xml_node_data_new
768 (parent, EINA_SIMPLE_XML_NODE_COMMENT, contents, length);
769}
770
771EAPI void
772eina_simple_xml_node_comment_free(Eina_Simple_XML_Node_Data *node)
773{
774 EINA_MAGIC_CHECK_DATA(&node->base);
775 if (node->base.type != EINA_SIMPLE_XML_NODE_COMMENT)
776 {
777 ERR("expected node of type: comment!");
778 return;
779 }
780 _eina_simple_xml_node_data_free(node);
781}
782
783struct eina_simple_xml_node_load_ctxt
784{
785 Eina_Simple_XML_Node_Root *root;
786 Eina_Simple_XML_Node_Tag *current;
787};
788
789static Eina_Bool
790_eina_simple_xml_attrs_parse(void *data, const char *key, const char *value)
791{
792 Eina_Simple_XML_Node_Tag *n = data;
793 Eina_Simple_XML_Attribute *attr;
794
795 attr = eina_simple_xml_attribute_new(n, key, value);
796 return !!attr;
797}
798
799static Eina_Bool
800_eina_simple_xml_node_parse(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset, unsigned length)
801{
802 struct eina_simple_xml_node_load_ctxt *ctx = data;
803
804 switch (type)
805 {
806 case EINA_SIMPLE_XML_OPEN:
807 case EINA_SIMPLE_XML_OPEN_EMPTY:
808 {
809 Eina_Simple_XML_Node_Tag *n;
810 const char *name, *name_end, *attrs;
811
812 attrs = eina_simple_xml_tag_attributes_find(content, length);
813 if (!attrs)
814 name_end = content + length;
815 else
816 name_end = attrs;
817
818 name_end = _eina_simple_xml_whitespace_unskip(name_end, content);
819
820 name = eina_stringshare_add_length(content, name_end - content);
821 n = eina_simple_xml_node_tag_new(ctx->current, name);
822 eina_stringshare_del(name);
823 if (!n) return EINA_FALSE;
824
825 if (attrs)
826 eina_simple_xml_attributes_parse
827 (attrs, length - (attrs - content),
828 _eina_simple_xml_attrs_parse, n);
829
830 if (type == EINA_SIMPLE_XML_OPEN)
831 ctx->current = n;
832 }
833 break;
834
835 case EINA_SIMPLE_XML_CLOSE:
836 if (ctx->current->base.parent)
837 {
838 const char *end = _eina_simple_xml_whitespace_unskip
839 (content + length, content);
840 int len;
841 len = end - content;
842 if ((len == 0) /* </> closes the tag for us. */ ||
843 ((eina_stringshare_strlen(ctx->current->name) == len) &&
844 (memcmp(ctx->current->name, content, len) == 0)))
845 ctx->current = ctx->current->base.parent;
846 else
847 WRN("closed incorrect tag: '%.*s', '%s' was expected!",
848 len, content, ctx->current->name);
849 }
850 else
851 WRN("closed tag '%.*s' but already at document root!",
852 length, content);
853 break;
854
855 case EINA_SIMPLE_XML_DATA:
856 return !!eina_simple_xml_node_data_new
857 (ctx->current, content, length);
858 case EINA_SIMPLE_XML_CDATA:
859 return !!eina_simple_xml_node_cdata_new
860 (ctx->current, content, length);
861 case EINA_SIMPLE_XML_PROCESSING:
862 return !!eina_simple_xml_node_processing_new
863 (ctx->current, content, length);
864 case EINA_SIMPLE_XML_DOCTYPE:
865 return !!eina_simple_xml_node_doctype_new
866 (ctx->current, content, length);
867 case EINA_SIMPLE_XML_COMMENT:
868 return !!eina_simple_xml_node_comment_new
869 (ctx->current, content, length);
870
871 case EINA_SIMPLE_XML_ERROR:
872 ERR("parser error at offset %u-%u: %.*s",
873 offset, length, length, content);
874 break;
875 case EINA_SIMPLE_XML_IGNORED:
876 DBG("ignored contents at offset %u-%u: %.*s",
877 offset, length, length, content);
878 break;
879 }
880
881 return EINA_TRUE;
882}
883
884EAPI Eina_Simple_XML_Node_Root *
885eina_simple_xml_node_load(const char *buf, unsigned buflen, Eina_Bool strip)
886{
887 Eina_Simple_XML_Node_Root *root;
888 struct eina_simple_xml_node_load_ctxt ctx;
889
890 if (!buf) return NULL;
891
892 root = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*root));
893 if (!root) return NULL;
894
895 memset(root, 0, sizeof(*root));
896 EINA_MAGIC_SET(&root->base, EINA_MAGIC_SIMPLE_XML_TAG);
897 root->base.type = EINA_SIMPLE_XML_NODE_ROOT;
898
899 ctx.root = root;
900 ctx.current = root;
901 eina_simple_xml_parse(buf, buflen, strip, _eina_simple_xml_node_parse, &ctx);
902
903 return root;
904}
905
906EAPI void
907eina_simple_xml_node_root_free(Eina_Simple_XML_Node_Root *root)
908{
909 if (!root) return;
910 EINA_MAGIC_CHECK_TAG(&root->base);
911 if (root->base.type != EINA_SIMPLE_XML_NODE_ROOT)
912 {
913 ERR("expected root node!");
914 return;
915 }
916 _eina_simple_xml_node_tag_free(root);
917}
918
919static inline void
920_eina_simple_xml_node_dump_indent(Eina_Strbuf *buf, const char *indent, unsigned level)
921{
922 unsigned i, indent_len = strlen(indent);
923 for (i = 0; i < level; i++)
924 eina_strbuf_append_length(buf, indent, indent_len);
925}
926
927static void
928_eina_simple_xml_node_tag_attributes_append(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag)
929{
930 Eina_Simple_XML_Attribute *a;
931
932 EINA_INLIST_FOREACH(tag->attributes, a)
933 eina_strbuf_append_printf(buf, " %s=\"%s\"", a->key, a->value);
934}
935
936static void _eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level);
937
938static void
939_eina_simple_xml_node_children_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag, const char *indent, unsigned level)
940{
941 Eina_Simple_XML_Node *node;
942
943 EINA_INLIST_FOREACH(tag->children, node)
944 _eina_simple_xml_node_dump(buf, node, indent, level);
945}
946
947static void
948_eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level)
949{
950 switch (node->type)
951 {
952 case EINA_SIMPLE_XML_NODE_ROOT:
953 _eina_simple_xml_node_children_dump
954 (buf, (Eina_Simple_XML_Node_Tag *)node, indent, level);
955 break;
956
957 case EINA_SIMPLE_XML_NODE_TAG:
958 {
959 Eina_Simple_XML_Node_Tag *n = (Eina_Simple_XML_Node_Tag *)node;
960
961 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
962
963 eina_strbuf_append_char(buf, '<');
964 eina_strbuf_append_length
965 (buf, n->name, eina_stringshare_strlen(n->name));
966
967 if (n->attributes)
968 _eina_simple_xml_node_tag_attributes_append(buf, n);
969
970 if (n->children)
971 eina_strbuf_append_char(buf, '>');
972 else
973 eina_strbuf_append_length(buf, "/>", sizeof("/>") - 1);
974
975 if (indent) eina_strbuf_append_char(buf, '\n');
976
977 if (n->children)
978 {
979 _eina_simple_xml_node_children_dump(buf, n, indent, level + 1);
980
981 if (indent)
982 _eina_simple_xml_node_dump_indent(buf, indent, level);
983
984 eina_strbuf_append_length(buf, "</", sizeof("</") - 1);
985 eina_strbuf_append_length
986 (buf, n->name, eina_stringshare_strlen(n->name));
987 eina_strbuf_append_char(buf, '>');
988
989 if (indent) eina_strbuf_append_char(buf, '\n');
990 }
991 }
992 break;
993 case EINA_SIMPLE_XML_NODE_DATA:
994 {
995 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
996
997 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
998 eina_strbuf_append_length(buf, n->data, n->length);
999 if (indent) eina_strbuf_append_char(buf, '\n');
1000 }
1001 break;
1002
1003 case EINA_SIMPLE_XML_NODE_CDATA:
1004 {
1005 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1006
1007 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1008 eina_strbuf_append_length(buf, "<![CDATA[", sizeof("<![CDATA[") - 1);
1009 eina_strbuf_append_length(buf, n->data, n->length);
1010 eina_strbuf_append_length(buf, "]]>", sizeof("]]>") - 1);
1011 if (indent) eina_strbuf_append_char(buf, '\n');
1012 }
1013 break;
1014
1015 case EINA_SIMPLE_XML_NODE_PROCESSING:
1016 {
1017 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1018
1019 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1020 eina_strbuf_append_length(buf, "<?", sizeof("<?") - 1);
1021 eina_strbuf_append_length(buf, n->data, n->length);
1022 eina_strbuf_append_length(buf, " ?>", sizeof(" ?>") - 1);
1023 if (indent) eina_strbuf_append_char(buf, '\n');
1024 }
1025 break;
1026
1027 case EINA_SIMPLE_XML_NODE_DOCTYPE:
1028 {
1029 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1030
1031 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1032 eina_strbuf_append_length
1033 (buf, "<!DOCTYPE ", sizeof("<!DOCTYPE ") - 1);
1034 eina_strbuf_append_length(buf, n->data, n->length);
1035 eina_strbuf_append_char(buf, '>');
1036 if (indent) eina_strbuf_append_char(buf, '\n');
1037 }
1038 break;
1039
1040 case EINA_SIMPLE_XML_NODE_COMMENT:
1041 {
1042 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1043
1044 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1045 eina_strbuf_append_length(buf, "<!-- ", sizeof("<!-- ") - 1);
1046 eina_strbuf_append_length(buf, n->data, n->length);
1047 eina_strbuf_append_length(buf, " -->", sizeof(" -->") - 1);
1048 if (indent) eina_strbuf_append_char(buf, '\n');
1049 }
1050 break;
1051 }
1052}
1053
1054EAPI char *
1055eina_simple_xml_node_dump(Eina_Simple_XML_Node *node, const char *indent)
1056{
1057 Eina_Strbuf *buf;
1058 char *ret;
1059
1060 if (!node) return NULL;
1061
1062 buf = eina_strbuf_new();
1063 if (!buf) return NULL;
1064
1065 _eina_simple_xml_node_dump(buf, node, indent, 0);
1066
1067 ret = eina_strbuf_string_steal(buf);
1068 eina_strbuf_free(buf);
1069 return ret;
1070}
diff --git a/libraries/eina/src/lib/eina_str.c b/libraries/eina/src/lib/eina_str.c
new file mode 100644
index 0000000..8d27c65
--- /dev/null
+++ b/libraries/eina/src/lib/eina_str.c
@@ -0,0 +1,462 @@
1/* Leave the OpenBSD version below so we can track upstream fixes */
2/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
3
4/*
5 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20
21#ifdef HAVE_CONFIG_H
22# include "config.h"
23#endif
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <limits.h>
29#include <ctype.h>
30
31#ifdef HAVE_ICONV
32# include <errno.h>
33# include <iconv.h>
34#endif
35
36#include "eina_private.h"
37#include "eina_str.h"
38
39/*============================================================================*
40* Local *
41*============================================================================*/
42
43/**
44 * @cond LOCAL
45 */
46
47/*
48 * Internal helper function used by eina_str_has_suffix() and
49 * eina_str_has_extension()
50 */
51static inline Eina_Bool
52eina_str_has_suffix_helper(const char *str,
53 const char *suffix,
54 int (*cmp)(const char *, const char *))
55{
56 size_t str_len;
57 size_t suffix_len;
58
59 if ((!str) || (!suffix)) return EINA_FALSE;
60 str_len = strlen(str);
61 suffix_len = eina_strlen_bounded(suffix, str_len);
62 if (suffix_len == (size_t)-1)
63 return EINA_FALSE;
64
65 return cmp(str + str_len - suffix_len, suffix) == 0;
66}
67
68static inline char **
69eina_str_split_full_helper(const char *str,
70 const char *delim,
71 int max_tokens,
72 unsigned int *elements)
73{
74 char *s, **str_array;
75 const char *src;
76 size_t len, dlen;
77 unsigned int tokens;
78
79 dlen = strlen(delim);
80 if (dlen == 0)
81 {
82 if (elements)
83 *elements = 0;
84
85 return NULL;
86 }
87
88 tokens = 0;
89 src = str;
90 /* count tokens and check strlen(str) */
91 while (*src != '\0')
92 {
93 const char *d = delim, *d_end = d + dlen;
94 const char *tmp = src;
95 for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
96 {
97 if (EINA_LIKELY(*d != *tmp))
98 break;
99 }
100 if (EINA_UNLIKELY(d == d_end))
101 {
102 src = tmp;
103 tokens++;
104 }
105 else
106 src++;
107 }
108 len = src - str;
109
110 if ((max_tokens > 0) && (tokens > (unsigned int)max_tokens))
111 tokens = max_tokens;
112
113 str_array = malloc(sizeof(char *) * (tokens + 2));
114 if (!str_array)
115 {
116 if (elements)
117 *elements = 0;
118
119 return NULL;
120 }
121
122 s = malloc(len + 1);
123 if (!s)
124 {
125 free(str_array);
126 if (elements)
127 *elements = 0;
128
129 return NULL;
130 }
131
132 /* copy tokens and string */
133 tokens = 0;
134 str_array[0] = s;
135 src = str;
136 while (*src != '\0')
137 {
138 const char *d = delim, *d_end = d + dlen;
139 const char *tmp = src;
140 for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
141 {
142 if (EINA_LIKELY(*d != *tmp))
143 break;
144 }
145 if (EINA_UNLIKELY(d == d_end))
146 {
147 src = tmp;
148 *s = '\0';
149 s += dlen;
150 tokens++;
151 str_array[tokens] = s;
152 }
153 else
154 {
155 *s = *src;
156 s++;
157 src++;
158 }
159 }
160 *s = '\0';
161 str_array[tokens + 1] = NULL;
162 if (elements)
163 *elements = (tokens + 1);
164
165 return str_array;
166}
167
168/**
169 * @endcond
170 */
171
172/*============================================================================*
173* Global *
174*============================================================================*/
175
176/*============================================================================*
177* API *
178*============================================================================*/
179
180EAPI size_t
181eina_strlcpy(char *dst, const char *src, size_t siz)
182{
183#ifdef HAVE_STRLCPY
184 return strlcpy(dst, src, siz);
185#else
186 char *d = dst;
187 const char *s = src;
188 size_t n = siz;
189
190 /* Copy as many bytes as will fit */
191 if (n != 0)
192 while (--n != 0)
193 {
194 if ((*d++ = *s++) == '\0')
195 break;
196 }
197
198 /* Not enough room in dst, add NUL and traverse rest of src */
199 if (n == 0)
200 {
201 if (siz != 0)
202 *d = '\0'; /* NUL-terminate dst */
203
204 while (*s++)
205 ;
206 }
207
208 return(s - src - 1); /* count does not include NUL */
209#endif
210}
211
212EAPI size_t
213eina_strlcat(char *dst, const char *src, size_t siz)
214{
215 char *d = dst;
216 const char *s = src;
217 size_t n = siz;
218 size_t dlen;
219
220 /* Find the end of dst and adjust bytes left but don't go past end */
221 while (n-- != 0 && *d != '\0')
222 d++;
223 dlen = d - dst;
224 n = siz - dlen;
225
226 if (n == 0)
227 return(dlen + strlen(s));
228
229 while (*s != '\0') {
230 if (n != 1)
231 {
232 *d++ = *s;
233 n--;
234 }
235
236 s++;
237 }
238 *d = '\0';
239
240 return(dlen + (s - src)); /* count does not include NUL */
241}
242
243EAPI Eina_Bool
244eina_str_has_prefix(const char *str, const char *prefix)
245{
246 size_t str_len;
247 size_t prefix_len;
248
249 str_len = strlen(str);
250 prefix_len = eina_strlen_bounded(prefix, str_len);
251 if (prefix_len == (size_t)-1)
252 return EINA_FALSE;
253
254 return (strncmp(str, prefix, prefix_len) == 0);
255}
256
257EAPI Eina_Bool
258eina_str_has_suffix(const char *str, const char *suffix)
259{
260 return eina_str_has_suffix_helper(str, suffix, strcmp);
261}
262
263EAPI Eina_Bool
264eina_str_has_extension(const char *str, const char *ext)
265{
266 return eina_str_has_suffix_helper(str, ext, strcasecmp);
267}
268
269EAPI char **
270eina_str_split_full(const char *str,
271 const char *delim,
272 int max_tokens,
273 unsigned int *elements)
274{
275 return eina_str_split_full_helper(str, delim, max_tokens, elements);
276}
277
278
279EAPI char **
280eina_str_split(const char *str, const char *delim, int max_tokens)
281{
282 return eina_str_split_full_helper(str, delim, max_tokens, NULL);
283}
284
285EAPI size_t
286eina_str_join_len(char *dst,
287 size_t size,
288 char sep,
289 const char *a,
290 size_t a_len,
291 const char *b,
292 size_t b_len)
293{
294 size_t ret = a_len + b_len + 1;
295 size_t off;
296
297 if (size < 1)
298 return ret;
299
300 if (size <= a_len)
301 {
302 memcpy(dst, a, size - 1);
303 dst[size - 1] = '\0';
304 return ret;
305 }
306
307 memcpy(dst, a, a_len);
308 off = a_len;
309
310 if (size <= off + 1)
311 {
312 dst[size - 1] = '\0';
313 return ret;
314 }
315
316 dst[off] = sep;
317 off++;
318
319 if (size <= off + b_len + 1)
320 {
321 memcpy(dst + off, b, size - off - 1);
322 dst[size - 1] = '\0';
323 return ret;
324 }
325
326 memcpy(dst + off, b, b_len);
327 dst[off + b_len] = '\0';
328 return ret;
329}
330
331#ifdef HAVE_ICONV
332EAPI char *
333eina_str_convert(const char *enc_from, const char *enc_to, const char *text)
334{
335 iconv_t ic;
336 char *new_txt, *inp, *outp;
337 size_t inb, outb, outlen, tob, outalloc;
338
339 if (!text)
340 return NULL;
341
342 ic = iconv_open(enc_to, enc_from);
343 if (ic == (iconv_t)(-1))
344 return NULL;
345
346 new_txt = malloc(64);
347 inb = strlen(text);
348 outb = 64;
349 inp = (char *)text;
350 outp = new_txt;
351 outalloc = 64;
352 outlen = 0;
353
354 for (;; )
355 {
356 size_t count;
357
358 tob = outb;
359 count = iconv(ic, &inp, &inb, &outp, &outb);
360 outlen += tob - outb;
361 if (count == (size_t)(-1))
362 {
363 if (errno == E2BIG)
364 {
365 new_txt = realloc(new_txt, outalloc + 64);
366 outp = new_txt + outlen;
367 outalloc += 64;
368 outb += 64;
369 }
370 else if (errno == EILSEQ)
371 {
372 if (new_txt)
373 free(new_txt);
374
375 new_txt = NULL;
376 break;
377 }
378 else if (errno == EINVAL)
379 {
380 if (new_txt)
381 free(new_txt);
382
383 new_txt = NULL;
384 break;
385 }
386 else
387 {
388 if (new_txt)
389 free(new_txt);
390
391 new_txt = NULL;
392 break;
393 }
394 }
395
396 if (inb == 0)
397 {
398 if (outalloc == outlen)
399 new_txt = realloc(new_txt, outalloc + 1);
400
401 new_txt[outlen] = 0;
402 break;
403 }
404 }
405 iconv_close(ic);
406 return new_txt;
407}
408#else
409EAPI char *
410eina_str_convert(const char *enc_from __UNUSED__,
411 const char *enc_to __UNUSED__,
412 const char *text __UNUSED__)
413{
414 return NULL;
415}
416#endif
417
418EAPI char *
419eina_str_escape(const char *str)
420{
421 char *s2, *d;
422 const char *s;
423
424 s2 = malloc((strlen(str) * 2) + 1);
425 if (!s2)
426 return NULL;
427
428 for (s = str, d = s2; *s != 0; s++, d++)
429 {
430 if ((*s == ' ') || (*s == '\\') || (*s == '\''))
431 {
432 *d = '\\';
433 d++;
434 }
435
436 *d = *s;
437 }
438 *d = 0;
439 return s2;
440}
441
442EAPI void
443eina_str_tolower(char **str)
444{
445 char *p;
446 if ((!str) || (!(*str)))
447 return;
448
449 for (p = *str; (*p); p++)
450 *p = tolower((unsigned char )(*p));
451}
452
453EAPI void
454eina_str_toupper(char **str)
455{
456 char *p;
457 if ((!str) || (!(*str)))
458 return;
459
460 for (p = *str; (*p); p++)
461 *p = toupper((unsigned char)(*p));
462}
diff --git a/libraries/eina/src/lib/eina_strbuf.c b/libraries/eina/src/lib/eina_strbuf.c
new file mode 100644
index 0000000..74b1eb9
--- /dev/null
+++ b/libraries/eina/src/lib/eina_strbuf.c
@@ -0,0 +1,202 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdio.h>
6#include <string.h>
7#include <ctype.h>
8
9#ifdef HAVE_EVIL
10# include <Evil.h>
11#endif
12
13#include "eina_private.h"
14#include "eina_str.h"
15#include "eina_strbuf_common.h"
16#include "eina_unicode.h"
17
18/*============================================================================*
19 * Local *
20 *============================================================================*/
21
22/**
23 * @cond LOCAL
24 */
25
26#ifdef _STRBUF_DATA_TYPE
27# undef _STRBUF_DATA_TYPE
28#endif
29
30#ifdef _STRBUF_CSIZE
31# undef _STRBUF_CSIZE
32#endif
33
34#ifdef _STRBUF_STRUCT_NAME
35# undef _STRBUF_STRUCT_NAME
36#endif
37
38#ifdef _STRBUF_STRLEN_FUNC
39# undef _STRBUF_STRLEN_FUNC
40#endif
41
42#ifdef _STRBUF_STRESCAPE_FUNC
43# undef _STRBUF_STRESCAPE_FUNC
44#endif
45
46#ifdef _STRBUF_MAGIC
47# undef _STRBUF_MAGIC
48#endif
49
50#ifdef _STRBUF_MAGIC_STR
51# undef _STRBUF_MAGIC_STR
52#endif
53
54#ifdef _FUNC_EXPAND
55# undef _FUNC_EXPAND
56#endif
57
58
59#define _STRBUF_DATA_TYPE char
60#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE)
61#define _STRBUF_STRUCT_NAME Eina_Strbuf
62#define _STRBUF_STRLEN_FUNC(x) strlen(x)
63#define _STRBUF_STRESCAPE_FUNC(x) eina_str_escape(x)
64#define _STRBUF_MAGIC EINA_MAGIC_STRBUF
65#define _STRBUF_MAGIC_STR __STRBUF_MAGIC_STR
66static const char __STRBUF_MAGIC_STR[] = "Eina Strbuf";
67
68#define _FUNC_EXPAND(y) eina_strbuf_ ## y
69
70/**
71 * @endcond
72 */
73
74
75/*============================================================================*
76 * Global *
77 *============================================================================*/
78
79
80/*============================================================================*
81 * API *
82 *============================================================================*/
83
84
85EAPI Eina_Bool
86eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...)
87{
88 va_list args;
89 char *str;
90 size_t len;
91 Eina_Bool ret;
92
93 va_start(args, fmt);
94 len = vasprintf(&str, fmt, args);
95 va_end(args);
96
97 if (len <= 0 || !str)
98 return EINA_FALSE;
99
100 ret = eina_strbuf_append_length(buf, str, len);
101 free(str);
102 return ret;
103}
104
105EAPI Eina_Bool
106eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args)
107{
108 char *str;
109 size_t len;
110 Eina_Bool ret;
111
112 len = vasprintf(&str, fmt, args);
113
114 if (len <= 0 || !str)
115 return EINA_FALSE;
116
117 ret = eina_strbuf_append_length(buf, str, len);
118 free(str);
119 return ret;
120}
121
122EAPI Eina_Bool
123eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...)
124{
125 va_list args;
126 char *str;
127 size_t len;
128 Eina_Bool ret;
129
130 va_start(args, pos);
131 len = vasprintf(&str, fmt, args);
132 va_end(args);
133
134 if (len <= 0 || !str)
135 return EINA_FALSE;
136
137 ret = eina_strbuf_insert(buf, str, pos);
138 free(str);
139 return ret;
140}
141
142EAPI Eina_Bool
143eina_strbuf_insert_vprintf(Eina_Strbuf *buf,
144 const char *fmt,
145 size_t pos,
146 va_list args)
147{
148 char *str;
149 size_t len;
150 Eina_Bool ret;
151
152 len = vasprintf(&str, fmt, args);
153
154 if (len <= 0 || !str)
155 return EINA_FALSE;
156
157 ret = eina_strbuf_insert(buf, str, pos);
158 free(str);
159 return ret;
160}
161
162EAPI void
163eina_strbuf_trim(Eina_Strbuf *buf)
164{
165 char *c = buf->buf;
166
167 while (buf->len > 0 && isspace(((unsigned char*)(buf->buf))[buf->len - 1]))
168 buf->len--;
169 while (buf->len > 0 && isspace(*c))
170 {
171 c++;
172 buf->len--;
173 }
174 memmove(buf->buf, c, buf->len);
175 ((unsigned char *)buf->buf)[buf->len] = '\0';
176}
177
178EAPI void
179eina_strbuf_ltrim(Eina_Strbuf *buf)
180{
181 char *c = buf->buf;
182
183 while (buf->len > 0 && isspace(*c))
184 {
185 c++;
186 buf->len--;
187 }
188 memmove(buf->buf, c, buf->len);
189 ((unsigned char *)buf->buf)[buf->len] = '\0';
190}
191
192EAPI void
193eina_strbuf_rtrim(Eina_Strbuf *buf)
194{
195 while (buf->len > 0 && isspace(((unsigned char*)(buf->buf))[buf->len - 1]))
196 buf->len--;
197 ((unsigned char *)buf->buf)[buf->len] = '\0';
198}
199
200/* Unicode */
201
202#include "eina_strbuf_template_c.x"
diff --git a/libraries/eina/src/lib/eina_strbuf_common.c b/libraries/eina/src/lib/eina_strbuf_common.c
new file mode 100644
index 0000000..46067cd
--- /dev/null
+++ b/libraries/eina/src/lib/eina_strbuf_common.c
@@ -0,0 +1,874 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#ifdef _WIN32
10# include <Evil.h>
11#endif
12
13#include "eina_private.h"
14#include "eina_str.h"
15#include "eina_magic.h"
16#include "eina_error.h"
17#include "eina_safety_checks.h"
18#include "eina_strbuf.h"
19#include "eina_strbuf_common.h"
20
21/*============================================================================*
22* Local *
23*============================================================================*/
24
25/**
26 * @cond LOCAL
27 */
28
29#define EINA_STRBUF_INIT_SIZE 32
30#define EINA_STRBUF_INIT_STEP 32
31#define EINA_STRBUF_MAX_STEP 4096
32
33/**
34 * @endcond
35 */
36
37/*============================================================================*
38* Global *
39*============================================================================*/
40
41/**
42 * @internal
43 * @brief Initialize the strbuf module.
44 *
45 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
46 *
47 * This function sets up the strbuf module of Eina. It is called by
48 * eina_init().
49 *
50 * @see eina_init()
51 */
52Eina_Bool
53eina_strbuf_common_init(void)
54{
55 return EINA_TRUE;
56}
57
58/**
59 * @internal
60 * @brief Shut down the strbuf module.
61 *
62 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
63 *
64 * This function shuts down the strbuf module set up by
65 * eina_strbuf_common_init(). It is called by eina_shutdown().
66 *
67 * @see eina_shutdown()
68 */
69Eina_Bool
70eina_strbuf_common_shutdown(void)
71{
72 return EINA_TRUE;
73}
74
75/**
76 * @internal
77 *
78 * init the buffer
79 * @param csize the character size
80 * @param buf the buffer to init
81 *
82 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
83 */
84static Eina_Bool
85_eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf)
86{
87 buf->len = 0;
88 buf->size = EINA_STRBUF_INIT_SIZE;
89 buf->step = EINA_STRBUF_INIT_STEP;
90
91 eina_error_set(0);
92 buf->buf = calloc(csize, buf->size);
93 if (EINA_UNLIKELY(!buf->buf))
94 {
95 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
96 return EINA_FALSE;
97 }
98
99 return EINA_TRUE;
100}
101
102/**
103 * @internal
104 *
105 * init the buffer without allocating the actual string (for managed)
106 * @param csize the character size
107 * @param buf the buffer to init
108 *
109 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
110 */
111static Eina_Bool
112_eina_strbuf_common_manage_init(size_t csize __UNUSED__,
113 Eina_Strbuf *buf,
114 void *str,
115 size_t len)
116{
117 buf->len = len;
118 buf->size = len + 1;
119 buf->step = EINA_STRBUF_INIT_STEP;
120 buf->buf = str;
121
122 return EINA_TRUE;
123}
124
125
126/**
127 * @internal
128 *
129 * resize the buffer
130 * @param csize the character size
131 * @param buf the buffer to resize
132 * @param size the minimum size of the buffer
133 *
134 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
135 */
136static inline Eina_Bool
137_eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size)
138{
139 size_t new_size, new_step, delta;
140 void *buffer;
141
142 size += 1; // Add extra space for '\0'
143
144 /* nothing to do */
145 if (size == buf->size) return EINA_TRUE;
146 else if (size > buf->size) delta = size - buf->size;
147 else delta = buf->size - size;
148
149 /* check if should keep the same step (just used while growing) */
150 if ((delta <= buf->step) && (size > buf->size)) new_step = buf->step;
151 else
152 {
153 new_step = (((delta / EINA_STRBUF_INIT_STEP) + 1)
154 * EINA_STRBUF_INIT_STEP);
155 if (new_step > EINA_STRBUF_MAX_STEP) new_step = EINA_STRBUF_MAX_STEP;
156 }
157
158 new_size = (((size / new_step) + 1) * new_step);
159
160 /* reallocate the buffer to the new size */
161 buffer = realloc(buf->buf, new_size * csize);
162 if (EINA_UNLIKELY(!buffer))
163 {
164 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
165 return EINA_FALSE;
166 }
167
168 buf->buf = buffer;
169 buf->size = new_size;
170 buf->step = new_step;
171 eina_error_set(0);
172 return EINA_TRUE;
173}
174
175/**
176 * @internal
177 *
178 * If required, enlarge the buffer to fit the new size.
179 *
180 * @param csize the character size
181 * @param buf the buffer to resize
182 * @param size the minimum size of the buffer
183 *
184 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
185 */
186Eina_Bool
187_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size)
188{
189 if ((size + 1) < buf->size) return EINA_TRUE;
190 return _eina_strbuf_common_resize(csize, buf, size);
191}
192
193/**
194 * @internal
195 *
196 * insert string of known length at random within existing strbuf limits.
197 *
198 * @param csize the character size
199 * @param buf the buffer to resize, must be valid.
200 * @param str the string to copy, must be valid (!NULL and smaller than @a len)
201 * @param len the amount of bytes in @a str to copy, must be valid.
202 * @param pos the position inside buffer to insert, must be valid (smaller
203 * than eina_strbuf_common_length_get())
204 *
205 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
206 */
207static inline Eina_Bool
208_eina_strbuf_common_insert_length(size_t csize,
209 Eina_Strbuf *buf,
210 const void *str,
211 size_t len,
212 size_t pos)
213{
214 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
215 return EINA_FALSE;
216
217 /* move the existing text */
218 memmove(((unsigned char *)(buf->buf)) + ((len + pos) * csize),
219 ((unsigned char *)(buf->buf)) + (pos * csize),
220 (buf->len - pos) * csize);
221
222 /* and now insert the given string */
223 memcpy((unsigned char *)buf->buf + (pos * csize), str, len * csize);
224
225 buf->len += len;
226 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
227 return EINA_TRUE;
228}
229
230/*============================================================================*
231* API *
232*============================================================================*/
233
234/**
235 * @internal
236 * @brief Create a new string buffer.
237 *
238 * @param csize the character size
239 * @return Newly allocated string buffer instance.
240 *
241 * This function creates a new string buffer. On error, @c NULL is
242 * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To
243 * free the resources, use eina_strbuf_common_free().
244 *
245 * @see eina_strbuf_common_free()
246 * @see eina_strbuf_common_append()
247 * @see eina_strbuf_common_string_get()
248 */
249Eina_Strbuf *
250eina_strbuf_common_new(size_t csize)
251{
252 Eina_Strbuf *buf;
253
254 eina_error_set(0);
255 buf = malloc(sizeof(Eina_Strbuf));
256 if (EINA_UNLIKELY(!buf))
257 {
258 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
259 return NULL;
260 }
261 if (EINA_UNLIKELY(!_eina_strbuf_common_init(csize, buf)))
262 {
263 eina_strbuf_common_free(buf);
264 return NULL;
265 }
266 return buf;
267}
268
269/**
270 * @internal
271 * @brief Create a new string buffer managing str.
272 *
273 * @param csize the character size
274 * @param str the string to manage
275 * @param len the length of the string to manage
276 * @return Newly allocated string buffer instance.
277 *
278 * This function creates a new string buffer. On error, @c NULL is
279 * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To
280 * free the resources, use eina_strbuf_common_free().
281 *
282 * @see eina_strbuf_common_free()
283 * @see eina_strbuf_common_append()
284 * @see eina_strbuf_common_string_get()
285 * @since 1.1.0
286 */
287Eina_Strbuf *
288eina_strbuf_common_manage_new(size_t csize,
289 void *str,
290 size_t len)
291{
292 Eina_Strbuf *buf;
293
294 eina_error_set(0);
295 buf = malloc(sizeof(Eina_Strbuf));
296 if (EINA_UNLIKELY(!buf))
297 {
298 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
299 return NULL;
300 }
301 if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len)))
302 {
303 eina_strbuf_common_free(buf);
304 return NULL;
305 }
306 return buf;
307}
308
309/**
310 * @internal
311 * @brief Free a string buffer.
312 *
313 * @param buf The string buffer to free.
314 *
315 * This function frees the memory of @p buf. @p buf must have been
316 * created by eina_strbuf_common_new().
317 */
318void
319eina_strbuf_common_free(Eina_Strbuf *buf)
320{
321 free(buf->buf);
322 free(buf);
323}
324
325/**
326 * @internal
327 * @brief Reset a string buffer.
328 *
329 * @param csize the character size
330 * @param buf The string buffer to reset.
331 *
332 * This function reset @p buf: the buffer len is set to 0, and the
333 * string is set to '\\0'. No memory is free'd.
334 */
335void
336eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf)
337{
338 buf->len = 0;
339 buf->step = EINA_STRBUF_INIT_STEP;
340 memset(buf->buf, 0, csize);
341}
342
343/**
344 * @internal
345 * @brief Append a string to a buffer, reallocating as necessary.
346 *
347 * @param csize the character size
348 * @param buf The string buffer to append to.
349 * @param str The string to append.
350 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
351 *
352 * This function appends @p str to @p buf. It computes the length of
353 * @p str, so is slightly slower than eina_strbuf_common_append_length(). If
354 * the length is known beforehand, consider using that variant. If
355 * @p buf can't append it, #EINA_FALSE is returned, otherwise
356 * #EINA_TRUE is returned.
357 *
358 * @see eina_strbuf_common_append()
359 * @see eina_strbuf_common_append_length()
360 */
361Eina_Bool
362eina_strbuf_common_append(size_t csize,
363 Eina_Strbuf *buf,
364 const void *str,
365 size_t len)
366{
367 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
368
369 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
370 return EINA_FALSE;
371 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
372 (len + 1) * csize);
373 buf->len += len;
374 return EINA_TRUE;
375}
376
377/**
378 * @internal
379 * @brief Append a string to a buffer, reallocating as necessary,
380 * limited by the given length.
381 *
382 * @param csize the character size
383 * @param buf The string buffer to append to.
384 * @param str The string to append.
385 * @param maxlen The maximum number of characters to append.
386 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
387 *
388 * This function appends at most @p maxlen characters of @p str to
389 * @p buf. It can't appends more than the length of @p str. It
390 * computes the length of @p str, so is slightly slower than
391 * eina_strbuf_common_append_length(). If the length is known beforehand,
392 * consider using that variant (@p maxlen should then be checked so
393 * that it is greater than the size of @p str). If @p str can not be
394 * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
395 * returned.
396 *
397 * @see eina_strbuf_common_append()
398 * @see eina_strbuf_common_append_length()
399 */
400Eina_Bool
401eina_strbuf_common_append_n(size_t csize,
402 Eina_Strbuf *buf,
403 const void *str,
404 size_t len,
405 size_t maxlen)
406{
407 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
408
409 if (len > maxlen) len = maxlen;
410 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
411 return EINA_FALSE;
412 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
413 len * csize);
414 buf->len += len;
415 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
416 return EINA_TRUE;
417}
418
419/**
420 * @internal
421 * @brief Append a string of exact length to a buffer, reallocating as necessary.
422 *
423 * @param csize the character size
424 * @param buf The string buffer to append to.
425 * @param str The string to append.
426 * @param length The exact length to use.
427 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
428 *
429 * This function appends @p str to @p buf. @p str must be of size at
430 * most @p length. It is slightly faster than eina_strbuf_common_append() as
431 * it does not compute the size of @p str. It is useful when dealing
432 * with strings of known size, such as eina_strngshare. If @p buf
433 * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
434 * returned.
435 *
436 * @see eina_stringshare_length()
437 * @see eina_strbuf_common_append()
438 * @see eina_strbuf_common_append_n()
439 */
440Eina_Bool
441eina_strbuf_common_append_length(size_t csize,
442 Eina_Strbuf *buf,
443 const void *str,
444 size_t length)
445{
446 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
447
448 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + length)))
449 return EINA_FALSE;
450 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
451 length * csize);
452 buf->len += length;
453 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
454 return EINA_TRUE;
455}
456
457/**
458 * @internal
459 * @brief Insert a string to a buffer, reallocating as necessary.
460 *
461 * @param csize the character size
462 * @param buf The string buffer to insert.
463 * @param str The string to insert.
464 * @param pos The position to insert the string.
465 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
466 *
467 * This function inserts @p str to @p buf at position @p pos. It
468 * computes the length of @p str, so is slightly slower than
469 * eina_strbuf_common_insert_length(). If the length is known beforehand,
470 * consider using that variant. If @p buf can't insert it, #EINA_FALSE
471 * is returned, otherwise #EINA_TRUE is returned.
472 */
473Eina_Bool
474eina_strbuf_common_insert(size_t csize,
475 Eina_Strbuf *buf,
476 const void *str,
477 size_t len,
478 size_t pos)
479{
480 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
481
482 if (pos >= buf->len) return eina_strbuf_common_append(csize, buf, str, len);
483 return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
484}
485
486/**
487 * @internal
488 * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
489 *
490 * @param csize the character size
491 * @param buf The string buffer to insert to.
492 * @param str The string to insert.
493 * @param maxlen The maximum number of chars to insert.
494 * @param pos The position to insert the string.
495 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
496 *
497 * This function inserts @p str ot @p buf at position @p pos, with at
498 * most @p maxlen bytes. The number of inserted characters can not be
499 * greater than the length of @p str. It computes the length of
500 * @p str, so is slightly slower than eina_strbuf_common_insert_length(). If the
501 * length is known beforehand, consider using that variant (@p maxlen
502 * should then be checked so that it is greater than the size of
503 * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
504 * otherwise, #EINA_TRUE is returned.
505 */
506Eina_Bool
507eina_strbuf_common_insert_n(size_t csize,
508 Eina_Strbuf *buf,
509 const void *str,
510 size_t len,
511 size_t maxlen,
512 size_t pos)
513{
514 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
515
516 if (pos >= buf->len)
517 return eina_strbuf_common_append_n(csize, buf, str, len, maxlen);
518 if (len > maxlen) len = maxlen;
519 return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
520}
521
522/**
523 * @internal
524 * @brief Insert a string of exact length to a buffer, reallocating as necessary.
525 *
526 * @param csize the character size
527 * @param buf The string buffer to insert to.
528 * @param str The string to insert.
529 * @param length The exact length to use.
530 * @param pos The position to insert the string.
531 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
532 *
533 * This function inserts @p str to @p buf. @p str must be of size at
534 * most @p length. It is slightly faster than eina_strbuf_common_insert() as
535 * it does not compute the size of @p str. It is useful when dealing
536 * with strings of known size, such as eina_strngshare. If @p buf
537 * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
538 * returned.
539 *
540 * @see eina_stringshare_length()
541 * @see eina_strbuf_common_insert()
542 * @see eina_strbuf_common_insert_n()
543 */
544Eina_Bool
545eina_strbuf_common_insert_length(size_t csize,
546 Eina_Strbuf *buf,
547 const void *str,
548 size_t length,
549 size_t pos)
550{
551 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
552
553 if (pos >= buf->len)
554 return eina_strbuf_common_append_length(csize, buf, str, length);
555 return _eina_strbuf_common_insert_length(csize, buf, str, length, pos);
556}
557
558/**
559 * @internal
560 * @brief Append a character to a string buffer, reallocating as
561 * necessary.
562 *
563 * @param csize the character size
564 * @param buf The string buffer to append to.
565 * @param c The char to append.
566 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
567 *
568 * This function inserts @p c to @p buf. If it can not insert it,
569 * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned.
570 */
571Eina_Bool
572eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c)
573{
574 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + 1)))
575 return EINA_FALSE;
576
577 memcpy(((unsigned char *)(buf->buf)) + ((buf->len)++ *csize), c, csize);
578 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
579 return EINA_TRUE;
580}
581
582/**
583 * @internal
584 * @brief Insert a character to a string buffer, reallocating as
585 * necessary.
586 *
587 * @param csize the character size
588 * @param buf The string buffer to insert to.
589 * @param c The char to insert.
590 * @param pos The position to insert the char.
591 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
592 *
593 * This function inserts @p c to @p buf at position @p pos. If @p buf
594 * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
595 * returned.
596 */
597Eina_Bool
598eina_strbuf_common_insert_char(size_t csize,
599 Eina_Strbuf *buf,
600 const void *c,
601 size_t pos)
602{
603 if (pos >= buf->len)
604 return eina_strbuf_common_append_char(csize, buf, c);
605 return _eina_strbuf_common_insert_length(csize, buf, c, 1, pos);
606}
607
608/**
609 * @internal
610 * @brief Remove a slice of the given string buffer.
611 *
612 * @param csize the character size
613 * @param buf The string buffer to remove a slice.
614 * @param start The initial (inclusive) slice position to start
615 * removing, in bytes.
616 * @param end The final (non-inclusive) slice position to finish
617 * removing, in bytes.
618 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
619 *
620 * This function removes a slice of @p buf, starting at @p start
621 * (inclusive) and ending at @p end (non-inclusive). Both values are
622 * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
623 */
624Eina_Bool
625eina_strbuf_common_remove(size_t csize,
626 Eina_Strbuf *buf,
627 size_t start,
628 size_t end)
629{
630 size_t remove_len, tail_len;
631
632 if (end >= buf->len) end = buf->len;
633 if (end <= start) return EINA_TRUE;
634
635 remove_len = end - start;
636 if (remove_len == buf->len)
637 {
638 free(buf->buf);
639 return _eina_strbuf_common_init(csize, buf);
640 }
641
642 tail_len = buf->len - end + 1; /* includes '\0' */
643 memmove(((unsigned char *)(buf->buf)) + (start * csize),
644 ((unsigned char *)(buf->buf)) + (end * csize),
645 tail_len * csize);
646 buf->len -= remove_len;
647 return _eina_strbuf_common_resize(csize, buf, buf->len);
648}
649
650/**
651 * @internal
652 * @brief Retrieve a pointer to the contents of a string buffer
653 *
654 * @param buf The string buffer.
655 * @return The current string in the string buffer.
656 *
657 * This function returns the string contained in @p buf. The returned
658 * value must not be modified and will no longer be valid if @p buf is
659 * modified. In other words, any eina_strbuf_common_append() or similar will
660 * make that pointer invalid.
661 *
662 * @see eina_strbuf_common_string_steal()
663 */
664const void *
665eina_strbuf_common_string_get(const Eina_Strbuf *buf)
666{
667 return buf->buf;
668}
669
670/**
671 * @internal
672 * @brief Steal the contents of a string buffer.
673 *
674 * @param csize the character size
675 * @param buf The string buffer to steal.
676 * @return The current string in the string buffer.
677 *
678 * This function returns the string contained in @p buf. @p buf is
679 * then initialized and does not own the returned string anymore. The
680 * caller must release the memory of the returned string by calling
681 * free().
682 *
683 * @see eina_strbuf_common_string_get()
684 */
685void *
686eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf)
687{
688 void *ret;
689
690 ret = buf->buf;
691 // TODO: Check return value and do something clever
692 _eina_strbuf_common_init(csize, buf);
693 return ret;
694}
695
696/**
697 * @internal
698 * @brief Free the contents of a string buffer but not the buffer.
699 *
700 * @param csize the character size
701 * @param buf The string buffer to free the string of.
702 *
703 * This function frees the string contained in @p buf without freeing
704 * @p buf.
705 */
706void
707eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf)
708{
709 free(buf->buf);
710 _eina_strbuf_common_init(csize, buf);
711}
712
713/**
714 * @internal
715 * @brief Retrieve the length of the string buffer content.
716 *
717 * @param buf The string buffer.
718 * @return The current length of the string, in bytes.
719 *
720 * This function returns the length of @p buf.
721 */
722size_t
723eina_strbuf_common_length_get(const Eina_Strbuf *buf)
724{
725 return buf->len;
726}
727
728/**
729 * @cond LOCAL
730 */
731
732/*FIXME: Implementing them here is a hack! */
733
734#ifdef _STRBUF_CSIZE
735# undef _STRBUF_CSIZE
736#endif
737
738#ifdef _STRBUF_MAGIC
739# undef _STRBUF_MAGIC
740#endif
741
742#ifdef _STRBUF_MAGIC_STR
743# undef _STRBUF_MAGIC_STR
744#endif
745
746#define _STRBUF_CSIZE 1
747#define _STRBUF_MAGIC EINA_MAGIC_STRBUF
748#define _STRBUF_MAGIC_STR __STRBUF_STR_MAGIC_STR
749static const char __STRBUF_STR_MAGIC_STR[] = "Eina Strbuf";
750
751
752/**
753 * @endcond
754 */
755
756
757EAPI Eina_Bool
758eina_strbuf_replace(Eina_Strbuf *buf,
759 const char *str,
760 const char *with,
761 unsigned int n)
762{
763 size_t len1, len2;
764 char *spos;
765 size_t pos;
766
767 EINA_SAFETY_ON_NULL_RETURN_VAL( str, EINA_FALSE);
768 EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE);
769 EINA_MAGIC_CHECK_STRBUF(buf, 0);
770 if (n == 0) return EINA_FALSE;
771
772 spos = buf->buf;
773 while (n--)
774 {
775 spos = strstr(spos, str);
776 if (!spos || *spos == '\0') return EINA_FALSE;
777 if (n) spos++;
778 }
779
780 pos = spos - (const char *)buf->buf;
781 len1 = strlen(str);
782 len2 = strlen(with);
783 if (len1 != len2)
784 {
785 /* resize the buffer if necessary */
786 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf,
787 buf->len - len1 + len2)))
788 return EINA_FALSE; /* move the existing text */
789 memmove(((unsigned char *)(buf->buf)) + pos + len2,
790 ((unsigned char *)(buf->buf)) + pos + len1,
791 buf->len - pos - len1);
792 }
793 /* and now insert the given string */
794 memcpy(((unsigned char *)(buf->buf)) + pos, with, len2);
795 buf->len += len2 - len1;
796 memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1);
797 return EINA_TRUE;
798}
799
800EAPI int
801eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with)
802{
803 size_t len1, len2, len;
804 char *tmp_buf = NULL;
805 char *spos;
806 size_t pos, start;
807 size_t pos_tmp, start_tmp;
808 int n = 0;
809
810 EINA_SAFETY_ON_NULL_RETURN_VAL( str, 0);
811 EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0);
812 EINA_MAGIC_CHECK_STRBUF(buf, 0);
813
814 spos = strstr(buf->buf, str);
815 if (!spos || *spos == '\0') return 0;
816 len1 = strlen(str);
817 len2 = strlen(with);
818 /* if the size of the two string is equal, it is fairly easy to replace them
819 * we don't need to resize the buffer or doing other calculations */
820 if (len1 == len2)
821 {
822 while (spos)
823 {
824 memcpy(spos, with, len2);
825 spos = strstr(spos + len2, str);
826 n++;
827 }
828 return n;
829 }
830 pos = pos_tmp = spos - (const char *)buf->buf;
831 tmp_buf = buf->buf;
832 buf->buf = malloc(buf->size);
833 if (EINA_UNLIKELY(!buf->buf))
834 {
835 buf->buf = tmp_buf;
836 return 0;
837 }
838 start = start_tmp = 0;
839 len = buf->len;
840 while (spos)
841 {
842 n++;
843 len = (len + len2) - len1;
844 /* resize the buffer if necessary */
845 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, len)))
846 {
847 /* we have to stop replacing here, because we haven't enough
848 * memory to go on */
849 len = (len + len1) - len2;
850 break;
851 }
852 /* copy the untouched text */
853 memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp,
854 pos - start);
855 /* copy the new string */
856 memcpy(((unsigned char *)(buf->buf)) + pos, with, len2);
857 /* calculate the next positions */
858 start_tmp = pos_tmp + len1;
859 start = pos + len2;
860 spos = strstr(tmp_buf + start_tmp, str);
861 /* this calculations don't make sense if spos == NULL, but the
862 * calculated values won't be used, because the loop will stop
863 * then */
864 pos_tmp = spos - tmp_buf;
865 pos = start + pos_tmp - start_tmp;
866 }
867 /* and now copy the rest of the text */
868 memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp,
869 len - start);
870 buf->len = len;
871 memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1);
872 free(tmp_buf);
873 return n;
874}
diff --git a/libraries/eina/src/lib/eina_strbuf_common.h b/libraries/eina/src/lib/eina_strbuf_common.h
new file mode 100644
index 0000000..06a1353
--- /dev/null
+++ b/libraries/eina/src/lib/eina_strbuf_common.h
@@ -0,0 +1,120 @@
1#ifndef EINA_STRBUF_COMMON_H
2#define EINA_STRBUF_COMMON_H
3
4#include <stdlib.h>
5
6#include "eina_private.h"
7#include "eina_magic.h"
8#include "eina_strbuf.h"
9
10/**
11 * @struct _Eina_Strbuf
12 * String buffer to facilitate string operations.
13 */
14struct _Eina_Strbuf
15{
16 void *buf;
17 size_t len;
18 size_t size;
19 size_t step;
20
21 EINA_MAGIC
22};
23
24#define EINA_MAGIC_CHECK_STRBUF(d, ...) \
25 do { \
26 if (!EINA_MAGIC_CHECK((d), _STRBUF_MAGIC)) \
27 { \
28 EINA_MAGIC_FAIL((d), _STRBUF_MAGIC); \
29 return __VA_ARGS__; \
30 } \
31 } while (0)
32
33Eina_Bool
34eina_strbuf_common_init(void);
35
36Eina_Bool
37eina_strbuf_common_shutdown(void);
38Eina_Strbuf *
39eina_strbuf_common_new(size_t csize);
40Eina_Strbuf *
41eina_strbuf_common_manage_new(size_t csize,
42 void *str,
43 size_t len);
44void
45eina_strbuf_common_free(Eina_Strbuf *buf);
46void
47eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf);
48Eina_Bool
49eina_strbuf_common_append(size_t csize,
50 Eina_Strbuf *buf,
51 const void *str,
52 size_t len);
53Eina_Bool
54eina_strbuf_common_append_escaped(size_t csize,
55 Eina_Strbuf *buf,
56 const void *str);
57Eina_Bool
58eina_strbuf_common_append_n(size_t csize,
59 Eina_Strbuf *buf,
60 const void *str,
61 size_t len,
62 size_t maxlen);
63Eina_Bool
64eina_strbuf_common_append_length(size_t csize,
65 Eina_Strbuf *buf,
66 const void *str,
67 size_t length);
68Eina_Bool
69eina_strbuf_common_insert(size_t csize,
70 Eina_Strbuf *buf,
71 const void *str,
72 size_t len,
73 size_t pos);
74Eina_Bool
75eina_strbuf_common_insert_escaped(size_t csize,
76 Eina_Strbuf *buf,
77 const void *str,
78 size_t len,
79 size_t pos);
80Eina_Bool
81eina_strbuf_common_insert_n(size_t csize,
82 Eina_Strbuf *buf,
83 const void *str,
84 size_t len,
85 size_t maxlen,
86 size_t pos);
87Eina_Bool
88eina_strbuf_common_insert_length(size_t csize,
89 Eina_Strbuf *buf,
90 const void *str,
91 size_t length,
92 size_t pos);
93Eina_Bool
94eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c);
95Eina_Bool
96eina_strbuf_common_insert_char(size_t csize,
97 Eina_Strbuf *buf,
98 const void *c,
99 size_t pos);
100Eina_Bool
101eina_strbuf_common_remove(size_t csize,
102 Eina_Strbuf *buf,
103 size_t start,
104 size_t end);
105const void *
106eina_strbuf_common_string_get(const Eina_Strbuf *buf);
107void *
108eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf);
109void
110eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf);
111size_t
112eina_strbuf_common_length_get(const Eina_Strbuf *buf);
113
114Eina_Bool
115_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size);
116/**
117 * @}
118 */
119
120#endif
diff --git a/libraries/eina/src/lib/eina_strbuf_template_c.x b/libraries/eina/src/lib/eina_strbuf_template_c.x
new file mode 100644
index 0000000..e8c3b61
--- /dev/null
+++ b/libraries/eina/src/lib/eina_strbuf_template_c.x
@@ -0,0 +1,97 @@
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 strbuf.
6 The including file should define the following macros:
7 * _STRBUF_DATA_TYPE
8 * _STRBUF_CSIZE
9 * _STRBUF_STRUCT_NAME
10 * _STRBUF_STRLEN_FUNC(x)
11 * _STRBUF_STRESCAPE_FUNC(x)
12 * _STRBUF_STRSTR_FUNC(x, y)
13 * _STRBUF_MAGIC
14 * _STRBUF_MAGIC_STR
15 * See how it's done in eina_ustrbuf.c and eina_strbuf.c. This just makes things
16 * a lot easier since those are essentially the same just with different sizes.
17 */
18
19#include "eina_binbuf_template_c.x"
20
21/*============================================================================*
22 * API *
23 *============================================================================*/
24
25EAPI _STRBUF_STRUCT_NAME *
26_FUNC_EXPAND(manage_new)(_STRBUF_DATA_TYPE *str)
27{
28 _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_manage_new(_STRBUF_CSIZE,
29 (void *) str, _STRBUF_STRLEN_FUNC(str));
30 EINA_MAGIC_SET(buf, _STRBUF_MAGIC);
31 return buf;
32}
33
34EAPI Eina_Bool
35_FUNC_EXPAND(append)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str)
36{
37 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
38 return eina_strbuf_common_append(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str));
39}
40
41EAPI Eina_Bool
42_FUNC_EXPAND(append_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str)
43{
44 _STRBUF_DATA_TYPE *esc;
45 Eina_Bool ret;
46
47 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
48 esc = _STRBUF_STRESCAPE_FUNC(str);
49 if (!esc) {
50 return _FUNC_EXPAND(append)(buf, str);
51 }
52 ret = _FUNC_EXPAND(append)(buf, esc);
53 if (esc)
54 free(esc);
55
56 return ret;
57}
58
59EAPI Eina_Bool
60_FUNC_EXPAND(append_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen)
61{
62 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
63 return eina_strbuf_common_append_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen);
64}
65
66EAPI Eina_Bool
67_FUNC_EXPAND(insert)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos)
68{
69 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
70 return eina_strbuf_common_insert(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), pos);
71}
72
73EAPI Eina_Bool
74_FUNC_EXPAND(insert_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos)
75{
76 _STRBUF_DATA_TYPE *esc;
77 Eina_Bool ret;
78 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
79
80 esc = _STRBUF_STRESCAPE_FUNC(str);
81 if (!esc) {
82 return _FUNC_EXPAND(insert)(buf, str, pos);
83 }
84 ret = _FUNC_EXPAND(insert)(buf, esc, pos);
85 if (esc)
86 free(esc);
87
88 return ret;
89}
90
91EAPI Eina_Bool
92_FUNC_EXPAND(insert_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen, size_t pos)
93{
94 EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
95 return eina_strbuf_common_insert_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen, pos);
96}
97
diff --git a/libraries/eina/src/lib/eina_stringshare.c b/libraries/eina/src/lib/eina_stringshare.c
new file mode 100644
index 0000000..478b300
--- /dev/null
+++ b/libraries/eina/src/lib/eina_stringshare.c
@@ -0,0 +1,751 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010
3 * Carsten Haitzler,
4 * Jorge Luis Zapata Muga,
5 * Cedric Bail,
6 * Gustavo Sverzut Barbieri
7 * Tom Hacohen
8 * Brett Nash
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library;
22 * if not, see <http://www.gnu.org/licenses/>.
23 */
24
25#ifdef HAVE_CONFIG_H
26# include "config.h"
27#endif
28
29#ifdef HAVE_ALLOCA_H
30# include <alloca.h>
31#elif defined __GNUC__
32# define alloca __builtin_alloca
33#elif defined _AIX
34# define alloca __alloca
35#elif defined _MSC_VER
36# include <malloc.h>
37# define alloca _alloca
38#else
39# include <stddef.h>
40# ifdef __cplusplus
41extern "C"
42# endif
43void *alloca (size_t);
44#endif
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49
50#ifdef HAVE_EVIL
51# include <Evil.h>
52#endif
53
54#include "eina_config.h"
55#include "eina_private.h"
56#include "eina_error.h"
57#include "eina_log.h"
58#include "eina_stringshare.h"
59#include "eina_lock.h"
60
61/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
62#include "eina_safety_checks.h"
63#include "eina_share_common.h"
64
65/* The actual share */
66static Eina_Share *stringshare_share;
67static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node";
68
69extern Eina_Bool _share_common_threads_activated;
70static Eina_Lock _mutex_small;
71
72/* Stringshare optimizations */
73static const unsigned char _eina_stringshare_single[512] = {
74 0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,
75 16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,
76 31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,
77 46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,
78 61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,
79 76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,
80 91,0,92,0,93,0,94,0,95,0,96,0,97,0,98,0,99,0,100,0,101,0,102,0,103,0,104,0,
81 105,0,
82 106,0,107,0,108,0,109,0,110,0,111,0,112,0,113,0,114,0,115,0,116,0,117,0,118,
83 0,119,0,120,0,
84 121,0,122,0,123,0,124,0,125,0,126,0,127,0,128,0,129,0,130,0,131,0,132,0,133,
85 0,134,0,135,0,
86 136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148,
87 0,149,0,150,0,
88 151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163,
89 0,164,0,165,0,
90 166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178,
91 0,179,0,180,0,
92 181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,191,0,192,0,193,
93 0,194,0,195,0,
94 196,0,197,0,198,0,199,0,200,0,201,0,202,0,203,0,204,0,205,0,206,0,207,0,208,
95 0,209,0,210,0,
96 211,0,212,0,213,0,214,0,215,0,216,0,217,0,218,0,219,0,220,0,221,0,222,0,223,
97 0,224,0,225,0,
98 226,0,227,0,228,0,229,0,230,0,231,0,232,0,233,0,234,0,235,0,236,0,237,0,238,
99 0,239,0,240,0,
100 241,0,242,0,243,0,244,0,245,0,246,0,247,0,248,0,249,0,250,0,251,0,252,0,253,
101 0,254,0,255,0
102};
103
104typedef struct _Eina_Stringshare_Small Eina_Stringshare_Small;
105typedef struct _Eina_Stringshare_Small_Bucket Eina_Stringshare_Small_Bucket;
106
107struct _Eina_Stringshare_Small_Bucket
108{
109 /* separate arrays for faster lookups */
110 const char **strings;
111 unsigned char *lengths;
112 unsigned short *references;
113 int count;
114 int size;
115};
116
117struct _Eina_Stringshare_Small
118{
119 Eina_Stringshare_Small_Bucket *buckets[256];
120};
121
122#define EINA_STRINGSHARE_SMALL_BUCKET_STEP 8
123static Eina_Stringshare_Small _eina_small_share;
124
125static inline int
126_eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket,
127 int i,
128 const char *pstr,
129 unsigned char plength)
130{
131 /* pstr and plength are from second char and on, since the first is
132 * always the same.
133 *
134 * First string being always the same, size being between 2 and 3
135 * characters (there is a check for special case length==1 and then
136 * small stringshare is applied to strings < 4), we just need to
137 * compare 2 characters of both strings.
138 */
139 const unsigned char cur_plength = bucket->lengths[i] - 1;
140 const char *cur_pstr;
141
142 if (cur_plength > plength)
143 return 1;
144 else if (cur_plength < plength)
145 return -1;
146
147 cur_pstr = bucket->strings[i] + 1;
148
149 if (cur_pstr[0] > pstr[0])
150 return 1;
151 else if (cur_pstr[0] < pstr[0])
152 return -1;
153
154 if (plength == 1)
155 return 0;
156
157 if (cur_pstr[1] > pstr[1])
158 return 1;
159 else if (cur_pstr[1] < pstr[1])
160 return -1;
161
162 return 0;
163}
164
165static const char *
166_eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket,
167 const char *str,
168 unsigned char length,
169 int *idx)
170{
171 const char *pstr = str + 1; /* skip first letter, it's always the same */
172 unsigned char plength = length - 1;
173 int i, low, high;
174
175 if (bucket->count == 0)
176 {
177 *idx = 0;
178 return NULL;
179 }
180
181 low = 0;
182 high = bucket->count;
183
184 while (low < high)
185 {
186 int r;
187
188 i = (low + high - 1) / 2;
189
190 r = _eina_stringshare_small_cmp(bucket, i, pstr, plength);
191 if (r > 0)
192 high = i;
193 else if (r < 0)
194 low = i + 1;
195 else
196 {
197 *idx = i;
198 return bucket->strings[i];
199 }
200 }
201
202 *idx = low;
203 return NULL;
204}
205
206static Eina_Bool
207_eina_stringshare_small_bucket_resize(Eina_Stringshare_Small_Bucket *bucket,
208 int size)
209{
210 void *tmp;
211
212 tmp = realloc((void *)bucket->strings, size * sizeof(bucket->strings[0]));
213 if (!tmp)
214 {
215 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
216 return 0;
217 }
218
219 bucket->strings = tmp;
220
221 tmp = realloc(bucket->lengths, size * sizeof(bucket->lengths[0]));
222 if (!tmp)
223 {
224 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
225 return 0;
226 }
227
228 bucket->lengths = tmp;
229
230 tmp = realloc(bucket->references, size * sizeof(bucket->references[0]));
231 if (!tmp)
232 {
233 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
234 return 0;
235 }
236
237 bucket->references = tmp;
238
239 bucket->size = size;
240 return 1;
241}
242
243static const char *
244_eina_stringshare_small_bucket_insert_at(
245 Eina_Stringshare_Small_Bucket **p_bucket,
246 const char *str,
247 unsigned char length,
248 int idx)
249{
250 Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
251 int todo, off;
252 char *snew;
253
254 if (!bucket)
255 {
256 *p_bucket = bucket = calloc(1, sizeof(*bucket));
257 if (!bucket)
258 {
259 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
260 return NULL;
261 }
262 }
263
264 if (bucket->count + 1 >= bucket->size)
265 {
266 int size = bucket->size + EINA_STRINGSHARE_SMALL_BUCKET_STEP;
267 if (!_eina_stringshare_small_bucket_resize(bucket, size))
268 return NULL;
269 }
270
271 snew = malloc(length + 1);
272 if (!snew)
273 {
274 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
275 return NULL;
276 }
277
278 memcpy(snew, str, length);
279 snew[length] = '\0';
280
281 off = idx + 1;
282 todo = bucket->count - idx;
283 if (todo > 0)
284 {
285 memmove((void *)(bucket->strings + off), bucket->strings + idx,
286 todo * sizeof(bucket->strings[0]));
287 memmove(bucket->lengths + off, bucket->lengths + idx,
288 todo * sizeof(bucket->lengths[0]));
289 memmove(bucket->references + off, bucket->references + idx,
290 todo * sizeof(bucket->references[0]));
291 }
292
293 bucket->strings[idx] = snew;
294 bucket->lengths[idx] = length;
295 bucket->references[idx] = 1;
296 bucket->count++;
297
298 return snew;
299}
300
301static void
302_eina_stringshare_small_bucket_remove_at(
303 Eina_Stringshare_Small_Bucket **p_bucket,
304 int idx)
305{
306 Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
307 int todo, off;
308
309 if (bucket->references[idx] > 1)
310 {
311 bucket->references[idx]--;
312 return;
313 }
314
315 free((char *)bucket->strings[idx]);
316
317 if (bucket->count == 1)
318 {
319 free((void *)bucket->strings);
320 free(bucket->lengths);
321 free(bucket->references);
322 free(bucket);
323 *p_bucket = NULL;
324 return;
325 }
326
327 bucket->count--;
328 if (idx == bucket->count)
329 goto end;
330
331 off = idx + 1;
332 todo = bucket->count - idx;
333
334 memmove((void *)(bucket->strings + idx), bucket->strings + off,
335 todo * sizeof(bucket->strings[0]));
336 memmove(bucket->lengths + idx, bucket->lengths + off,
337 todo * sizeof(bucket->lengths[0]));
338 memmove(bucket->references + idx, bucket->references + off,
339 todo * sizeof(bucket->references[0]));
340
341end:
342 if (bucket->count + EINA_STRINGSHARE_SMALL_BUCKET_STEP < bucket->size)
343 {
344 int size = bucket->size - EINA_STRINGSHARE_SMALL_BUCKET_STEP;
345 _eina_stringshare_small_bucket_resize(bucket, size);
346 }
347}
348
349static const char *
350_eina_stringshare_small_add(const char *str, unsigned char length)
351{
352 Eina_Stringshare_Small_Bucket **bucket;
353 int i;
354
355 bucket = _eina_small_share.buckets + (unsigned char)str[0];
356 if (!*bucket)
357 i = 0;
358 else
359 {
360 const char *ret;
361 ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i);
362 if (ret)
363 {
364 (*bucket)->references[i]++;
365 return ret;
366 }
367 }
368
369 return _eina_stringshare_small_bucket_insert_at(bucket, str, length, i);
370}
371
372static void
373_eina_stringshare_small_del(const char *str, unsigned char length)
374{
375 Eina_Stringshare_Small_Bucket **bucket;
376 const char *ret;
377 int i;
378
379 bucket = _eina_small_share.buckets + (unsigned char)str[0];
380 if (!*bucket)
381 goto error;
382
383 ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i);
384 if (!ret)
385 goto error;
386
387 _eina_stringshare_small_bucket_remove_at(bucket, i);
388 return;
389
390error:
391 CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str);
392}
393
394static void
395_eina_stringshare_small_init(void)
396{
397 eina_lock_new(&_mutex_small);
398 memset(&_eina_small_share, 0, sizeof(_eina_small_share));
399}
400
401static void
402_eina_stringshare_small_shutdown(void)
403{
404 Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end;
405
406 p_bucket = _eina_small_share.buckets;
407 p_bucket_end = p_bucket + 256;
408
409 for (; p_bucket < p_bucket_end; p_bucket++)
410 {
411 Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
412 char **s, **s_end;
413
414 if (!bucket)
415 continue;
416
417 s = (char **)bucket->strings;
418 s_end = s + bucket->count;
419 for (; s < s_end; s++)
420 free(*s);
421
422 free((void *)bucket->strings);
423 free(bucket->lengths);
424 free(bucket->references);
425 free(bucket);
426 *p_bucket = NULL;
427 }
428
429 eina_lock_free(&_mutex_small);
430}
431
432static void
433_eina_stringshare_small_bucket_dump(Eina_Stringshare_Small_Bucket *bucket,
434 struct dumpinfo *di)
435{
436 const char **s = bucket->strings;
437 unsigned char *l = bucket->lengths;
438 unsigned short *r = bucket->references;
439 int i;
440
441 di->used += sizeof(*bucket);
442 di->used += bucket->count * sizeof(*s);
443 di->used += bucket->count * sizeof(*l);
444 di->used += bucket->count * sizeof(*r);
445 di->unique += bucket->count;
446
447 for (i = 0; i < bucket->count; i++, s++, l++, r++)
448 {
449 int dups;
450#ifdef _WIN32
451 printf("DDD: %5hu %5hu '%s'\n", *l, *r, *s);
452#else
453 printf("DDD: %5hhu %5hu '%s'\n", *l, *r, *s);
454#endif
455
456 dups = (*r - 1);
457
458 di->used += *l;
459 di->saved += *l * dups;
460 di->dups += dups;
461 }
462}
463
464static void
465_eina_stringshare_small_dump(struct dumpinfo *di)
466{
467 Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end;
468
469 p_bucket = _eina_small_share.buckets;
470 p_bucket_end = p_bucket + 256;
471
472 for (; p_bucket < p_bucket_end; p_bucket++)
473 {
474 Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
475
476 if (!bucket)
477 continue;
478
479 _eina_stringshare_small_bucket_dump(bucket, di);
480 }
481}
482
483
484/*============================================================================*
485* Global *
486*============================================================================*/
487
488/**
489 * @internal
490 * @brief Initialize the share_common module.
491 *
492 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
493 *
494 * This function sets up the share_common module of Eina. It is called by
495 * eina_init().
496 *
497 * @see eina_init()
498 */
499Eina_Bool
500eina_stringshare_init(void)
501{
502 Eina_Bool ret;
503 ret = eina_share_common_init(&stringshare_share,
504 EINA_MAGIC_STRINGSHARE_NODE,
505 EINA_MAGIC_STRINGSHARE_NODE_STR);
506 if (ret)
507 _eina_stringshare_small_init();
508
509 return ret;
510}
511
512/**
513 * @internal
514 * @brief Shut down the share_common module.
515 *
516 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
517 *
518 * This function shuts down the share_common module set up by
519 * eina_share_common_init(). It is called by eina_shutdown().
520 *
521 * @see eina_shutdown()
522 */
523Eina_Bool
524eina_stringshare_shutdown(void)
525{
526 Eina_Bool ret;
527 _eina_stringshare_small_shutdown();
528 ret = eina_share_common_shutdown(&stringshare_share);
529 return ret;
530}
531
532/*============================================================================*
533* API *
534*============================================================================*/
535
536EAPI void
537eina_stringshare_del(const char *str)
538{
539 int slen;
540
541 if (!str)
542 return;
543
544 /* special cases */
545 if (str[0] == '\0')
546 slen = 0;
547 else if (str[1] == '\0')
548 slen = 1;
549 else if (str[2] == '\0')
550 slen = 2;
551 else if (str[3] == '\0')
552 slen = 3;
553 else
554 slen = 4; /* handled later */
555
556 if (slen < 2)
557 return;
558 else if (slen < 4)
559 {
560 eina_share_common_population_del(stringshare_share, slen);
561 eina_lock_take(&_mutex_small);
562 _eina_stringshare_small_del(str, slen);
563 eina_lock_release(&_mutex_small);
564 return;
565 }
566
567 eina_share_common_del(stringshare_share, str);
568}
569
570EAPI const char *
571eina_stringshare_add_length(const char *str, unsigned int slen)
572{
573 if ((!str) || (slen <= 0))
574 return "";
575 else if (slen == 1)
576 return (const char *)_eina_stringshare_single + ((*str) << 1);
577 else if (slen < 4)
578 {
579 const char *s;
580
581 eina_lock_take(&_mutex_small);
582 s = _eina_stringshare_small_add(str, slen);
583 eina_lock_release(&_mutex_small);
584 return s;
585 }
586
587 return eina_share_common_add_length(stringshare_share, str, slen *
588 sizeof(char), sizeof(char));
589}
590
591EAPI const char *
592eina_stringshare_add(const char *str)
593{
594 int slen;
595 if (!str)
596 return NULL;
597
598 if (str[0] == '\0')
599 slen = 0;
600 else if (str[1] == '\0')
601 slen = 1;
602 else if (str[2] == '\0')
603 slen = 2;
604 else if (str[3] == '\0')
605 slen = 3;
606 else
607 slen = 3 + (int)strlen(str + 3);
608
609 return eina_stringshare_add_length(str, slen);
610}
611
612EAPI const char *
613eina_stringshare_printf(const char *fmt, ...)
614{
615 va_list args;
616 char *tmp;
617 const char *ret;
618 int len;
619
620 if (!fmt)
621 return NULL;
622
623 va_start(args, fmt);
624 len = vasprintf(&tmp, fmt, args);
625 va_end(args);
626
627 if (len < 1)
628 return NULL;
629
630 ret = eina_stringshare_add_length(tmp, len);
631 free(tmp);
632
633 return ret;
634}
635
636EAPI const char *
637eina_stringshare_vprintf(const char *fmt, va_list args)
638{
639 char *tmp;
640 const char *ret;
641 int len;
642
643 if (!fmt)
644 return NULL;
645
646 len = vasprintf(&tmp, fmt, args);
647
648 if (len < 1)
649 return NULL;
650
651 ret = eina_stringshare_add_length(tmp, len);
652 free(tmp);
653
654 return ret;
655}
656
657EAPI const char *
658eina_stringshare_nprintf(unsigned int len, const char *fmt, ...)
659{
660 va_list args;
661 char *tmp;
662 int size;
663
664 if (!fmt)
665 return NULL;
666
667 if (len < 1)
668 return NULL;
669
670 tmp = alloca(sizeof(char) * len + 1);
671
672 va_start(args, fmt);
673 size = vsnprintf(tmp, len, fmt, args);
674 va_end(args);
675
676 if (size < 1)
677 return NULL;
678
679 return eina_stringshare_add_length(tmp, len);
680}
681
682EAPI const char *
683eina_stringshare_ref(const char *str)
684{
685 int slen;
686
687 if (!str)
688 return eina_share_common_ref(stringshare_share, str);
689
690 /* special cases */
691 if (str[0] == '\0')
692 slen = 0;
693 else if (str[1] == '\0')
694 slen = 1;
695 else if (str[2] == '\0')
696 slen = 2;
697 else if (str[3] == '\0')
698 slen = 3;
699 else
700 slen = 3 + (int)strlen(str + 3);
701
702 if (slen < 2)
703 {
704 eina_share_common_population_add(stringshare_share, slen);
705
706 return str;
707 }
708 else if (slen < 4)
709 {
710 const char *s;
711 eina_share_common_population_add(stringshare_share, slen);
712
713 eina_lock_take(&_mutex_small);
714 s = _eina_stringshare_small_add(str, slen);
715 eina_lock_release(&_mutex_small);
716
717 return s;
718 }
719
720 return eina_share_common_ref(stringshare_share, str);
721}
722
723EAPI int
724eina_stringshare_strlen(const char *str)
725{
726 int len;
727 /* special cases */
728 if (str[0] == '\0')
729 return 0;
730
731 if (str[1] == '\0')
732 return 1;
733
734 if (str[2] == '\0')
735 return 2;
736
737 if (str[3] == '\0')
738 return 3;
739
740 len = eina_share_common_length(stringshare_share, (const char *)str);
741 len = (len > 0) ? len / (int)sizeof(char) : -1;
742 return len;
743}
744
745EAPI void
746eina_stringshare_dump(void)
747{
748 eina_share_common_dump(stringshare_share,
749 _eina_stringshare_small_dump,
750 sizeof(_eina_stringshare_single));
751}
diff --git a/libraries/eina/src/lib/eina_tiler.c b/libraries/eina/src/lib/eina_tiler.c
new file mode 100644
index 0000000..69b944e
--- /dev/null
+++ b/libraries/eina/src/lib/eina_tiler.c
@@ -0,0 +1,1276 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Gustavo Sverzut Barbieri, 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/* TODO
20 * it is possible to have more than one tiler algorithm, but for now the
21 * version Gustavo did is hardcoded here
22 * http://blog.gustavobarbieri.com.br/2007/06/03/evas-now-using-rectangle-split-and-merge/
23 */
24
25#ifdef HAVE_CONFIG_H
26# include "config.h"
27#endif
28
29#include <stdlib.h>
30#include <stdio.h>
31
32#include "eina_config.h"
33#include "eina_private.h"
34#include "eina_tiler.h"
35#include "eina_error.h"
36
37/*============================================================================*
38* Local *
39*============================================================================*/
40
41/* The splitter data types */
42typedef struct list_node list_node_t;
43typedef struct list list_t;
44typedef struct rect rect_t;
45typedef struct rect_node rect_node_t;
46
47struct list_node
48{
49 struct list_node *next;
50};
51
52struct list
53{
54 struct list_node *head;
55 struct list_node *tail;
56};
57
58struct rect
59{
60 short right;
61 short bottom;
62 short left;
63 short top;
64 short width;
65 short height;
66 int area;
67};
68
69struct rect_node
70{
71 struct list_node _lst;
72 struct rect rect;
73};
74
75typedef struct splitter
76{
77 Eina_Bool need_merge;
78 list_t rects;
79} splitter_t;
80
81typedef struct list_node_pool
82{
83 list_node_t *node;
84 int len;
85 int max;
86} list_node_pool_t;
87
88
89static const list_node_t list_node_zeroed = { NULL };
90static const list_t list_zeroed = { NULL, NULL };
91static list_node_pool_t list_node_pool = { NULL, 0, 1024 };
92
93
94typedef struct _Eina_Iterator_Tiler
95{
96 Eina_Iterator iterator;
97 const Eina_Tiler *tiler;
98 list_node_t *curr;
99 Eina_Rectangle r;
100 EINA_MAGIC
101} Eina_Iterator_Tiler;
102
103struct _Eina_Tiler
104{
105 struct
106 {
107 int w, h;
108 } tile;
109 Eina_Rectangle area;
110 EINA_MAGIC
111 splitter_t splitter;
112};
113
114#define EINA_MAGIC_CHECK_TILER(d, ...) \
115 do { \
116 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_TILER)) \
117 { \
118 EINA_MAGIC_FAIL(d, EINA_MAGIC_TILER); \
119 return __VA_ARGS__; \
120 } \
121 } while(0)
122
123
124#define EINA_MAGIC_CHECK_TILER_ITERATOR(d, ...) \
125 do { \
126 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_TILER_ITERATOR)) \
127 { \
128 EINA_MAGIC_FAIL(d, EINA_MAGIC_TILER_ITERATOR); \
129 return __VA_ARGS__; \
130 } \
131 } while(0)
132
133/* The Splitter algorithm */
134static inline void rect_init(rect_t *r, int x, int y, int w, int h)
135{
136 r->area = w * h;
137
138 r->left = x;
139 r->top = y;
140
141 r->right = x + w;
142 r->bottom = y + h;
143
144 r->width = w;
145 r->height = h;
146}
147
148static inline list_node_t *
149rect_list_node_pool_get(void)
150{
151 if (list_node_pool.node)
152 {
153 list_node_t *node;
154
155 node = list_node_pool.node;
156 list_node_pool.node = node->next;
157 list_node_pool.len--;
158
159 return node;
160 }
161 else
162 return malloc(sizeof(rect_node_t));
163}
164
165
166static inline void rect_list_concat(list_t *rects, list_t *other)
167{
168 if (!other->head)
169 return;
170
171 if (rects->tail)
172 {
173 rects->tail->next = other->head;
174 rects->tail = other->tail;
175 }
176 else
177 {
178 rects->head = other->head;
179 rects->tail = other->tail;
180 }
181
182 *other = list_zeroed;
183}
184
185static inline void rect_list_append_node(list_t *rects, list_node_t *node)
186{
187 if (rects->tail)
188 {
189 rects->tail->next = node;
190 rects->tail = node;
191 }
192 else
193 {
194 rects->head = node;
195 rects->tail = node;
196 }
197}
198
199static inline void rect_list_append(list_t *rects, const rect_t r)
200{
201 rect_node_t *rect_node;
202
203 rect_node = (rect_node_t *)rect_list_node_pool_get();
204 rect_node->rect = r;
205 rect_node->_lst = list_node_zeroed;
206
207 rect_list_append_node(rects, (list_node_t *)rect_node);
208}
209
210static inline void rect_list_append_xywh(list_t *rects,
211 int x,
212 int y,
213 int w,
214 int h)
215{
216 rect_t r;
217
218 rect_init(&r, x, y, w, h);
219 rect_list_append(rects, r);
220}
221
222static inline void _calc_intra_rect_area(const rect_t a, const rect_t b,
223 int *width, int *height)
224{
225 int max_left, min_right, max_top, min_bottom;
226
227 if (a.left < b.left)
228 max_left = b.left;
229 else
230 max_left = a.left;
231
232 if (a.right < b.right)
233 min_right = a.right;
234 else
235 min_right = b.right;
236
237 *width = min_right - max_left;
238
239 if (a.top < b.top)
240 max_top = b.top;
241 else
242 max_top = a.top;
243
244 if (a.bottom < b.bottom)
245 min_bottom = a.bottom;
246 else
247 min_bottom = b.bottom;
248
249 *height = min_bottom - max_top;
250}
251
252static inline void _split_strict(list_t *dirty, const rect_t current, rect_t r)
253{
254 int h_1, h_2, w_1, w_2;
255
256 h_1 = current.top - r.top;
257 h_2 = r.bottom - current.bottom;
258 w_1 = current.left - r.left;
259 w_2 = r.right - current.right;
260
261 if (h_1 > 0)
262 {
263 /* .--.r (b) .---.r2
264 * | | | |
265 * .-------.cur (a) .---.r '---'
266 * | | | | -> | | +
267 * | `--' | `---'
268 * `-------'
269 */
270 rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1);
271 r.height -= h_1;
272 r.top = current.top;
273 }
274
275 if (h_2 > 0)
276 {
277 /* .-------.cur (a)
278 * | .---. | .---.r
279 * | | | | -> | |
280 * `-------' `---' + .---.r2
281 * | | | |
282 * `---'r (b) `---'
283 */
284 rect_list_append_xywh(dirty, r.left, current.bottom, r.width,
285 h_2);
286 r.height -= h_2;
287 }
288
289 if (w_1 > 0)
290 /* (b) r .----.cur (a)
291 * .--|-. | .--.r2 .-.r
292 * | | | | -> | | + | |
293 * `--|-' | `--' `-'
294 * `----'
295 */
296 rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height); /* not necessary to keep these, r (b) will be destroyed */
297
298 /* r.width -= w_1; */
299 /* r.left = current.left; */
300
301 if (w_2 > 0)
302 /* .----.cur (a)
303 * | |
304 * | .-|--.r (b) .-.r .--.r2
305 * | | | | -> | | + | |
306 * | `-|--' `-' `--'
307 * `----'
308 */
309 rect_list_append_xywh(dirty, current.right, r.top, w_2,
310 r.height); /* not necessary to keep this, r (b) will be destroyed */
311
312 /* r.width -= w_2; */
313}
314
315static inline void _calc_intra_outer_rect_area(const rect_t a, const rect_t b,
316 rect_t *intra, rect_t *outer)
317{
318 int min_left, max_left, min_right, max_right;
319 int min_top, max_top, min_bottom, max_bottom;
320
321 if (a.left < b.left)
322 {
323 max_left = b.left;
324 min_left = a.left;
325 }
326 else
327 {
328 max_left = a.left;
329 min_left = b.left;
330 }
331
332 if (a.right < b.right)
333 {
334 min_right = a.right;
335 max_right = b.right;
336 }
337 else
338 {
339 min_right = b.right;
340 max_right = a.right;
341 }
342
343 intra->left = max_left;
344 intra->right = min_right;
345 intra->width = min_right - max_left;
346
347 outer->left = min_left;
348 outer->right = max_right;
349 outer->width = max_right - min_left;
350
351 if (a.top < b.top)
352 {
353 max_top = b.top;
354 min_top = a.top;
355 }
356 else
357 {
358 max_top = a.top;
359 min_top = b.top;
360 }
361
362 if (a.bottom < b.bottom)
363 {
364 min_bottom = a.bottom;
365 max_bottom = b.bottom;
366 }
367 else
368 {
369 min_bottom = b.bottom;
370 max_bottom = a.bottom;
371 }
372
373 intra->top = max_top;
374 intra->bottom = min_bottom;
375 intra->height = min_bottom - max_top;
376 if ((intra->width > 0) && (intra->height > 0))
377 intra->area = intra->width * intra->height;
378 else
379 intra->area = 0;
380
381 outer->top = min_top;
382 outer->bottom = max_bottom;
383 outer->height = max_bottom - min_top;
384 outer->area = outer->width * outer->height;
385}
386
387enum
388{
389 SPLIT_FUZZY_ACTION_NONE,
390 SPLIT_FUZZY_ACTION_SPLIT,
391 SPLIT_FUZZY_ACTION_MERGE
392};
393
394static inline int _split_fuzzy(list_t *dirty, const rect_t a, rect_t *b)
395{
396 int h_1, h_2, w_1, w_2, action;
397
398 h_1 = a.top - b->top;
399 h_2 = b->bottom - a.bottom;
400 w_1 = a.left - b->left;
401 w_2 = b->right - a.right;
402
403 action = SPLIT_FUZZY_ACTION_NONE;
404
405 if (h_1 > 0)
406 {
407 /* .--.r (b) .---.r2
408 * | | | |
409 * .-------.cur (a) .---.r '---'
410 * | | | | -> | | +
411 * | `--' | `---'
412 * `-------'
413 */
414 rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1);
415 b->height -= h_1;
416 b->top = a.top;
417 action = SPLIT_FUZZY_ACTION_SPLIT;
418 }
419
420 if (h_2 > 0)
421 {
422 /* .-------.cur (a)
423 * | .---. | .---.r
424 * | | | | -> | |
425 * `-------' `---' + .---.r2
426 * | | | |
427 * `---'r (b) `---'
428 */
429 rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2);
430 b->height -= h_2;
431 action = SPLIT_FUZZY_ACTION_SPLIT;
432 }
433
434 if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height))
435 return SPLIT_FUZZY_ACTION_MERGE;
436
437 if (w_1 > 0)
438 {
439 /* (b) r .----.cur (a)
440 * .--|-. | .--.r2 .-.r
441 * | | | | -> | | + | |
442 * `--|-' | `--' `-'
443 * `----'
444 */
445 rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height);
446 /* not necessary to keep these, r (b) will be destroyed */
447 /* b->width -= w_1; */
448 /* b->left = a.left; */
449 action = SPLIT_FUZZY_ACTION_SPLIT;
450 }
451
452 if (w_2 > 0)
453 {
454 /* .----.cur (a)
455 * | |
456 * | .-|--.r (b) .-.r .--.r2
457 * | | | | -> | | + | |
458 * | `-|--' `-' `--'
459 * `----'
460 */
461 rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height);
462 /* not necessary to keep these, r (b) will be destroyed */
463 /* b->width -= w_2; */
464 action = SPLIT_FUZZY_ACTION_SPLIT;
465 }
466
467 return action;
468}
469
470#if 0
471static void rect_list_node_pool_set_max(int max)
472{
473 int diff;
474
475 diff = list_node_pool.len - max;
476 for (; diff > 0 && list_node_pool.node != NULL; diff--)
477 {
478 list_node_t *node;
479
480 node = list_node_pool.node;
481 list_node_pool.node = node->next;
482 list_node_pool.len--;
483
484 free(node);
485 }
486
487 list_node_pool.max = max;
488}
489#endif
490
491static void rect_list_node_pool_flush(void)
492{
493 while (list_node_pool.node)
494 {
495 list_node_t *node;
496
497 node = list_node_pool.node;
498 list_node_pool.node = node->next;
499 list_node_pool.len--;
500
501 free(node);
502 }
503}
504
505
506
507static inline void rect_list_node_pool_put(list_node_t *node)
508{
509 if (list_node_pool.len < list_node_pool.max)
510 {
511 node->next = list_node_pool.node;
512 list_node_pool.node = node;
513 list_node_pool.len++;
514 }
515 else
516 free(node);
517}
518
519#if 0
520static void rect_print(const rect_t r)
521{
522 printf("<rect(%d, %d, %d, %d)>", r.left, r.top, r.width, r.height);
523}
524
525static void rect_list_print(const list_t rects)
526{
527 list_node_t *node;
528 int len;
529
530 len = 0;
531 for (node = rects.head; node != NULL; node = node->next)
532 len++;
533
534 printf("[");
535 for (node = rects.head; node != NULL; node = node->next)
536 {
537 rect_print(((rect_node_t *)node)->rect);
538 if (node->next)
539 {
540 putchar(',');
541 if (len < 4)
542 putchar(' ');
543 else
544 {
545 putchar('\n');
546 putchar(' ');
547 }
548 }
549 }
550 printf("]\n");
551}
552#endif
553
554static inline list_node_t *
555rect_list_unlink_next(list_t *rects, list_node_t *parent_node)
556{
557 list_node_t *node;
558
559 if (parent_node)
560 {
561 node = parent_node->next;
562 parent_node->next = node->next;
563 }
564 else
565 {
566 node = rects->head;
567 rects->head = node->next;
568 }
569
570 if (rects->tail == node)
571 rects->tail = parent_node;
572
573 *node = list_node_zeroed;
574 return node;
575}
576
577static inline void rect_list_del_next(list_t *rects, list_node_t *parent_node)
578{
579 list_node_t *node;
580
581 node = rect_list_unlink_next(rects, parent_node);
582 rect_list_node_pool_put(node);
583}
584
585static void rect_list_clear(list_t *rects)
586{
587 list_node_t *node;
588
589 node = rects->head;
590 while (node)
591 {
592 list_node_t *aux;
593
594 aux = node->next;
595 rect_list_node_pool_put(node);
596 node = aux;
597 }
598 *rects = list_zeroed;
599}
600
601static void rect_list_del_split_strict(list_t *rects, const rect_t del_r)
602{
603 list_t modified = list_zeroed;
604 list_node_t *cur_node, *prev_node;
605
606 prev_node = NULL;
607 cur_node = rects->head;
608 while (cur_node)
609 {
610 int intra_width, intra_height;
611 rect_t current;
612
613 current = ((rect_node_t *)cur_node)->rect;
614
615 _calc_intra_rect_area(del_r, current, &intra_width,
616 &intra_height);
617 if ((intra_width <= 0) || (intra_height <= 0))
618 {
619 /* .---.current .---.del_r
620 * | | | |
621 * `---+---.del_r `---+---.current
622 * | | | |
623 * `---' `---'
624 * no intersection, nothing to do
625 */
626 prev_node = cur_node;
627 cur_node = cur_node->next;
628 }
629 else if ((intra_width == current.width) && (intra_height
630 == current.height))
631 {
632 /* .-------.del_r
633 * | .---. |
634 * | | | |
635 * | `---'current
636 * `-------'
637 * current is contained, remove from rects
638 */
639 cur_node = cur_node->next;
640 rect_list_del_next(rects, prev_node);
641 }
642 else
643 {
644 _split_strict(&modified, del_r, current);
645 cur_node = cur_node->next;
646 rect_list_del_next(rects, prev_node);
647 }
648 }
649
650 rect_list_concat(rects, &modified);
651}
652
653#if 0
654static void rect_list_add_split_strict(list_t *rects, list_node_t *node)
655{
656 list_t dirty = list_zeroed;
657 list_t new_dirty = list_zeroed;
658 list_node_t *cur_node;
659
660 if (!rects->head)
661 {
662 rect_list_append_node(rects, node);
663 return;
664 }
665
666 rect_list_append_node(&dirty, node);
667
668 cur_node = rects->head;
669 while (dirty.head)
670 {
671 rect_t current;
672
673 if (!cur_node)
674 {
675 rect_list_concat(rects, &dirty);
676 break;
677 }
678
679 current = ((rect_node_t *)cur_node)->rect;
680
681 while (dirty.head)
682 {
683 int intra_width, intra_height;
684 rect_t r;
685
686 r = ((rect_node_t *)dirty.head)->rect;
687 _calc_intra_rect_area(r, current, &intra_width,
688 &intra_height);
689 if ((intra_width == r.width) && (intra_height
690 == r.height))
691 /* .-------.cur
692 * | .---.r|
693 * | | | |
694 * | `---' |
695 * `-------'
696 */
697 rect_list_del_next(&dirty, NULL);
698 else if ((intra_width <= 0) || (intra_height <= 0))
699 {
700 /* .---.cur .---.r
701 * | | | |
702 * `---+---.r `---+---.cur
703 * | | | |
704 * `---' `---'
705 */
706 list_node_t *tmp;
707 tmp = rect_list_unlink_next(&dirty, NULL);
708 rect_list_append_node(&new_dirty, tmp);
709 }
710 else
711 {
712 _split_strict(&new_dirty, current, r);
713 rect_list_del_next(&dirty, NULL);
714 }
715 }
716 dirty = new_dirty;
717 new_dirty = list_zeroed;
718
719 cur_node = cur_node->next;
720 }
721}
722#endif
723
724static list_node_t *
725rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error)
726{
727 list_t dirty = list_zeroed;
728 list_node_t *old_last;
729
730 old_last = rects->tail;
731
732 if (!rects->head)
733 {
734 rect_list_append_node(rects, node);
735 return old_last;
736 }
737
738 rect_list_append_node(&dirty, node);
739 while (dirty.head)
740 {
741 list_node_t *d_node, *cur_node, *prev_cur_node;
742 int keep_dirty;
743 rect_t r;
744
745 d_node = rect_list_unlink_next(&dirty, NULL);
746 r = ((rect_node_t *)d_node)->rect;
747
748 prev_cur_node = NULL;
749 cur_node = rects->head;
750 keep_dirty = 1;
751 while (cur_node)
752 {
753 int area, action;
754 rect_t current, intra, outer;
755
756 current = ((rect_node_t *)cur_node)->rect;
757
758 _calc_intra_outer_rect_area(r, current, &intra, &outer);
759 area = current.area + r.area - intra.area;
760
761 if ((intra.width == r.width) && (intra.height
762 == r.height))
763 {
764 /* .-------.cur
765 * | .---.r|
766 * | | | |
767 * | `---' |
768 * `-------'
769 */
770 keep_dirty = 0;
771 break;
772 }
773 else if ((intra.width == current.width)
774 && (intra.height == current.height))
775 {
776 /* .-------.r
777 * | .---.cur
778 * | | | |
779 * | `---' |
780 * `-------'
781 */
782 if (old_last == cur_node)
783 old_last = prev_cur_node;
784
785 cur_node = cur_node->next;
786 rect_list_del_next(rects, prev_cur_node);
787 }
788 else if ((outer.area - area) <= accepted_error)
789 {
790 /* .-----------. bounding box (outer)
791 * |.---. .---.|
792 * ||cur| |r ||
793 * || | | ||
794 * |`---' `---'|
795 * `-----------'
796 * merge them, remove both and add merged
797 */
798 rect_node_t *n;
799
800 if (old_last == cur_node)
801 old_last = prev_cur_node;
802
803 n = (rect_node_t *)rect_list_unlink_next(
804 rects, prev_cur_node);
805 n->rect = outer;
806 rect_list_append_node(&dirty, (list_node_t *)n);
807
808 keep_dirty = 0;
809 break;
810 }
811 else if (intra.area <= accepted_error)
812 {
813 /* .---.cur .---.r
814 * | | | |
815 * `---+---.r `---+---.cur
816 * | | | |
817 * `---' `---'
818 * no split, no merge
819 */
820 prev_cur_node = cur_node;
821 cur_node = cur_node->next;
822 }
823 else
824 {
825 /* split is required */
826 action = _split_fuzzy(&dirty, current, &r);
827 if (action == SPLIT_FUZZY_ACTION_MERGE)
828 {
829/* horizontal merge is possible: remove both, add merged */
830 rect_node_t *n;
831
832 if (old_last == cur_node)
833 old_last = prev_cur_node;
834
835 n
836 = (rect_node_t *)rect_list_unlink_next(
837 rects,
838 prev_cur_node);
839
840 n->rect.left = outer.left;
841 n->rect.width = outer.width;
842 n->rect.right = outer.right;
843 n->rect.area = outer.width * r.height;
844 rect_list_append_node(&dirty,
845 (list_node_t *)n);
846 }
847 else if (action == SPLIT_FUZZY_ACTION_NONE)
848 {
849/*
850 * this rect check was totally useless,
851 * should never happen
852 */
853/* prev_cur_node = cur_node; */
854/* cur_node = cur_node->next; */
855 printf("Should not get here!\n");
856 abort();
857 }
858
859 keep_dirty = 0;
860 break;
861 }
862 }
863 if (EINA_UNLIKELY(keep_dirty))
864 rect_list_append_node(rects, d_node);
865 else
866 rect_list_node_pool_put(d_node);
867 }
868
869 return old_last;
870}
871
872static inline void _calc_outer_rect_area(const rect_t a, const rect_t b,
873 rect_t *outer)
874{
875 int min_left, max_right;
876 int min_top, max_bottom;
877
878 if (a.left < b.left)
879 min_left = a.left;
880 else
881 min_left = b.left;
882
883 if (a.right < b.right)
884 max_right = b.right;
885 else
886 max_right = a.right;
887
888 outer->left = min_left;
889 outer->right = max_right;
890 outer->width = max_right - min_left;
891
892 if (a.top < b.top)
893 min_top = a.top;
894 else
895 min_top = b.top;
896
897 if (a.bottom < b.bottom)
898 max_bottom = b.bottom;
899 else
900 max_bottom = a.bottom;
901
902 outer->top = min_top;
903 outer->bottom = max_bottom;
904 outer->height = max_bottom - min_top;
905
906 outer->area = outer->width * outer->height;
907}
908
909static void rect_list_merge_rects(list_t *rects,
910 list_t *to_merge,
911 int accepted_error)
912{
913 while (to_merge->head)
914 {
915 list_node_t *node, *parent_node;
916 rect_t r1;
917 int merged;
918
919 r1 = ((rect_node_t *)to_merge->head)->rect;
920
921 merged = 0;
922 parent_node = NULL;
923 node = rects->head;
924 while (node)
925 {
926 rect_t r2, outer;
927 int area;
928
929 r2 = ((rect_node_t *)node)->rect;
930
931 _calc_outer_rect_area(r1, r2, &outer);
932 area = r1.area + r2.area; /* intra area is taken as 0 */
933 if (outer.area - area <= accepted_error)
934 {
935 /*
936 * remove both r1 and r2, create r3
937 * actually r3 uses r2 instance, saves memory
938 */
939 rect_node_t *n;
940
941 n = (rect_node_t *)rect_list_unlink_next(
942 rects, parent_node);
943 n->rect = outer;
944 rect_list_append_node(to_merge,
945 (list_node_t *)n);
946 merged = 1;
947 break;
948 }
949
950 parent_node = node;
951 node = node->next;
952 }
953
954 if (!merged)
955 {
956 list_node_t *n;
957 n = rect_list_unlink_next(to_merge, NULL);
958 rect_list_append_node(rects, n);
959 }
960 else
961 rect_list_del_next(to_merge, NULL);
962 }
963}
964
965static void rect_list_add_split_fuzzy_and_merge(list_t *rects,
966 list_node_t *node,
967 int split_accepted_error,
968 int merge_accepted_error)
969{
970 list_node_t *n;
971
972 n = rect_list_add_split_fuzzy(rects, node, split_accepted_error);
973 if (n && n->next)
974 {
975 list_t to_merge;
976
977 /* split list into 2 segments, already merged and to merge */
978 to_merge.head = n->next;
979 to_merge.tail = rects->tail;
980 rects->tail = n;
981 n->next = NULL;
982
983 rect_list_merge_rects(rects, &to_merge, merge_accepted_error);
984 }
985}
986
987static inline void _splitter_new(Eina_Tiler *t)
988{
989 t->splitter.rects = list_zeroed;
990 t->splitter.need_merge = EINA_FALSE;
991}
992
993static inline void _splitter_del(Eina_Tiler *t)
994{
995 rect_list_clear(&t->splitter.rects);
996 rect_list_node_pool_flush();
997}
998
999static inline void _splitter_tile_size_set(Eina_Tiler *t,
1000 int w __UNUSED__,
1001 int h __UNUSED__)
1002{
1003 /* TODO are w and h used for something? */
1004 t->splitter.rects = list_zeroed;
1005}
1006
1007static inline Eina_Bool _splitter_rect_add(Eina_Tiler *t, Eina_Rectangle *rect)
1008{
1009 rect_node_t *rn;
1010
1011 //printf("ACCOUNTING[1]: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h);
1012 rect->x >>= 1;
1013 rect->y >>= 1;
1014 rect->w += 2;
1015 rect->w >>= 1;
1016 rect->h += 2;
1017 rect->h >>= 1;
1018
1019 rn = (rect_node_t *)rect_list_node_pool_get();
1020 rn->_lst = list_node_zeroed;
1021 rect_init(&rn->rect, rect->x, rect->y, rect->w, rect->h);
1022 //printf("ACCOUNTING[2]: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h);
1023 //testing on my core2 duo desktop - fuzz of 32 or 48 is best.
1024#define FUZZ 32
1025 rect_list_add_split_fuzzy_and_merge(&t->splitter.rects,
1026 (list_node_t *)rn,
1027 FUZZ * FUZZ,
1028 FUZZ * FUZZ);
1029 return EINA_TRUE;
1030}
1031
1032static inline void _splitter_rect_del(Eina_Tiler *t, Eina_Rectangle *rect)
1033{
1034 rect_t r;
1035
1036 if (!t->splitter.rects.head)
1037 return;
1038
1039 rect->x += 1;
1040 rect->y += 1;
1041 rect->x >>= 1;
1042 rect->y >>= 1;
1043 rect->w -= 1;
1044 rect->w >>= 1;
1045 rect->h -= 1;
1046 rect->h >>= 1;
1047
1048 if ((rect->w <= 0) || (rect->h <= 0))
1049 return;
1050
1051 rect_init(&r, rect->x, rect->y, rect->w, rect->h);
1052 //fprintf(stderr, "ACCOUNTING: del_redraw: %4d,%4d %3dx%3d\n", x, y, w, h);
1053
1054 rect_list_del_split_strict(&t->splitter.rects, r);
1055 t->splitter.need_merge = EINA_TRUE;
1056 return;
1057}
1058
1059static inline void _splitter_clear(Eina_Tiler *t)
1060{
1061 rect_list_clear(&t->splitter.rects);
1062 t->splitter.need_merge = EINA_FALSE;
1063}
1064/* end of splitter algorithm */
1065
1066static Eina_Bool _iterator_next(Eina_Iterator_Tiler *it, void **data)
1067{
1068 list_node_t *n;
1069
1070 for (n = it->curr; n; n = n->next)
1071 {
1072 rect_t cur;
1073
1074 cur = ((rect_node_t *)n)->rect;
1075
1076 it->r.x = cur.left << 1;
1077 it->r.y = cur.top << 1;
1078 it->r.w = cur.width << 1;
1079 it->r.h = cur.height << 1;
1080
1081 if (eina_rectangle_intersection(&it->r, &it->tiler->area) == EINA_FALSE)
1082 continue;
1083
1084 if ((it->r.w <= 0) || (it->r.h <= 0))
1085 continue;
1086
1087 it->curr = n->next;
1088 *(Eina_Rectangle **)data = &it->r;
1089 return EINA_TRUE;
1090 }
1091 return EINA_FALSE;
1092}
1093
1094static void *_iterator_get_container(Eina_Iterator_Tiler *it)
1095{
1096 EINA_MAGIC_CHECK_TILER_ITERATOR(it, NULL);
1097 return (void *)it->tiler;
1098}
1099
1100static void _iterator_free(Eina_Iterator_Tiler *it)
1101{
1102 EINA_MAGIC_CHECK_TILER_ITERATOR(it);
1103 free(it);
1104}
1105
1106/*============================================================================*
1107* Global *
1108*============================================================================*/
1109
1110/*============================================================================*
1111* API *
1112*============================================================================*/
1113
1114EAPI Eina_Tiler *eina_tiler_new(int w, int h)
1115{
1116 Eina_Tiler *t;
1117
1118 t = calloc(1, sizeof(Eina_Tiler));
1119 t->area.w = w;
1120 t->area.h = h;
1121 t->tile.w = w;
1122 t->tile.h = h;
1123 EINA_MAGIC_SET(t, EINA_MAGIC_TILER);
1124 _splitter_new(t);
1125 return t;
1126}
1127
1128EAPI void eina_tiler_free(Eina_Tiler *t)
1129{
1130 EINA_MAGIC_CHECK_TILER(t);
1131 _splitter_del(t);
1132 free(t);
1133}
1134
1135EAPI void eina_tiler_tile_size_set(Eina_Tiler *t, int w, int h)
1136{
1137 EINA_MAGIC_CHECK_TILER(t);
1138 if ((w <= 0) || (h <= 0))
1139 return;
1140
1141 t->tile.w = w;
1142 t->tile.h = h;
1143 _splitter_tile_size_set(t, w, h);
1144}
1145
1146EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r)
1147{
1148 Eina_Rectangle tmp;
1149
1150 EINA_MAGIC_CHECK_TILER(t, EINA_FALSE);
1151 if ((r->w <= 0) || (r->h <= 0))
1152 return EINA_FALSE;
1153
1154 tmp = *r;
1155 if (eina_rectangle_intersection(&tmp, &t->area) == EINA_FALSE)
1156 return EINA_FALSE;
1157
1158 if ((tmp.w <= 0) || (tmp.h <= 0))
1159 return EINA_FALSE;
1160
1161 return _splitter_rect_add(t, &tmp);
1162}
1163
1164EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r)
1165{
1166 Eina_Rectangle tmp;
1167
1168 EINA_MAGIC_CHECK_TILER(t);
1169 if ((r->w <= 0) || (r->h <= 0))
1170 return;
1171
1172 tmp = *r;
1173 if (eina_rectangle_intersection(&tmp, &t->area) == EINA_FALSE)
1174 return;
1175
1176 if ((tmp.w <= 0) || (tmp.h <= 0))
1177 return;
1178
1179 _splitter_rect_del(t, &tmp);
1180}
1181
1182EAPI void eina_tiler_clear(Eina_Tiler *t)
1183{
1184 EINA_MAGIC_CHECK_TILER(t);
1185 _splitter_clear(t);
1186}
1187
1188
1189EAPI Eina_Iterator *eina_tiler_iterator_new(const Eina_Tiler *t)
1190{
1191 Eina_Iterator_Tiler *it;
1192
1193 EINA_MAGIC_CHECK_TILER(t, NULL);
1194
1195 it = calloc(1, sizeof (Eina_Iterator_Tiler));
1196 if (!it)
1197 return NULL;
1198
1199 it->tiler = t;
1200
1201 if (t->splitter.need_merge == EINA_TRUE)
1202 {
1203 list_t to_merge;
1204 splitter_t *sp;
1205
1206 sp = (splitter_t *)&(t->splitter);
1207 to_merge = t->splitter.rects;
1208 sp->rects = list_zeroed;
1209 rect_list_merge_rects(&sp->rects, &to_merge, FUZZ * FUZZ);
1210 sp->need_merge = 0;
1211 }
1212
1213 it->curr = it->tiler->splitter.rects.head;
1214
1215 it->iterator.version = EINA_ITERATOR_VERSION;
1216 it->iterator.next = FUNC_ITERATOR_NEXT(_iterator_next);
1217 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1218 _iterator_get_container);
1219 it->iterator.free = FUNC_ITERATOR_FREE(_iterator_free);
1220
1221 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1222 EINA_MAGIC_SET(it, EINA_MAGIC_TILER_ITERATOR);
1223
1224 return &it->iterator;
1225}
1226
1227struct _Eina_Tile_Grid_Slicer_Iterator
1228{
1229 Eina_Iterator iterator;
1230 Eina_Tile_Grid_Slicer priv;
1231};
1232
1233typedef struct _Eina_Tile_Grid_Slicer_Iterator Eina_Tile_Grid_Slicer_Iterator;
1234
1235static void
1236eina_tile_grid_slicer_iterator_free(Eina_Tile_Grid_Slicer_Iterator *it)
1237{
1238 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
1239 free(it);
1240}
1241
1242static Eina_Bool
1243eina_tile_grid_slicer_iterator_next(Eina_Tile_Grid_Slicer_Iterator *it,
1244 void **data)
1245{
1246 return eina_tile_grid_slicer_next
1247 (&it->priv, (const Eina_Tile_Grid_Info **)data);
1248}
1249
1250EAPI Eina_Iterator *
1251eina_tile_grid_slicer_iterator_new(int x,
1252 int y,
1253 int w,
1254 int h,
1255 int tile_w,
1256 int tile_h)
1257{
1258 Eina_Tile_Grid_Slicer_Iterator *it;
1259
1260 it = calloc(1, sizeof(*it));
1261 if (!it)
1262 {
1263 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1264 return NULL;
1265 }
1266
1267 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1268
1269 it->iterator.version = EINA_ITERATOR_VERSION;
1270 it->iterator.next = FUNC_ITERATOR_NEXT(eina_tile_grid_slicer_iterator_next);
1271 it->iterator.free = FUNC_ITERATOR_FREE(eina_tile_grid_slicer_iterator_free);
1272
1273 eina_tile_grid_slicer_setup(&it->priv, x, y, w, h, tile_w, tile_h);
1274
1275 return &it->iterator;
1276}
diff --git a/libraries/eina/src/lib/eina_unicode.c b/libraries/eina/src/lib/eina_unicode.c
new file mode 100644
index 0000000..342e3cb
--- /dev/null
+++ b/libraries/eina/src/lib/eina_unicode.c
@@ -0,0 +1,405 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2010 Tom Hacohen,
3 * Brett Nash
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
21#include <Eina.h>
22#include "eina_unicode.h"
23
24/* FIXME: check if sizeof(wchar_t) == sizeof(Eina_Unicode) if so,
25 * probably better to use the standard functions */
26
27/* Maybe I'm too tired, but this is the only thing that actually worked. */
28const Eina_Unicode _EINA_UNICODE_EMPTY_STRING[1] = {0};
29EAPI const Eina_Unicode *EINA_UNICODE_EMPTY_STRING = _EINA_UNICODE_EMPTY_STRING;
30EAPI int
31eina_unicode_strcmp(const Eina_Unicode *a, const Eina_Unicode *b)
32{
33 for (; *a && *a == *b; a++, b++)
34 ;
35 if (*a == *b)
36 return 0;
37 else if (*a < *b)
38 return -1;
39 else
40 return 1;
41}
42
43EAPI Eina_Unicode *
44eina_unicode_strcpy(Eina_Unicode *dest, const Eina_Unicode *source)
45{
46 Eina_Unicode *ret = dest;
47
48 while (*source)
49 *dest++ = *source++;
50 *dest = 0;
51 return ret;
52}
53
54EAPI Eina_Unicode *
55eina_unicode_strncpy(Eina_Unicode *dest, const Eina_Unicode *source, size_t n)
56{
57 Eina_Unicode *ret = dest;
58
59 for ( ; n && *source ; n--)
60 *dest++ = *source++;
61 for (; n; n--)
62 *dest++ = 0;
63 return ret;
64}
65
66EAPI size_t
67eina_unicode_strlen(const Eina_Unicode *ustr)
68{
69 const Eina_Unicode *end;
70 for (end = ustr; *end; end++)
71 ;
72 return end - ustr;
73}
74
75EAPI size_t
76eina_unicode_strnlen(const Eina_Unicode *ustr, int n)
77{
78 const Eina_Unicode *end;
79 const Eina_Unicode *last = ustr + n; /* technically not portable ;-) */
80 for (end = ustr; end < last && *end; end++)
81 ;
82 return end - ustr;
83}
84
85
86
87
88EAPI Eina_Unicode *
89eina_unicode_strndup(const Eina_Unicode *text, size_t n)
90{
91 Eina_Unicode *ustr;
92
93 ustr = (Eina_Unicode *) malloc((n + 1) * sizeof(Eina_Unicode));
94 memcpy(ustr, text, n * sizeof(Eina_Unicode));
95 ustr[n] = 0;
96 return ustr;
97}
98
99EAPI Eina_Unicode *
100eina_unicode_strdup(const Eina_Unicode *text)
101{
102 size_t len;
103
104 len = eina_unicode_strlen(text);
105 return eina_unicode_strndup(text, len);
106}
107
108EAPI Eina_Unicode *
109eina_unicode_strstr(const Eina_Unicode *haystack, const Eina_Unicode *needle)
110{
111 const Eina_Unicode *i, *j;
112
113 for (i = haystack; *i; i++)
114 {
115 haystack = i; /* set this location as the base position */
116 for (j = needle; *j && *i && *j == *i; j++, i++)
117 ;
118
119 if (!*j) /*if we got to the end of j this means we got a full match */
120 {
121 return (Eina_Unicode *)haystack; /* return the new base position */
122 }
123 }
124
125 return NULL;
126}
127
128EAPI Eina_Unicode *
129eina_unicode_escape(const Eina_Unicode *str)
130{
131 Eina_Unicode *s2, *d;
132 const Eina_Unicode *s;
133
134 s2 = malloc((eina_unicode_strlen(str) * 2) + 1);
135 if (!s2)
136 return NULL;
137
138 for (s = str, d = s2; *s != 0; s++, d++)
139 {
140 if ((*s == ' ') || (*s == '\\') || (*s == '\''))
141 {
142 *d = '\\';
143 d++;
144 }
145
146 *d = *s;
147 }
148 *d = 0;
149 return s2;
150}
151
152/* UTF-8 Handling */
153
154#define EINA_UNICODE_UTF8_BYTES_PER_CHAR 6
155/* The replacement range that will be used for bad utf8 chars. */
156#define ERROR_REPLACEMENT_BASE 0xDC80
157#define ERROR_REPLACEMENT_END 0xDCFF
158#define IS_INVALID_BYTE(x) ((x == 192) || (x == 193) || (x >= 245))
159#define IS_CONTINUATION_BYTE(x) ((x & 0xC0) == 0x80)
160
161EAPI Eina_Unicode
162eina_unicode_utf8_get_next(const char *buf, int *iindex)
163{
164 int ind = *iindex;
165 Eina_Unicode r;
166 unsigned char d;
167
168 /* if this char is the null terminator, exit */
169 if ((d = buf[ind++]) == 0) return 0;
170
171 if ((d & 0x80) == 0)
172 { // 1 byte (7bit) - 0xxxxxxx
173 *iindex = ind;
174 return d;
175 }
176 if ((d & 0xe0) == 0xc0)
177 { // 2 byte (11bit) - 110xxxxx 10xxxxxx
178 r = (d & 0x1f) << 6;
179 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
180 !IS_CONTINUATION_BYTE(d)) goto error;
181 r |= (d & 0x3f);
182 if (r <= 0x7F) goto error;
183 *iindex = ind;
184 return r;
185 }
186 if ((d & 0xf0) == 0xe0)
187 { // 3 byte (16bit) - 1110xxxx 10xxxxxx 10xxxxxx
188 r = (d & 0x0f) << 12;
189 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
190 !IS_CONTINUATION_BYTE(d)) goto error;
191 r |= (d & 0x3f) << 6;
192 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
193 !IS_CONTINUATION_BYTE(d)) goto error;
194 r |= (d & 0x3f);
195 if (r <= 0x7FF) goto error;
196 *iindex = ind;
197 return r;
198 }
199 if ((d & 0xf8) == 0xf0)
200 { // 4 byte (21bit) - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
201 r = (d & 0x07) << 18;
202 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
203 !IS_CONTINUATION_BYTE(d)) goto error;
204 r |= (d & 0x3f) << 12;
205 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
206 !IS_CONTINUATION_BYTE(d)) goto error;
207 r |= (d & 0x3f) << 6;
208 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
209 !IS_CONTINUATION_BYTE(d)) goto error;
210 r |= (d & 0x3f);
211 if (r <= 0xFFFF) goto error;
212 *iindex = ind;
213 return r;
214 }
215 if ((d & 0xfc) == 0xf8)
216 { // 5 byte (26bit) - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
217 r = (d & 0x03) << 24;
218 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
219 !IS_CONTINUATION_BYTE(d)) goto error;
220 r |= (d & 0x3f) << 18;
221 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
222 !IS_CONTINUATION_BYTE(d)) goto error;
223 r |= (d & 0x3f) << 12;
224 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
225 !IS_CONTINUATION_BYTE(d)) goto error;
226 r |= (d & 0x3f) << 6;
227 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
228 !IS_CONTINUATION_BYTE(d)) goto error;
229 r |= (d & 0x3f);
230 if (r <= 0x1FFFFF) goto error;
231 *iindex = ind;
232 return r;
233 }
234 if ((d & 0xfe) == 0xfc)
235 { // 6 byte (31bit) - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
236 r = (d & 0x01) << 30;
237 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
238 !IS_CONTINUATION_BYTE(d)) goto error;
239 r |= (d & 0x3f) << 24;
240 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
241 !IS_CONTINUATION_BYTE(d)) goto error;
242 r |= (d & 0x3f) << 18;
243 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
244 !IS_CONTINUATION_BYTE(d)) goto error;
245 r |= (d & 0x3f) << 12;
246 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
247 !IS_CONTINUATION_BYTE(d)) goto error;
248 r |= (d & 0x3f) << 6;
249 if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) ||
250 !IS_CONTINUATION_BYTE(d)) goto error;
251 r |= (d & 0x3f);
252 if (r <= 0x3FFFFFF) goto error;
253 *iindex = ind;
254 return r;
255 }
256
257/* Gets here where there was an error and we want to replace the char
258 * we just use the invalid unicode codepoints 8 lower bits represent
259 * the original char */
260error:
261 d = buf[*iindex];
262 (*iindex)++;
263 return ERROR_REPLACEMENT_BASE | d;
264}
265
266EAPI Eina_Unicode
267eina_unicode_utf8_get_prev(const char *buf, int *iindex)
268{
269 int r;
270 int ind = *iindex;
271 /* First obtain the codepoint at iindex */
272 r = eina_unicode_utf8_get_next(buf, &ind);
273
274 /* although when ind == 0 there's no previous char, we still want to get
275 * the current char */
276 if (*iindex <= 0)
277 return r;
278
279 /* Next advance iindex to previous codepoint */
280 ind = *iindex;
281 ind--;
282 while ((ind > 0) && ((buf[ind] & 0xc0) == 0x80))
283 ind--;
284
285 *iindex = ind;
286 return r;
287}
288
289EAPI int
290eina_unicode_utf8_get_len(const char *buf)
291{
292 /* returns the number of utf8 characters (not bytes) in the string */
293 int i = 0, len = 0;
294
295 while (eina_unicode_utf8_get_next(buf, &i))
296 len++;
297
298 return len;
299}
300
301EAPI Eina_Unicode *
302eina_unicode_utf8_to_unicode(const char *utf, int *_len)
303{
304 /* FIXME: Should optimize! */
305 int len, i;
306 int ind;
307 Eina_Unicode *buf, *uind;
308
309 len = eina_unicode_utf8_get_len(utf);
310 if (_len)
311 *_len = len;
312 buf = (Eina_Unicode *) calloc(sizeof(Eina_Unicode), (len + 1));
313 if (!buf) return buf;
314
315 for (i = 0, ind = 0, uind = buf ; i < len ; i++, uind++)
316 {
317 *uind = eina_unicode_utf8_get_next(utf, &ind);
318 }
319
320 return buf;
321}
322
323EAPI char *
324eina_unicode_unicode_to_utf8(const Eina_Unicode *uni, int *_len)
325{
326 char *buf;
327 const Eina_Unicode *uind;
328 char *ind;
329 int ulen, len;
330
331 ulen = eina_unicode_strlen(uni);
332 buf = (char *) calloc(ulen + 1, EINA_UNICODE_UTF8_BYTES_PER_CHAR);
333
334 len = 0;
335 for (uind = uni, ind = buf ; *uind ; uind++)
336 {
337 if (*uind <= 0x7F) /* 1 byte char */
338 {
339 *ind++ = *uind;
340 len += 1;
341 }
342 else if (*uind <= 0x7FF) /* 2 byte char */
343 {
344 *ind++ = 0xC0 | (unsigned char) (*uind >> 6);
345 *ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
346 len += 2;
347 }
348 else if (*uind <= 0xFFFF) /* 3 byte char */
349 {
350 /* If it's a special replacement codepoint */
351 if (*uind >= ERROR_REPLACEMENT_BASE &&
352 *uind <= ERROR_REPLACEMENT_END)
353 {
354 *ind++ = *uind & 0xFF;
355 len += 1;
356 }
357 else
358 {
359 *ind++ = 0xE0 | (unsigned char) (*uind >> 12);
360 *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
361 *ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
362 len += 3;
363 }
364 }
365 else if (*uind <= 0x1FFFFF) /* 4 byte char */
366 {
367 *ind++ = 0xF0 | (unsigned char) ((*uind >> 18) & 0x07);
368 *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F);
369 *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
370 *ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
371 len += 4;
372 }
373 else if (*uind <= 0x3FFFFFF) /* 5 byte char */
374 {
375 *ind++ = 0xF8 | (unsigned char) ((*uind >> 24) & 0x03);
376 *ind++ = 0x80 | (unsigned char) ((*uind >> 18) & 0x3F);
377 *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F);
378 *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
379 *ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
380 len += 5;
381 }
382 else if (*uind <= 0x7FFFFFFF) /* 6 byte char */
383 {
384 *ind++ = 0xFC | (unsigned char) ((*uind >> 30) & 0x01);
385 *ind++ = 0x80 | (unsigned char) ((*uind >> 24) & 0x3F);
386 *ind++ = 0x80 | (unsigned char) ((*uind >> 18) & 0x3F);
387 *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F);
388 *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
389 *ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
390 len += 6;
391 }
392 else /* error */
393 {
394 /* Do something */
395 }
396 }
397 buf = realloc(buf, len + 1);
398 buf[len] = '\0';
399 if (_len)
400 *_len = len;
401 return buf;
402}
403
404
405
diff --git a/libraries/eina/src/lib/eina_ustrbuf.c b/libraries/eina/src/lib/eina_ustrbuf.c
new file mode 100644
index 0000000..7c1c2db
--- /dev/null
+++ b/libraries/eina/src/lib/eina_ustrbuf.c
@@ -0,0 +1,74 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "eina_strbuf_common.h"
6#include "eina_unicode.h"
7#include "eina_ustrbuf.h"
8
9/*============================================================================*
10 * Local *
11 *============================================================================*/
12
13/**
14 * @cond LOCAL
15 */
16
17#ifdef _STRBUF_DATA_TYPE
18# undef _STRBUF_DATA_TYPE
19#endif
20
21#ifdef _STRBUF_CSIZE
22# undef _STRBUF_CSIZE
23#endif
24
25#ifdef _STRBUF_STRUCT_NAME
26# undef _STRBUF_STRUCT_NAME
27#endif
28
29#ifdef _STRBUF_STRLEN_FUNC
30# undef _STRBUF_STRLEN_FUNC
31#endif
32
33#ifdef _STRBUF_STRESCAPE_FUNC
34# undef _STRBUF_STRESCAPE_FUNC
35#endif
36
37#ifdef _STRBUF_MAGIC
38# undef _STRBUF_MAGIC
39#endif
40
41#ifdef _STRBUF_MAGIC_STR
42# undef _STRBUF_MAGIC_STR
43#endif
44
45#ifdef _FUNC_EXPAND
46# undef _FUNC_EXPAND
47#endif
48
49#define _STRBUF_DATA_TYPE Eina_Unicode
50#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE)
51#define _STRBUF_STRUCT_NAME Eina_UStrbuf
52#define _STRBUF_STRLEN_FUNC(x) eina_unicode_strlen(x)
53#define _STRBUF_STRESCAPE_FUNC(x) eina_unicode_escape(x)
54#define _STRBUF_MAGIC EINA_MAGIC_USTRBUF
55#define _STRBUF_MAGIC_STR __USTRBUF_MAGIC_STR
56static const char __USTRBUF_MAGIC_STR[] = "Eina UStrbuf";
57
58#define _FUNC_EXPAND(y) eina_ustrbuf_ ## y
59
60/**
61 * @endcond
62 */
63
64
65/*============================================================================*
66 * Global *
67 *============================================================================*/
68
69
70/*============================================================================*
71 * API *
72 *============================================================================*/
73
74#include "eina_strbuf_template_c.x"
diff --git a/libraries/eina/src/lib/eina_ustringshare.c b/libraries/eina/src/lib/eina_ustringshare.c
new file mode 100644
index 0000000..3992dc6
--- /dev/null
+++ b/libraries/eina/src/lib/eina_ustringshare.c
@@ -0,0 +1,132 @@
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 * @page tutorial_ustringshare_page UStringshare Tutorial
25 *
26 * to be written...
27 *
28 */
29
30#include "eina_share_common.h"
31#include "eina_unicode.h"
32#include "eina_private.h"
33#include "eina_ustringshare.h"
34
35/* The actual share */
36static Eina_Share *ustringshare_share;
37static const char EINA_MAGIC_USTRINGSHARE_NODE_STR[] = "Eina UStringshare Node";
38
39/*============================================================================*
40* Global *
41*============================================================================*/
42
43/**
44 * @internal
45 * @brief Initialize the share_common module.
46 *
47 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
48 *
49 * This function sets up the share_common module of Eina. It is called by
50 * eina_init().
51 *
52 * @see eina_init()
53 */
54Eina_Bool
55eina_ustringshare_init(void)
56{
57 return eina_share_common_init(&ustringshare_share,
58 EINA_MAGIC_USTRINGSHARE_NODE,
59 EINA_MAGIC_USTRINGSHARE_NODE_STR);
60}
61
62/**
63 * @internal
64 * @brief Shut down the share_common module.
65 *
66 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
67 *
68 * This function shuts down the share_common module set up by
69 * eina_share_common_init(). It is called by eina_shutdown().
70 *
71 * @see eina_shutdown()
72 */
73Eina_Bool
74eina_ustringshare_shutdown(void)
75{
76 Eina_Bool ret;
77 ret = eina_share_common_shutdown(&ustringshare_share);
78 return ret;
79}
80
81/*============================================================================*
82* API *
83*============================================================================*/
84
85EAPI void
86eina_ustringshare_del(const Eina_Unicode *str)
87{
88 if (!str)
89 return;
90
91 eina_share_common_del(ustringshare_share,(const char *)str);
92}
93
94EAPI const Eina_Unicode *
95eina_ustringshare_add_length(const Eina_Unicode *str, unsigned int slen)
96{
97 return (const Eina_Unicode *)eina_share_common_add_length(ustringshare_share,
98 (const char *)str,
99 slen *
100 sizeof(
101 Eina_Unicode),
102 sizeof(
103 Eina_Unicode));
104}
105
106EAPI const Eina_Unicode *
107eina_ustringshare_add(const Eina_Unicode *str)
108{
109 int slen = (str) ? (int)eina_unicode_strlen(str) : -1;
110 return eina_ustringshare_add_length(str, slen);
111}
112
113EAPI const Eina_Unicode *
114eina_ustringshare_ref(const Eina_Unicode *str)
115{
116 return (const Eina_Unicode *)eina_share_common_ref(ustringshare_share,
117 (const char *)str);
118}
119
120EAPI int
121eina_ustringshare_strlen(const Eina_Unicode *str)
122{
123 int len = eina_share_common_length(ustringshare_share, (const char *)str);
124 len = (len > 0) ? len / (int)sizeof(Eina_Unicode) : -1;
125 return len;
126}
127
128EAPI void
129eina_ustringshare_dump(void)
130{
131 eina_share_common_dump(ustringshare_share, NULL, 0);
132}
diff --git a/libraries/eina/src/lib/eina_value.c b/libraries/eina/src/lib/eina_value.c
new file mode 100644
index 0000000..554f907
--- /dev/null
+++ b/libraries/eina/src/lib/eina_value.c
@@ -0,0 +1,47 @@
1/* eina_value.c
2
3 Copyright (C) 2001 Christopher Rosendahl <smugg@fatelabs.com>
4 Nathan Ingersoll <ningerso@d.umn.edu>
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to
8 deal in the Software without restriction, including without limitation the
9 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 sell copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies of the Software and its documentation and acknowledgment shall be
15 given in the documentation and software packages that this Software was
16 used.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 */
26
27#ifdef HAVE_CONFIG_H
28# include "config.h"
29#endif
30
31#include "eina_config.h"
32#include "eina_private.h"
33
34/*============================================================================*
35* Global *
36*============================================================================*/
37
38/*============================================================================*
39* API *
40*============================================================================*/
41
42EAPI const unsigned int eina_prime_table[] =
43{
44 17, 31, 61, 127, 257, 509, 1021,
45 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573,
46 2097143, 4194301, 8388617, 16777213
47};
diff --git a/libraries/eina/src/lib/eina_xattr.c b/libraries/eina/src/lib/eina_xattr.c
new file mode 100644
index 0000000..bd5b98e
--- /dev/null
+++ b/libraries/eina/src/lib/eina_xattr.c
@@ -0,0 +1,292 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2011 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 <sys/types.h>
24#include <string.h>
25#include <math.h>
26
27#ifdef HAVE_XATTR
28# include <sys/xattr.h>
29#endif
30
31#include "eina_config.h"
32#include "eina_private.h"
33
34#include "eina_safety_checks.h"
35#include "eina_xattr.h"
36#include "eina_convert.h"
37
38/*============================================================================*
39 * Local *
40 *============================================================================*/
41
42/**
43 * @cond LOCAL
44 */
45
46typedef struct _Eina_Xattr_Iterator Eina_Xattr_Iterator;
47
48struct _Eina_Xattr_Iterator
49{
50 Eina_Iterator iterator;
51
52 ssize_t length;
53 ssize_t offset;
54
55 char xattr[1];
56};
57
58#ifdef HAVE_XATTR
59static Eina_Bool
60_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data)
61{
62 if (it->offset >= it->length)
63 return EINA_FALSE;
64
65 *data = it->xattr + it->offset;
66 it->offset += strlen(it->xattr + it->offset) + 1;
67
68 return EINA_TRUE;
69}
70
71static void *
72_eina_xattr_ls_iterator_container(Eina_Xattr_Iterator *it __UNUSED__)
73{
74 return NULL;
75}
76
77static void
78_eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it)
79{
80 EINA_MAGIC_SET(&it->iterator, 0);
81 free(it);
82}
83#endif
84
85/**
86 * @endcond
87 */
88
89
90/*============================================================================*
91 * Global *
92 *============================================================================*/
93
94
95/*============================================================================*
96 * API *
97 *============================================================================*/
98
99
100EAPI Eina_Iterator *
101eina_xattr_ls(const char *file)
102{
103#ifdef HAVE_XATTR
104 Eina_Xattr_Iterator *it;
105 ssize_t length;
106
107 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
108
109 length = listxattr(file, NULL, 0);
110 if (length <= 0) return NULL;
111
112 it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1);
113 if (!it) return NULL;
114
115 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
116
117 it->length = listxattr(file, it->xattr, length);
118 if (it->length != length)
119 {
120 free(it);
121 return NULL;
122 }
123
124 it->iterator.version = EINA_ITERATOR_VERSION;
125 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_ls_iterator_next);
126 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container);
127 it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free);
128
129 return &it->iterator;
130#else
131 return NULL;
132 (void)file;
133#endif
134}
135
136EAPI void *
137eina_xattr_get(const char *file, const char *attribute, ssize_t *size)
138{
139#ifdef HAVE_XATTR
140 void *ret = NULL;
141 ssize_t tmp;
142
143 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
144 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
145 EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, NULL);
146
147 *size = getxattr(file, attribute, NULL, 0);
148 /* Size should be less than 2MB (already huge in my opinion) */
149 if (!(*size > 0 && *size < 2 * 1024 * 1024))
150 goto on_error;
151
152 ret = malloc(*size);
153 if (!ret) return NULL;
154
155 tmp = getxattr(file, attribute, ret, *size);
156 if (tmp != *size)
157 goto on_error;
158
159 return ret;
160
161 on_error:
162 free(ret);
163 *size = 0;
164 return NULL;
165#else
166 EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, NULL);
167 *size = 0;
168 return NULL;
169 (void)file;
170 (void)attribute;
171#endif
172}
173
174EAPI Eina_Bool
175eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags)
176{
177#ifdef HAVE_XATTR
178 int iflags;
179
180 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
181 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, EINA_FALSE);
182 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
183 EINA_SAFETY_ON_TRUE_RETURN_VAL(!(length > 0 && length < 2 * 1024 * 1024), EINA_FALSE);
184
185 switch (flags)
186 {
187 case EINA_XATTR_INSERT: iflags = 0; break;
188 case EINA_XATTR_REPLACE: iflags = XATTR_REPLACE; break;
189 case EINA_XATTR_CREATED: iflags = XATTR_CREATE; break;
190 default:
191 return EINA_FALSE;
192 }
193
194 if (setxattr(file, attribute, data, length, iflags))
195 return EINA_FALSE;
196 return EINA_TRUE;
197#else
198 return EINA_FALSE;
199 (void)file;
200 (void)attribute;
201 (void)data;
202 (void)length;
203 (void)flags;
204#endif
205}
206
207EAPI Eina_Bool
208eina_xattr_string_set(const char *file, const char *attribute, const char *data, Eina_Xattr_Flags flags)
209{
210 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
211
212 return eina_xattr_set(file, attribute, data, strlen(data) + 1, flags);
213}
214
215EAPI char *
216eina_xattr_string_get(const char *file, const char *attribute)
217{
218 char *tmp;
219 ssize_t size;
220
221 tmp = eina_xattr_get(file, attribute, &size);
222 if (!tmp) return NULL;
223
224 if (tmp[size - 1] != '\0')
225 {
226 free(tmp);
227 return NULL;
228 }
229
230 return tmp;
231}
232
233EAPI Eina_Bool
234eina_xattr_double_set(const char *file, const char *attribute, double value, Eina_Xattr_Flags flags)
235{
236 char buffer[128];
237
238 eina_convert_dtoa(value, buffer);
239 return eina_xattr_string_set(file, attribute, buffer, flags);
240}
241
242EAPI Eina_Bool
243eina_xattr_double_get(const char *file, const char *attribute, double *value)
244{
245 char *tmp;
246 long long int m = 0;
247 long int e = 0;
248
249 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
250
251 tmp = eina_xattr_string_get(file, attribute);
252 if (!tmp) return EINA_FALSE;
253
254 if (!eina_convert_atod(tmp, strlen(tmp), &m, &e))
255 {
256 free(tmp);
257 return EINA_FALSE;
258 }
259
260 *value = ldexp((double)m, e);
261 free(tmp);
262
263 return EINA_TRUE;
264}
265
266EAPI Eina_Bool
267eina_xattr_int_set(const char *file, const char *attribute, int value, Eina_Xattr_Flags flags)
268{
269 char buffer[10];
270
271 eina_convert_itoa(value, buffer);
272 return eina_xattr_string_set(file, attribute, buffer, flags);
273}
274
275EAPI Eina_Bool
276eina_xattr_int_get(const char *file, const char *attribute, int *value)
277{
278 char *tmp;
279 char *eos;
280 Eina_Bool result;
281
282 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
283
284 tmp = eina_xattr_string_get(file, attribute);
285 if (!tmp) return EINA_FALSE;
286
287 *value = (int) strtol(tmp, &eos, 10);
288 result = (*eos == '\0');
289 free(tmp);
290
291 return result;
292}