diff options
Diffstat (limited to '')
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 @@ | |||
1 | MAINTAINERCLEANFILES = Makefile.in | ||
2 | |||
3 | AM_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 | |||
12 | base_sources = \ | ||
13 | eina_accessor.c \ | ||
14 | eina_array.c \ | ||
15 | eina_benchmark.c \ | ||
16 | eina_binbuf.c \ | ||
17 | eina_binshare.c \ | ||
18 | eina_convert.c \ | ||
19 | eina_counter.c \ | ||
20 | eina_cpu.c \ | ||
21 | eina_error.c \ | ||
22 | eina_fp.c \ | ||
23 | eina_hamster.c \ | ||
24 | eina_hash.c \ | ||
25 | eina_inlist.c \ | ||
26 | eina_iterator.c \ | ||
27 | eina_lalloc.c \ | ||
28 | eina_list.c \ | ||
29 | eina_log.c \ | ||
30 | eina_magic.c \ | ||
31 | eina_main.c \ | ||
32 | eina_matrixsparse.c \ | ||
33 | eina_mempool.c \ | ||
34 | eina_mmap.c \ | ||
35 | eina_module.c \ | ||
36 | eina_prefix.c \ | ||
37 | eina_quadtree.c \ | ||
38 | eina_rbtree.c \ | ||
39 | eina_rectangle.c \ | ||
40 | eina_safety_checks.c \ | ||
41 | eina_sched.c \ | ||
42 | eina_share_common.c \ | ||
43 | eina_simple_xml_parser.c \ | ||
44 | eina_str.c \ | ||
45 | eina_strbuf.c \ | ||
46 | eina_strbuf_common.c \ | ||
47 | eina_stringshare.c \ | ||
48 | eina_tiler.c \ | ||
49 | eina_unicode.c \ | ||
50 | eina_ustrbuf.c \ | ||
51 | eina_ustringshare.c \ | ||
52 | eina_value.c \ | ||
53 | eina_xattr.c | ||
54 | |||
55 | # Will be back for developper after 1.1 | ||
56 | # eina_object.c | ||
57 | |||
58 | if EINA_HAVE_WIN32 | ||
59 | base_sources += eina_file_win32.c | ||
60 | else | ||
61 | base_sources += eina_file.c | ||
62 | endif | ||
63 | |||
64 | EXTRA_DIST = \ | ||
65 | eina_share_common.h \ | ||
66 | eina_private.h \ | ||
67 | eina_strbuf_common.h \ | ||
68 | eina_strbuf_template_c.x \ | ||
69 | eina_binbuf_template_c.x | ||
70 | |||
71 | |||
72 | |||
73 | if EINA_STATIC_BUILD_BUDDY | ||
74 | base_sources += $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c | ||
75 | endif | ||
76 | |||
77 | if EINA_STATIC_BUILD_CHAINED_POOL | ||
78 | base_sources += $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c | ||
79 | endif | ||
80 | |||
81 | if EINA_STATIC_BUILD_EMEMOA_FIXED | ||
82 | base_sources += $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c | ||
83 | endif | ||
84 | |||
85 | if EINA_STATIC_BUILD_EMEMOA_UNKNOWN | ||
86 | base_sources += $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c | ||
87 | endif | ||
88 | |||
89 | if EINA_STATIC_BUILD_FIXED_BITMAP | ||
90 | base_sources += $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c | ||
91 | endif | ||
92 | |||
93 | if EINA_STATIC_BUILD_ONE_BIG | ||
94 | base_sources += $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c | ||
95 | endif | ||
96 | |||
97 | if EINA_STATIC_BUILD_PASS_THROUGH | ||
98 | base_sources += $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c | ||
99 | endif | ||
100 | |||
101 | lib_LTLIBRARIES = libeina.la | ||
102 | |||
103 | if EINA_AMALGAMATION | ||
104 | nodist_libeina_la_SOURCES = eina_amalgamation.c | ||
105 | |||
106 | eina_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 | |||
162 | else | ||
163 | libeina_la_SOURCES = $(base_sources) | ||
164 | endif | ||
165 | |||
166 | libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@ | ||
167 | libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@ | ||
168 | libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@ | ||
169 | |||
170 | clean-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 | |||
18 | VPATH = @srcdir@ | ||
19 | pkgdatadir = $(datadir)/@PACKAGE@ | ||
20 | pkgincludedir = $(includedir)/@PACKAGE@ | ||
21 | pkglibdir = $(libdir)/@PACKAGE@ | ||
22 | pkglibexecdir = $(libexecdir)/@PACKAGE@ | ||
23 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd | ||
24 | install_sh_DATA = $(install_sh) -c -m 644 | ||
25 | install_sh_PROGRAM = $(install_sh) -c | ||
26 | install_sh_SCRIPT = $(install_sh) -c | ||
27 | INSTALL_HEADER = $(INSTALL_DATA) | ||
28 | transform = $(program_transform_name) | ||
29 | NORMAL_INSTALL = : | ||
30 | PRE_INSTALL = : | ||
31 | POST_INSTALL = : | ||
32 | NORMAL_UNINSTALL = : | ||
33 | PRE_UNINSTALL = : | ||
34 | POST_UNINSTALL = : | ||
35 | build_triplet = @build@ | ||
36 | host_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 | ||
49 | subdir = src/lib | ||
50 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in | ||
51 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||
52 | am__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 | ||
66 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ | ||
67 | $(ACLOCAL_M4) | ||
68 | mkinstalldirs = $(install_sh) -d | ||
69 | CONFIG_HEADER = $(top_builddir)/config.h | ||
70 | CONFIG_CLEAN_FILES = | ||
71 | CONFIG_CLEAN_VPATH_FILES = | ||
72 | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||
73 | am__vpath_adj = case $$p in \ | ||
74 | $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||
75 | *) f=$$p;; \ | ||
76 | esac; | ||
77 | am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; | ||
78 | am__install_max = 40 | ||
79 | am__nobase_strip_setup = \ | ||
80 | srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` | ||
81 | am__nobase_strip = \ | ||
82 | for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" | ||
83 | am__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] }' | ||
90 | am__base_list = \ | ||
91 | sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ | ||
92 | sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | ||
93 | am__installdirs = "$(DESTDIR)$(libdir)" | ||
94 | LTLIBRARIES = $(lib_LTLIBRARIES) | ||
95 | libeina_la_DEPENDENCIES = | ||
96 | am__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 | ||
126 | am__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 | ||
153 | libeina_la_OBJECTS = $(am_libeina_la_OBJECTS) \ | ||
154 | $(nodist_libeina_la_OBJECTS) | ||
155 | AM_V_lt = $(am__v_lt_$(V)) | ||
156 | am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) | ||
157 | am__v_lt_0 = --silent | ||
158 | libeina_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 $@ | ||
161 | DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) | ||
162 | depcomp = $(SHELL) $(top_srcdir)/depcomp | ||
163 | am__depfiles_maybe = depfiles | ||
164 | am__mv = mv -f | ||
165 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ | ||
166 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) | ||
167 | LTCOMPILE = $(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) | ||
171 | AM_V_CC = $(am__v_CC_$(V)) | ||
172 | am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) | ||
173 | am__v_CC_0 = @echo " CC " $@; | ||
174 | AM_V_at = $(am__v_at_$(V)) | ||
175 | am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) | ||
176 | am__v_at_0 = @ | ||
177 | CCLD = $(CC) | ||
178 | LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||
179 | $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||
180 | $(AM_LDFLAGS) $(LDFLAGS) -o $@ | ||
181 | AM_V_CCLD = $(am__v_CCLD_$(V)) | ||
182 | am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) | ||
183 | am__v_CCLD_0 = @echo " CCLD " $@; | ||
184 | AM_V_GEN = $(am__v_GEN_$(V)) | ||
185 | am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) | ||
186 | am__v_GEN_0 = @echo " GEN " $@; | ||
187 | SOURCES = $(libeina_la_SOURCES) $(nodist_libeina_la_SOURCES) | ||
188 | DIST_SOURCES = $(am__libeina_la_SOURCES_DIST) | ||
189 | ETAGS = etags | ||
190 | CTAGS = ctags | ||
191 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) | ||
192 | ACLOCAL = @ACLOCAL@ | ||
193 | ALLOCA = @ALLOCA@ | ||
194 | AMTAR = @AMTAR@ | ||
195 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ | ||
196 | AR = @AR@ | ||
197 | AS = @AS@ | ||
198 | AUTOCONF = @AUTOCONF@ | ||
199 | AUTOHEADER = @AUTOHEADER@ | ||
200 | AUTOMAKE = @AUTOMAKE@ | ||
201 | AWK = @AWK@ | ||
202 | CC = @CC@ | ||
203 | CCDEPMODE = @CCDEPMODE@ | ||
204 | CFLAGS = @CFLAGS@ | ||
205 | CHECK_CFLAGS = @CHECK_CFLAGS@ | ||
206 | CHECK_LIBS = @CHECK_LIBS@ | ||
207 | CPP = @CPP@ | ||
208 | CPPFLAGS = @CPPFLAGS@ | ||
209 | CXX = @CXX@ | ||
210 | CXXCPP = @CXXCPP@ | ||
211 | CXXDEPMODE = @CXXDEPMODE@ | ||
212 | CXXFLAGS = @CXXFLAGS@ | ||
213 | CYGPATH_W = @CYGPATH_W@ | ||
214 | DEFS = @DEFS@ | ||
215 | DEPDIR = @DEPDIR@ | ||
216 | DLLTOOL = @DLLTOOL@ | ||
217 | DSYMUTIL = @DSYMUTIL@ | ||
218 | DUMPBIN = @DUMPBIN@ | ||
219 | ECHO_C = @ECHO_C@ | ||
220 | ECHO_N = @ECHO_N@ | ||
221 | ECHO_T = @ECHO_T@ | ||
222 | ECORE_EVAS_CFLAGS = @ECORE_EVAS_CFLAGS@ | ||
223 | ECORE_EVAS_LIBS = @ECORE_EVAS_LIBS@ | ||
224 | EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@ | ||
225 | EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@ | ||
226 | EFL_EINA_BUILD = @EFL_EINA_BUILD@ | ||
227 | EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@ | ||
228 | EFL_PTHREAD_CFLAGS = @EFL_PTHREAD_CFLAGS@ | ||
229 | EFL_PTHREAD_LIBS = @EFL_PTHREAD_LIBS@ | ||
230 | EFL_SIMD_FLAGS = @EFL_SIMD_FLAGS@ | ||
231 | EGREP = @EGREP@ | ||
232 | EINA_CFLAGS = @EINA_CFLAGS@ | ||
233 | EINA_CONFIGURE_DEFAULT_MEMPOOL = @EINA_CONFIGURE_DEFAULT_MEMPOOL@ | ||
234 | EINA_CONFIGURE_HAVE_DEBUG_THREADS = @EINA_CONFIGURE_HAVE_DEBUG_THREADS@ | ||
235 | EINA_CONFIGURE_HAVE_INTTYPES_H = @EINA_CONFIGURE_HAVE_INTTYPES_H@ | ||
236 | EINA_CONFIGURE_HAVE_ON_OFF_THREADS = @EINA_CONFIGURE_HAVE_ON_OFF_THREADS@ | ||
237 | EINA_CONFIGURE_HAVE_STDINT_H = @EINA_CONFIGURE_HAVE_STDINT_H@ | ||
238 | EINA_CONFIGURE_HAVE_THREADS = @EINA_CONFIGURE_HAVE_THREADS@ | ||
239 | EINA_CONFIGURE_MAGIC_DEBUG = @EINA_CONFIGURE_MAGIC_DEBUG@ | ||
240 | EINA_CONFIGURE_SAFETY_CHECKS = @EINA_CONFIGURE_SAFETY_CHECKS@ | ||
241 | EINA_CPPFLAGS = @EINA_CPPFLAGS@ | ||
242 | EINA_LIBS = @EINA_LIBS@ | ||
243 | EINA_SIZEOF_WCHAR_T = @EINA_SIZEOF_WCHAR_T@ | ||
244 | EMEMOA_CFLAGS = @EMEMOA_CFLAGS@ | ||
245 | EMEMOA_LIBS = @EMEMOA_LIBS@ | ||
246 | ESCAPE_CFLAGS = @ESCAPE_CFLAGS@ | ||
247 | ESCAPE_LIBS = @ESCAPE_LIBS@ | ||
248 | EVIL_CFLAGS = @EVIL_CFLAGS@ | ||
249 | EVIL_LIBS = @EVIL_LIBS@ | ||
250 | EXEEXT = @EXEEXT@ | ||
251 | FGREP = @FGREP@ | ||
252 | GLIB_CFLAGS = @GLIB_CFLAGS@ | ||
253 | GLIB_LIBS = @GLIB_LIBS@ | ||
254 | GREP = @GREP@ | ||
255 | INSTALL = @INSTALL@ | ||
256 | INSTALL_DATA = @INSTALL_DATA@ | ||
257 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ | ||
258 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ | ||
259 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ | ||
260 | LD = @LD@ | ||
261 | LDFLAGS = @LDFLAGS@ | ||
262 | LIBOBJS = @LIBOBJS@ | ||
263 | LIBS = @LIBS@ | ||
264 | LIBTOOL = @LIBTOOL@ | ||
265 | LIPO = @LIPO@ | ||
266 | LN_S = @LN_S@ | ||
267 | LTLIBOBJS = @LTLIBOBJS@ | ||
268 | MAKEINFO = @MAKEINFO@ | ||
269 | MKDIR_P = @MKDIR_P@ | ||
270 | MODULE_ARCH = @MODULE_ARCH@ | ||
271 | NM = @NM@ | ||
272 | NMEDIT = @NMEDIT@ | ||
273 | OBJDUMP = @OBJDUMP@ | ||
274 | OBJEXT = @OBJEXT@ | ||
275 | OTOOL = @OTOOL@ | ||
276 | OTOOL64 = @OTOOL64@ | ||
277 | PACKAGE = @PACKAGE@ | ||
278 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ | ||
279 | PACKAGE_NAME = @PACKAGE_NAME@ | ||
280 | PACKAGE_STRING = @PACKAGE_STRING@ | ||
281 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ | ||
282 | PACKAGE_URL = @PACKAGE_URL@ | ||
283 | PACKAGE_VERSION = @PACKAGE_VERSION@ | ||
284 | PATH_SEPARATOR = @PATH_SEPARATOR@ | ||
285 | PKG_CONFIG = @PKG_CONFIG@ | ||
286 | PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ | ||
287 | PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ | ||
288 | RANLIB = @RANLIB@ | ||
289 | SED = @SED@ | ||
290 | SET_MAKE = @SET_MAKE@ | ||
291 | SHELL = @SHELL@ | ||
292 | STRIP = @STRIP@ | ||
293 | VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ | ||
294 | VALGRIND_LIBS = @VALGRIND_LIBS@ | ||
295 | VERSION = @VERSION@ | ||
296 | VMAJ = @VMAJ@ | ||
297 | abs_builddir = @abs_builddir@ | ||
298 | abs_srcdir = @abs_srcdir@ | ||
299 | abs_top_builddir = @abs_top_builddir@ | ||
300 | abs_top_srcdir = @abs_top_srcdir@ | ||
301 | ac_ct_CC = @ac_ct_CC@ | ||
302 | ac_ct_CXX = @ac_ct_CXX@ | ||
303 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ | ||
304 | am__include = @am__include@ | ||
305 | am__leading_dot = @am__leading_dot@ | ||
306 | am__quote = @am__quote@ | ||
307 | am__tar = @am__tar@ | ||
308 | am__untar = @am__untar@ | ||
309 | bindir = @bindir@ | ||
310 | build = @build@ | ||
311 | build_alias = @build_alias@ | ||
312 | build_cpu = @build_cpu@ | ||
313 | build_os = @build_os@ | ||
314 | build_vendor = @build_vendor@ | ||
315 | builddir = @builddir@ | ||
316 | datadir = @datadir@ | ||
317 | datarootdir = @datarootdir@ | ||
318 | dlopen_libs = @dlopen_libs@ | ||
319 | docdir = @docdir@ | ||
320 | dvidir = @dvidir@ | ||
321 | efl_doxygen = @efl_doxygen@ | ||
322 | efl_have_doxygen = @efl_have_doxygen@ | ||
323 | exec_prefix = @exec_prefix@ | ||
324 | have_lcov = @have_lcov@ | ||
325 | host = @host@ | ||
326 | host_alias = @host_alias@ | ||
327 | host_cpu = @host_cpu@ | ||
328 | host_os = @host_os@ | ||
329 | host_vendor = @host_vendor@ | ||
330 | htmldir = @htmldir@ | ||
331 | iconv_libs = @iconv_libs@ | ||
332 | includedir = @includedir@ | ||
333 | infodir = @infodir@ | ||
334 | install_sh = @install_sh@ | ||
335 | libdir = @libdir@ | ||
336 | libexecdir = @libexecdir@ | ||
337 | localedir = @localedir@ | ||
338 | localstatedir = @localstatedir@ | ||
339 | lt_ECHO = @lt_ECHO@ | ||
340 | lt_enable_auto_import = @lt_enable_auto_import@ | ||
341 | mandir = @mandir@ | ||
342 | mkdir_p = @mkdir_p@ | ||
343 | oldincludedir = @oldincludedir@ | ||
344 | pdfdir = @pdfdir@ | ||
345 | pkgconfig_requires_private = @pkgconfig_requires_private@ | ||
346 | prefix = @prefix@ | ||
347 | program_transform_name = @program_transform_name@ | ||
348 | psdir = @psdir@ | ||
349 | release_info = @release_info@ | ||
350 | requirement_eina = @requirement_eina@ | ||
351 | rt_libs = @rt_libs@ | ||
352 | sbindir = @sbindir@ | ||
353 | sharedstatedir = @sharedstatedir@ | ||
354 | srcdir = @srcdir@ | ||
355 | sysconfdir = @sysconfdir@ | ||
356 | target_alias = @target_alias@ | ||
357 | top_build_prefix = @top_build_prefix@ | ||
358 | top_builddir = @top_builddir@ | ||
359 | top_srcdir = @top_srcdir@ | ||
360 | version_info = @version_info@ | ||
361 | MAINTAINERCLEANFILES = Makefile.in | ||
362 | AM_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 | |||
371 | base_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) | ||
385 | EXTRA_DIST = \ | ||
386 | eina_share_common.h \ | ||
387 | eina_private.h \ | ||
388 | eina_strbuf_common.h \ | ||
389 | eina_strbuf_template_c.x \ | ||
390 | eina_binbuf_template_c.x | ||
391 | |||
392 | lib_LTLIBRARIES = libeina.la | ||
393 | @EINA_AMALGAMATION_TRUE@nodist_libeina_la_SOURCES = eina_amalgamation.c | ||
394 | @EINA_AMALGAMATION_FALSE@libeina_la_SOURCES = $(base_sources) | ||
395 | libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@ | ||
396 | libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@ | ||
397 | libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@ | ||
398 | all: 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 | ||
415 | Makefile: $(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): | ||
432 | install-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 | |||
446 | uninstall-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 | |||
455 | clean-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 | ||
463 | libeina.la: $(libeina_la_OBJECTS) $(libeina_la_DEPENDENCIES) | ||
464 | $(AM_V_CCLD)$(libeina_la_LINK) -rpath $(libdir) $(libeina_la_OBJECTS) $(libeina_la_LIBADD) $(LIBS) | ||
465 | |||
466 | mostlyclean-compile: | ||
467 | -rm -f *.$(OBJEXT) | ||
468 | |||
469 | distclean-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 | |||
548 | libeina_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 | |||
556 | libeina_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 | |||
564 | libeina_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 | |||
572 | libeina_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 | |||
580 | libeina_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 | |||
588 | libeina_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 | |||
596 | libeina_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 | |||
604 | libeina_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 | |||
612 | libeina_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 | |||
620 | libeina_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 | |||
628 | libeina_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 | |||
636 | libeina_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 | |||
644 | libeina_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 | |||
652 | libeina_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 | |||
660 | libeina_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 | |||
668 | libeina_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 | |||
676 | libeina_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 | |||
684 | libeina_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 | |||
692 | libeina_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 | |||
700 | libeina_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 | |||
708 | libeina_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 | |||
716 | libeina_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 | |||
724 | libeina_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 | |||
732 | libeina_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 | |||
740 | libeina_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 | |||
748 | libeina_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 | |||
756 | libeina_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 | |||
764 | libeina_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 | |||
772 | libeina_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 | |||
780 | libeina_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 | |||
788 | libeina_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 | |||
796 | libeina_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 | |||
804 | libeina_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 | |||
812 | libeina_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 | |||
820 | libeina_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 | |||
828 | libeina_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 | |||
836 | libeina_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 | |||
844 | libeina_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 | |||
852 | libeina_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 | |||
860 | libeina_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 | |||
868 | libeina_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 | |||
876 | libeina_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 | |||
884 | libeina_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 | |||
892 | libeina_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 | |||
900 | libeina_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 | |||
908 | libeina_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 | |||
916 | libeina_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 | |||
924 | libeina_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 | |||
932 | libeina_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 | |||
940 | libeina_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 | |||
948 | libeina_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 | |||
956 | mostlyclean-libtool: | ||
957 | -rm -f *.lo | ||
958 | |||
959 | clean-libtool: | ||
960 | -rm -rf .libs _libs | ||
961 | |||
962 | ID: $(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 | ||
970 | tags: TAGS | ||
971 | |||
972 | TAGS: $(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 | ||
993 | ctags: CTAGS | ||
994 | CTAGS: $(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 | |||
1006 | GTAGS: | ||
1007 | here=`$(am__cd) $(top_builddir) && pwd` \ | ||
1008 | && $(am__cd) $(top_srcdir) \ | ||
1009 | && gtags -i $(GTAGS_ARGS) "$$here" | ||
1010 | |||
1011 | distclean-tags: | ||
1012 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags | ||
1013 | |||
1014 | distdir: $(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 | ||
1044 | check-am: all-am | ||
1045 | check: check-am | ||
1046 | all-am: Makefile $(LTLIBRARIES) | ||
1047 | installdirs: | ||
1048 | for dir in "$(DESTDIR)$(libdir)"; do \ | ||
1049 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ | ||
1050 | done | ||
1051 | install: install-am | ||
1052 | install-exec: install-exec-am | ||
1053 | install-data: install-data-am | ||
1054 | uninstall: uninstall-am | ||
1055 | |||
1056 | install-am: all-am | ||
1057 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am | ||
1058 | |||
1059 | installcheck: installcheck-am | ||
1060 | install-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 | ||
1065 | mostlyclean-generic: | ||
1066 | |||
1067 | clean-generic: | ||
1068 | |||
1069 | distclean-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 | |||
1073 | maintainer-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) | ||
1077 | clean: clean-am | ||
1078 | |||
1079 | clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ | ||
1080 | mostlyclean-am | ||
1081 | |||
1082 | distclean: distclean-am | ||
1083 | -rm -rf ./$(DEPDIR) | ||
1084 | -rm -f Makefile | ||
1085 | distclean-am: clean-am distclean-compile distclean-generic \ | ||
1086 | distclean-tags | ||
1087 | |||
1088 | dvi: dvi-am | ||
1089 | |||
1090 | dvi-am: | ||
1091 | |||
1092 | html: html-am | ||
1093 | |||
1094 | html-am: | ||
1095 | |||
1096 | info: info-am | ||
1097 | |||
1098 | info-am: | ||
1099 | |||
1100 | install-data-am: | ||
1101 | |||
1102 | install-dvi: install-dvi-am | ||
1103 | |||
1104 | install-dvi-am: | ||
1105 | |||
1106 | install-exec-am: install-libLTLIBRARIES | ||
1107 | |||
1108 | install-html: install-html-am | ||
1109 | |||
1110 | install-html-am: | ||
1111 | |||
1112 | install-info: install-info-am | ||
1113 | |||
1114 | install-info-am: | ||
1115 | |||
1116 | install-man: | ||
1117 | |||
1118 | install-pdf: install-pdf-am | ||
1119 | |||
1120 | install-pdf-am: | ||
1121 | |||
1122 | install-ps: install-ps-am | ||
1123 | |||
1124 | install-ps-am: | ||
1125 | |||
1126 | installcheck-am: | ||
1127 | |||
1128 | maintainer-clean: maintainer-clean-am | ||
1129 | -rm -rf ./$(DEPDIR) | ||
1130 | -rm -f Makefile | ||
1131 | maintainer-clean-am: distclean-am maintainer-clean-generic | ||
1132 | |||
1133 | mostlyclean: mostlyclean-am | ||
1134 | |||
1135 | mostlyclean-am: mostlyclean-compile mostlyclean-generic \ | ||
1136 | mostlyclean-libtool | ||
1137 | |||
1138 | pdf: pdf-am | ||
1139 | |||
1140 | pdf-am: | ||
1141 | |||
1142 | ps: ps-am | ||
1143 | |||
1144 | ps-am: | ||
1145 | |||
1146 | uninstall-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 | |||
1221 | clean-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 | |||
40 | static 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 | */ | ||
67 | Eina_Bool | ||
68 | eina_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 | */ | ||
84 | Eina_Bool | ||
85 | eina_accessor_shutdown(void) | ||
86 | { | ||
87 | return EINA_TRUE; | ||
88 | } | ||
89 | |||
90 | /*============================================================================* | ||
91 | * API * | ||
92 | *============================================================================*/ | ||
93 | |||
94 | |||
95 | EAPI void | ||
96 | eina_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 | |||
104 | EAPI void * | ||
105 | eina_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 | |||
113 | EAPI Eina_Bool | ||
114 | eina_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 | |||
125 | EAPI void | ||
126 | eina_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 | |||
156 | EAPI Eina_Bool | ||
157 | eina_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 | |||
167 | EAPI Eina_Bool | ||
168 | eina_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 | |||
46 | static const char EINA_MAGIC_ARRAY_STR[] = "Eina Array"; | ||
47 | static const char EINA_MAGIC_ARRAY_ITERATOR_STR[] = "Eina Array Iterator"; | ||
48 | static 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 | |||
75 | typedef struct _Eina_Iterator_Array Eina_Iterator_Array; | ||
76 | struct _Eina_Iterator_Array | ||
77 | { | ||
78 | Eina_Iterator iterator; | ||
79 | |||
80 | const Eina_Array *array; | ||
81 | unsigned int index; | ||
82 | |||
83 | EINA_MAGIC | ||
84 | }; | ||
85 | |||
86 | typedef struct _Eina_Accessor_Array Eina_Accessor_Array; | ||
87 | struct _Eina_Accessor_Array | ||
88 | { | ||
89 | Eina_Accessor accessor; | ||
90 | const Eina_Array *array; | ||
91 | EINA_MAGIC | ||
92 | }; | ||
93 | |||
94 | static 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 | |||
106 | static void eina_array_iterator_free(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1); | ||
107 | static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1); | ||
108 | static Eina_Bool eina_array_iterator_next(Eina_Iterator_Array *it, | ||
109 | void **data) EINA_ARG_NONNULL(1); | ||
110 | |||
111 | static Eina_Bool eina_array_accessor_get_at(Eina_Accessor_Array *it, | ||
112 | unsigned int idx, | ||
113 | void **data) EINA_ARG_NONNULL(1); | ||
114 | static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1); | ||
115 | static void eina_array_accessor_free(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1); | ||
116 | |||
117 | static Eina_Bool | ||
118 | eina_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 | |||
132 | static Eina_Array * | ||
133 | eina_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 | |||
139 | static void | ||
140 | eina_array_iterator_free(Eina_Iterator_Array *it) | ||
141 | { | ||
142 | EINA_MAGIC_CHECK_ARRAY_ITERATOR(it); | ||
143 | MAGIC_FREE(it); | ||
144 | } | ||
145 | |||
146 | static Eina_Bool | ||
147 | eina_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 | |||
162 | static Eina_Array * | ||
163 | eina_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 | |||
169 | static void | ||
170 | eina_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 */ | ||
177 | EAPI Eina_Bool | ||
178 | eina_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 | */ | ||
222 | Eina_Bool | ||
223 | eina_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 | */ | ||
252 | Eina_Bool | ||
253 | eina_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 | |||
264 | EAPI Eina_Array * | ||
265 | eina_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 | |||
288 | EAPI void | ||
289 | eina_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 | |||
298 | EAPI void | ||
299 | eina_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 | |||
323 | EAPI void | ||
324 | eina_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 | |||
339 | EAPI Eina_Bool | ||
340 | eina_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 | |||
433 | EAPI Eina_Iterator * | ||
434 | eina_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 | |||
463 | EAPI Eina_Accessor * | ||
464 | eina_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 | ||
35 | extern "C" | ||
36 | # endif | ||
37 | void *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 | |||
67 | typedef struct _Eina_Run Eina_Run; | ||
68 | struct _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 | |||
79 | struct _Eina_Benchmark | ||
80 | { | ||
81 | const char *name; | ||
82 | const char *run; | ||
83 | |||
84 | Eina_Inlist *runs; | ||
85 | Eina_List *names; | ||
86 | }; | ||
87 | |||
88 | static 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 | */ | ||
119 | Eina_Bool | ||
120 | eina_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 | */ | ||
144 | Eina_Bool | ||
145 | eina_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 | |||
156 | EAPI Eina_Benchmark * | ||
157 | eina_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 | |||
175 | EAPI void | ||
176 | eina_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 | |||
206 | EAPI Eina_Bool | ||
207 | eina_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 | |||
241 | EAPI Eina_Array * | ||
242 | eina_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 | ||
54 | static 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 | */ | ||
32 | Eina_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 | */ | ||
50 | Eina_Bool | ||
51 | _FUNC_EXPAND(shutdown)(void) | ||
52 | { | ||
53 | return eina_strbuf_common_shutdown(); | ||
54 | } | ||
55 | |||
56 | /*============================================================================* | ||
57 | * API * | ||
58 | *============================================================================*/ | ||
59 | |||
60 | EAPI _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 | |||
68 | EAPI 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 | |||
76 | EAPI 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 | |||
83 | EAPI 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 | |||
90 | EAPI 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 | |||
97 | EAPI 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 | |||
104 | EAPI 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 | |||
111 | EAPI 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 | |||
118 | EAPI 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 | |||
125 | EAPI _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 | |||
132 | EAPI 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 | |||
139 | EAPI 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 */ | ||
38 | static Eina_Share *binshare_share; | ||
39 | static 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 | */ | ||
61 | EAPI Eina_Bool | ||
62 | eina_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 | */ | ||
80 | EAPI Eina_Bool | ||
81 | eina_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 | |||
93 | EAPI void | ||
94 | eina_binshare_del(const void *obj) | ||
95 | { | ||
96 | if (!obj) | ||
97 | return; | ||
98 | |||
99 | eina_share_common_del(binshare_share, obj); | ||
100 | } | ||
101 | |||
102 | EAPI const void * | ||
103 | eina_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 | |||
111 | EAPI const void * | ||
112 | eina_binshare_ref(const void *obj) | ||
113 | { | ||
114 | return eina_share_common_ref(binshare_share, obj); | ||
115 | } | ||
116 | |||
117 | EAPI int | ||
118 | eina_binshare_length(const void *obj) | ||
119 | { | ||
120 | return eina_share_common_length(binshare_share, obj); | ||
121 | } | ||
122 | |||
123 | EAPI void | ||
124 | eina_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 | |||
49 | static const char look_up_table[] = {'0', '1', '2', '3', '4', | ||
50 | '5', '6', '7', '8', '9', | ||
51 | 'a', 'b', 'c', 'd', 'e', 'f'}; | ||
52 | static 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 | |||
66 | static 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 | |||
91 | EAPI Eina_Error EINA_ERROR_CONVERT_P_NOT_FOUND = 0; | ||
92 | EAPI Eina_Error EINA_ERROR_CONVERT_0X_NOT_FOUND = 0; | ||
93 | EAPI Eina_Error EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = 0; | ||
94 | |||
95 | static const char EINA_ERROR_CONVERT_0X_NOT_FOUND_STR[] = | ||
96 | "Error during string conversion to float, First '0x' was not found."; | ||
97 | static const char EINA_ERROR_CONVERT_P_NOT_FOUND_STR[] = | ||
98 | "Error during string conversion to float, First 'p' was not found."; | ||
99 | static 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 | */ | ||
122 | Eina_Bool | ||
123 | eina_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 | */ | ||
153 | Eina_Bool | ||
154 | eina_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 | |||
169 | EAPI int | ||
170 | eina_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 | |||
195 | EAPI int | ||
196 | eina_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 | |||
214 | EAPI Eina_Bool | ||
215 | eina_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 | |||
307 | on_length_error: | ||
308 | eina_error_set(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH); | ||
309 | return EINA_FALSE; | ||
310 | } | ||
311 | |||
312 | EAPI int | ||
313 | eina_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 | |||
375 | EAPI int | ||
376 | eina_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 | |||
459 | EAPI Eina_Bool | ||
460 | eina_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 | ||
58 | typedef struct timespec Eina_Nano_Time; | ||
59 | #else | ||
60 | typedef LARGE_INTEGER Eina_Nano_Time; | ||
61 | #endif | ||
62 | |||
63 | typedef struct _Eina_Clock Eina_Clock; | ||
64 | |||
65 | struct _Eina_Counter | ||
66 | { | ||
67 | EINA_INLIST; | ||
68 | |||
69 | Eina_Inlist *clocks; | ||
70 | const char *name; | ||
71 | }; | ||
72 | |||
73 | struct _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 | ||
85 | static 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 | ||
107 | static const char EINA_ERROR_COUNTER_WINDOWS_STR[] = | ||
108 | "Change your OS, you moron !"; | ||
109 | static int EINA_ERROR_COUNTER_WINDOWS = 0; | ||
110 | static LARGE_INTEGER _eina_counter_frequency; | ||
111 | |||
112 | static inline int | ||
113 | _eina_counter_time_get(Eina_Nano_Time *tp) | ||
114 | { | ||
115 | return QueryPerformanceCounter(tp); | ||
116 | } | ||
117 | #endif /* _WIN2 */ | ||
118 | |||
119 | static 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 | */ | ||
184 | Eina_Bool | ||
185 | eina_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 | */ | ||
211 | Eina_Bool | ||
212 | eina_counter_shutdown(void) | ||
213 | { | ||
214 | return EINA_TRUE; | ||
215 | } | ||
216 | |||
217 | /*============================================================================* | ||
218 | * API * | ||
219 | *============================================================================*/ | ||
220 | |||
221 | EAPI Eina_Counter * | ||
222 | eina_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 | |||
245 | EAPI void | ||
246 | eina_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 | |||
261 | EAPI void | ||
262 | eina_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 | |||
285 | EAPI void | ||
286 | eina_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 | |||
305 | EAPI char * | ||
306 | eina_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 */ | ||
58 | static 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 | |||
78 | static | ||
79 | void _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 | */ | ||
124 | EAPI 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 | |||
133 | EAPI 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 | |||
55 | typedef struct _Eina_Error_Message Eina_Error_Message; | ||
56 | struct _Eina_Error_Message | ||
57 | { | ||
58 | Eina_Bool string_allocated; | ||
59 | const char *string; | ||
60 | }; | ||
61 | |||
62 | static Eina_Error_Message *_eina_errors = NULL; | ||
63 | static size_t _eina_errors_count = 0; | ||
64 | static size_t _eina_errors_allocated = 0; | ||
65 | static Eina_Error _eina_last_error; | ||
66 | |||
67 | static 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 | |||
108 | EAPI Eina_Error EINA_ERROR_OUT_OF_MEMORY = 0; | ||
109 | |||
110 | static 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 | */ | ||
129 | Eina_Bool | ||
130 | eina_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 | */ | ||
149 | Eina_Bool | ||
150 | eina_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 | |||
173 | EAPI Eina_Error | ||
174 | eina_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 | |||
195 | EAPI Eina_Error | ||
196 | eina_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 | |||
211 | EAPI Eina_Bool | ||
212 | eina_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 | |||
237 | EAPI const char * | ||
238 | eina_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 | |||
249 | EAPI Eina_Error | ||
250 | eina_error_get(void) | ||
251 | { | ||
252 | return _eina_last_error; | ||
253 | } | ||
254 | |||
255 | EAPI void | ||
256 | eina_error_set(Eina_Error err) | ||
257 | { | ||
258 | _eina_last_error = err; | ||
259 | } | ||
260 | |||
261 | EAPI Eina_Error | ||
262 | eina_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 | ||
36 | extern "C" | ||
37 | # endif | ||
38 | void *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 | |||
98 | typedef struct _Eina_File_Iterator Eina_File_Iterator; | ||
99 | typedef struct _Eina_File_Map Eina_File_Map; | ||
100 | |||
101 | struct _Eina_File_Iterator | ||
102 | { | ||
103 | Eina_Iterator iterator; | ||
104 | |||
105 | DIR *dirp; | ||
106 | int length; | ||
107 | |||
108 | char dir[1]; | ||
109 | }; | ||
110 | |||
111 | struct _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 | |||
137 | struct _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 | |||
149 | static Eina_Hash *_eina_file_cache = NULL; | ||
150 | static Eina_Lock _eina_file_lock_cache; | ||
151 | |||
152 | static 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 | */ | ||
159 | static 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 | |||
191 | static 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 | |||
202 | static 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 | |||
237 | static DIR * | ||
238 | _eina_file_ls_iterator_container(Eina_File_Iterator *it) | ||
239 | { | ||
240 | return it->dirp; | ||
241 | } | ||
242 | |||
243 | static 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 | |||
252 | typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; | ||
253 | struct _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 | |||
265 | static 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 | |||
336 | static DIR * | ||
337 | _eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) | ||
338 | { | ||
339 | return it->dirp; | ||
340 | } | ||
341 | |||
342 | static 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 | |||
351 | static 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 | |||
394 | static 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 | |||
410 | static void | ||
411 | _eina_file_map_close(Eina_File_Map *map) | ||
412 | { | ||
413 | munmap(map->map, map->length); | ||
414 | free(map); | ||
415 | } | ||
416 | |||
417 | static unsigned int | ||
418 | _eina_file_map_key_length(const void *key __UNUSED__) | ||
419 | { | ||
420 | return sizeof (unsigned long int) * 2; | ||
421 | } | ||
422 | |||
423 | static 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 | |||
431 | static 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 | ||
439 | static 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 | |||
457 | static 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 | |||
483 | static 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 | |||
501 | static void | ||
502 | slprintf(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 | |||
514 | static 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 | |||
584 | Eina_Bool | ||
585 | eina_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 | |||
609 | Eina_Bool | ||
610 | eina_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 | |||
644 | EAPI char * | ||
645 | eina_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 | |||
673 | EAPI Eina_Bool | ||
674 | eina_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 | |||
705 | EAPI Eina_Array * | ||
706 | eina_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 | |||
738 | EAPI Eina_Iterator * | ||
739 | eina_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 | |||
778 | EAPI Eina_Iterator * | ||
779 | eina_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 | |||
830 | EAPI Eina_Iterator * | ||
831 | eina_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 | |||
882 | EAPI Eina_File * | ||
883 | eina_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 | |||
989 | EAPI void | ||
990 | eina_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 | |||
1007 | EAPI size_t | ||
1008 | eina_file_size_get(Eina_File *file) | ||
1009 | { | ||
1010 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); | ||
1011 | return file->length; | ||
1012 | } | ||
1013 | |||
1014 | EAPI time_t | ||
1015 | eina_file_mtime_get(Eina_File *file) | ||
1016 | { | ||
1017 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); | ||
1018 | return file->mtime; | ||
1019 | } | ||
1020 | |||
1021 | EAPI const char * | ||
1022 | eina_file_filename_get(Eina_File *file) | ||
1023 | { | ||
1024 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); | ||
1025 | return file->filename; | ||
1026 | } | ||
1027 | |||
1028 | EAPI void * | ||
1029 | eina_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 | |||
1072 | EAPI void * | ||
1073 | eina_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 | |||
1148 | EAPI void | ||
1149 | eina_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 | ||
35 | extern "C" | ||
36 | # endif | ||
37 | void *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 | |||
88 | typedef struct _Eina_File_Iterator Eina_File_Iterator; | ||
89 | typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; | ||
90 | typedef struct _Eina_File_Map Eina_File_Map; | ||
91 | |||
92 | struct _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 | |||
104 | struct _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 | |||
118 | struct _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 | |||
139 | struct _Eina_File_Map | ||
140 | { | ||
141 | void *map; | ||
142 | |||
143 | unsigned long int offset; | ||
144 | unsigned long int length; | ||
145 | |||
146 | int refcount; | ||
147 | }; | ||
148 | |||
149 | static Eina_Hash *_eina_file_cache = NULL; | ||
150 | static Eina_List *_eina_file_cache_lru = NULL; | ||
151 | static Eina_List *_eina_file_cache_delete = NULL; | ||
152 | |||
153 | static int _eina_file_log_dom = -1; | ||
154 | |||
155 | static 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 | |||
168 | static 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 | |||
197 | static 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 | |||
216 | static 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 | |||
247 | static 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 | |||
313 | static HANDLE | ||
314 | _eina_file_win32_ls_iterator_container(Eina_File_Iterator *it) | ||
315 | { | ||
316 | return it->handle; | ||
317 | } | ||
318 | |||
319 | static 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 | |||
329 | static 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 | |||
427 | static HANDLE | ||
428 | _eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) | ||
429 | { | ||
430 | return it->handle; | ||
431 | } | ||
432 | |||
433 | static 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 | |||
443 | static 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 | |||
460 | static 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 | |||
468 | static unsigned int | ||
469 | _eina_file_map_key_length(const void *key __UNUSED__) | ||
470 | { | ||
471 | return sizeof (unsigned long int) * 2; | ||
472 | } | ||
473 | |||
474 | static 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 | |||
482 | static 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 | |||
489 | Eina_Bool | ||
490 | eina_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 | |||
512 | Eina_Bool | ||
513 | eina_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 | |||
555 | EAPI Eina_Bool | ||
556 | eina_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 | |||
620 | EAPI Eina_Array * | ||
621 | eina_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 | |||
653 | EAPI Eina_Iterator * | ||
654 | eina_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 | |||
703 | EAPI Eina_Iterator * | ||
704 | eina_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 | |||
760 | EAPI Eina_Iterator * | ||
761 | eina_file_stat_ls(const char *dir) | ||
762 | { | ||
763 | return eina_file_direct_ls(dir); | ||
764 | } | ||
765 | |||
766 | EAPI Eina_File * | ||
767 | eina_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 | |||
875 | EAPI void | ||
876 | eina_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 | |||
893 | EAPI size_t | ||
894 | eina_file_size_get(Eina_File *file) | ||
895 | { | ||
896 | return file->length; | ||
897 | } | ||
898 | |||
899 | EAPI time_t | ||
900 | eina_file_mtime_get(Eina_File *file) | ||
901 | { | ||
902 | return file->mtime; | ||
903 | } | ||
904 | |||
905 | EAPI const char * | ||
906 | eina_file_filename_get(Eina_File *file) | ||
907 | { | ||
908 | return file->filename; | ||
909 | } | ||
910 | |||
911 | EAPI void * | ||
912 | eina_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 | |||
935 | EAPI void * | ||
936 | eina_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 | |||
989 | EAPI void | ||
990 | eina_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 | ||
12 | static 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 | |||
426 | EAPI Eina_F32p32 | ||
427 | eina_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 | |||
478 | EAPI Eina_F32p32 | ||
479 | eina_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 | |||
38 | const char *_eina_hamster_time = __TIME__; | ||
39 | const char *_eina_hamster_date = __DATE__; | ||
40 | static int _eina_hamsters = -1; | ||
41 | |||
42 | /** | ||
43 | * @endcond | ||
44 | */ | ||
45 | |||
46 | /*============================================================================* | ||
47 | * Global * | ||
48 | *============================================================================*/ | ||
49 | |||
50 | /*============================================================================* | ||
51 | * API * | ||
52 | *============================================================================*/ | ||
53 | |||
54 | EAPI int | ||
55 | eina_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 | |||
73 | typedef struct _Eina_Hash_Head Eina_Hash_Head; | ||
74 | typedef struct _Eina_Hash_Element Eina_Hash_Element; | ||
75 | typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data; | ||
76 | typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash; | ||
77 | typedef struct _Eina_Hash_Each Eina_Hash_Each; | ||
78 | |||
79 | struct _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 | |||
95 | struct _Eina_Hash_Head | ||
96 | { | ||
97 | EINA_RBTREE; | ||
98 | int hash; | ||
99 | |||
100 | Eina_Rbtree *head; | ||
101 | }; | ||
102 | |||
103 | struct _Eina_Hash_Element | ||
104 | { | ||
105 | EINA_RBTREE; | ||
106 | Eina_Hash_Tuple tuple; | ||
107 | Eina_Bool begin : 1; | ||
108 | }; | ||
109 | |||
110 | struct _Eina_Hash_Foreach_Data | ||
111 | { | ||
112 | Eina_Hash_Foreach cb; | ||
113 | const void *fdata; | ||
114 | }; | ||
115 | |||
116 | typedef 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 | |||
120 | struct _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 | |||
138 | struct _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 | |||
156 | static 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 | |||
165 | static 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 | |||
176 | static 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 | |||
195 | static 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 | |||
211 | static inline Eina_Bool | ||
212 | eina_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 | |||
304 | on_error: | ||
305 | eina_error_set(error); | ||
306 | return EINA_FALSE; | ||
307 | } | ||
308 | |||
309 | static 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 | |||
334 | static 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 | |||
367 | static 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 | |||
403 | static 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 | |||
413 | static 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 | |||
420 | static 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 | |||
454 | static 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 | |||
483 | static 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 | |||
503 | static 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 | |||
512 | static 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 | |||
519 | static 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 | |||
526 | static unsigned int | ||
527 | _eina_int32_key_length(__UNUSED__ const uint32_t *key) | ||
528 | { | ||
529 | return 4; | ||
530 | } | ||
531 | |||
532 | static 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 | |||
539 | static unsigned int | ||
540 | _eina_int64_key_length(__UNUSED__ const uint32_t *key) | ||
541 | { | ||
542 | return 8; | ||
543 | } | ||
544 | |||
545 | static 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 | |||
552 | static 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 | |||
563 | static 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 | |||
578 | static 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 | |||
593 | static 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 | |||
608 | static 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 | |||
684 | static 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 | |||
691 | static 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 | |||
716 | EAPI void | ||
717 | eina_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 | |||
725 | EAPI Eina_Hash * | ||
726 | eina_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 | |||
759 | on_error: | ||
760 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
761 | return NULL; | ||
762 | } | ||
763 | |||
764 | EAPI Eina_Hash * | ||
765 | eina_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 | |||
774 | EAPI Eina_Hash * | ||
775 | eina_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 | |||
784 | EAPI Eina_Hash * | ||
785 | eina_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 | |||
794 | EAPI Eina_Hash * | ||
795 | eina_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 | |||
804 | EAPI Eina_Hash * | ||
805 | eina_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 | |||
814 | EAPI Eina_Hash * | ||
815 | eina_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 | |||
832 | EAPI Eina_Hash * | ||
833 | eina_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 | |||
842 | EAPI int | ||
843 | eina_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 | |||
852 | EAPI void | ||
853 | eina_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 | |||
869 | EAPI void | ||
870 | eina_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 | |||
888 | EAPI Eina_Bool | ||
889 | eina_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 | |||
903 | EAPI Eina_Bool | ||
904 | eina_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 | |||
913 | EAPI Eina_Bool | ||
914 | eina_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 | |||
931 | EAPI Eina_Bool | ||
932 | eina_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 | |||
949 | EAPI Eina_Bool | ||
950 | eina_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 | |||
961 | EAPI Eina_Bool | ||
962 | eina_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 | |||
970 | EAPI Eina_Bool | ||
971 | eina_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 | |||
990 | error: | ||
991 | return EINA_FALSE; | ||
992 | } | ||
993 | |||
994 | EAPI Eina_Bool | ||
995 | eina_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 | |||
1014 | EAPI Eina_Bool | ||
1015 | eina_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 | |||
1026 | EAPI void * | ||
1027 | eina_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 | |||
1053 | EAPI void * | ||
1054 | eina_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 | |||
1072 | EAPI void * | ||
1073 | eina_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 | |||
1103 | EAPI void * | ||
1104 | eina_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 | } | ||
1153 | EAPI void * | ||
1154 | eina_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 | |||
1171 | EAPI Eina_Bool | ||
1172 | eina_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 | |||
1195 | error: | ||
1196 | return result; | ||
1197 | } | ||
1198 | |||
1199 | /*============================================================================* | ||
1200 | * Iterator * | ||
1201 | *============================================================================*/ | ||
1202 | |||
1203 | EAPI void | ||
1204 | eina_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 | |||
1226 | EAPI Eina_Iterator * | ||
1227 | eina_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 | |||
1257 | EAPI Eina_Iterator * | ||
1258 | eina_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 | |||
1289 | EAPI Eina_Iterator * | ||
1290 | eina_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/) */ | ||
1325 | EAPI int | ||
1326 | eina_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 | |||
49 | typedef struct _Eina_Iterator_Inlist Eina_Iterator_Inlist; | ||
50 | typedef struct _Eina_Accessor_Inlist Eina_Accessor_Inlist; | ||
51 | |||
52 | struct _Eina_Iterator_Inlist | ||
53 | { | ||
54 | Eina_Iterator iterator; | ||
55 | const Eina_Inlist *head; | ||
56 | const Eina_Inlist *current; | ||
57 | }; | ||
58 | |||
59 | struct _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 | |||
69 | struct _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 | |||
79 | static Eina_Bool | ||
80 | eina_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 | |||
92 | static Eina_Inlist * | ||
93 | eina_inlist_iterator_get_container(Eina_Iterator_Inlist *it) { | ||
94 | return (Eina_Inlist *)it->head; | ||
95 | } | ||
96 | |||
97 | static void | ||
98 | eina_inlist_iterator_free(Eina_Iterator_Inlist *it) { | ||
99 | free(it); | ||
100 | } | ||
101 | |||
102 | static Eina_Bool | ||
103 | eina_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 | |||
148 | static Eina_Inlist * | ||
149 | eina_inlist_accessor_get_container(Eina_Accessor_Inlist *it) { | ||
150 | return (Eina_Inlist *)it->head; | ||
151 | } | ||
152 | |||
153 | static void | ||
154 | eina_inlist_accessor_free(Eina_Accessor_Inlist *it) { | ||
155 | free(it); | ||
156 | } | ||
157 | |||
158 | static Eina_Inlist * | ||
159 | eina_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 | |||
179 | static Eina_Inlist * | ||
180 | eina_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 | |||
193 | static 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 | |||
221 | EAPI Eina_Inlist * | ||
222 | eina_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 | |||
248 | EAPI Eina_Inlist * | ||
249 | eina_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 | |||
268 | EAPI Eina_Inlist * | ||
269 | eina_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 | |||
296 | EAPI Eina_Inlist * | ||
297 | eina_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 | |||
329 | EAPI Eina_Inlist * | ||
330 | eina_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 | |||
367 | EAPI Eina_Inlist * | ||
368 | eina_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 | |||
394 | EAPI Eina_Inlist * | ||
395 | eina_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 | |||
428 | EAPI Eina_Inlist * | ||
429 | eina_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 | |||
440 | EAPI unsigned int | ||
441 | eina_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 | |||
452 | EAPI int | ||
453 | eina_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 | |||
482 | EAPI Eina_Inlist_Sorted_State * | ||
483 | eina_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 | |||
495 | EAPI void | ||
496 | eina_inlist_sorted_state_free(Eina_Inlist_Sorted_State *state) | ||
497 | { | ||
498 | free(state); | ||
499 | } | ||
500 | |||
501 | static 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 | |||
550 | EAPI Eina_Inlist * | ||
551 | eina_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 | |||
658 | EAPI Eina_Inlist * | ||
659 | eina_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 | |||
801 | EAPI Eina_Inlist * | ||
802 | eina_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 | |||
856 | EAPI Eina_Iterator * | ||
857 | eina_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 | |||
883 | EAPI Eina_Accessor * | ||
884 | eina_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 | |||
40 | static 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 | */ | ||
68 | Eina_Bool | ||
69 | eina_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 | */ | ||
85 | Eina_Bool | ||
86 | eina_iterator_shutdown(void) | ||
87 | { | ||
88 | return EINA_TRUE; | ||
89 | } | ||
90 | |||
91 | /*============================================================================* | ||
92 | * API * | ||
93 | *============================================================================*/ | ||
94 | |||
95 | EAPI void | ||
96 | eina_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 | |||
104 | EAPI void * | ||
105 | eina_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 | |||
113 | EAPI Eina_Bool | ||
114 | eina_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 | |||
126 | EAPI void | ||
127 | eina_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 | |||
152 | EAPI Eina_Bool | ||
153 | eina_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 | |||
163 | EAPI Eina_Bool | ||
164 | eina_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 | |||
40 | struct _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 | |||
68 | EAPI 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 | |||
91 | EAPI 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 | |||
99 | EAPI 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 | |||
120 | EAPI 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 | |||
87 | static const char EINA_MAGIC_LIST_STR[] = "Eina List"; | ||
88 | static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator"; | ||
89 | static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor"; | ||
90 | static 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 | |||
131 | typedef struct _Eina_Iterator_List Eina_Iterator_List; | ||
132 | typedef struct _Eina_Accessor_List Eina_Accessor_List; | ||
133 | |||
134 | struct _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 | |||
144 | struct _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 | |||
156 | static Eina_Mempool *_eina_list_mp = NULL; | ||
157 | static Eina_Mempool *_eina_list_accounting_mp = NULL; | ||
158 | static 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 | |||
170 | static 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 | } | ||
185 | static 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 | |||
194 | static 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 | } | ||
207 | static 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 | |||
220 | static 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 | |||
234 | on_error: | ||
235 | _eina_list_mempool_list_free(list); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | static 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 | ||
250 | static Eina_Mempool2 _eina_list_mempool = | ||
251 | { | ||
252 | sizeof(Eina_List), | ||
253 | 320, | ||
254 | 0, NULL, NULL | ||
255 | }; | ||
256 | static Eina_Mempool2 _eina_list_accounting_mempool = | ||
257 | { | ||
258 | sizeof(Eina_List_Accounting), | ||
259 | 80, | ||
260 | 0, NULL, NULL | ||
261 | }; | ||
262 | #endif | ||
263 | |||
264 | static Eina_Bool | ||
265 | eina_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 | |||
279 | static Eina_Bool | ||
280 | eina_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 | |||
294 | static Eina_List * | ||
295 | eina_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 | |||
302 | static void | ||
303 | eina_list_iterator_free(Eina_Iterator_List *it) | ||
304 | { | ||
305 | EINA_MAGIC_CHECK_LIST_ITERATOR(it); | ||
306 | |||
307 | MAGIC_FREE(it); | ||
308 | } | ||
309 | |||
310 | static Eina_Bool | ||
311 | eina_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 | |||
372 | static Eina_List * | ||
373 | eina_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 | |||
380 | static void | ||
381 | eina_list_accessor_free(Eina_Accessor_List *it) | ||
382 | { | ||
383 | EINA_MAGIC_CHECK_LIST_ACCESSOR(it); | ||
384 | |||
385 | MAGIC_FREE(it); | ||
386 | } | ||
387 | |||
388 | static Eina_List * | ||
389 | eina_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 | |||
404 | static Eina_List * | ||
405 | eina_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 | */ | ||
448 | Eina_Bool | ||
449 | eina_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 | |||
497 | on_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 | */ | ||
514 | Eina_Bool | ||
515 | eina_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 | |||
529 | EAPI Eina_List * | ||
530 | eina_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 | |||
559 | EAPI Eina_List * | ||
560 | eina_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 | |||
585 | EAPI Eina_List * | ||
586 | eina_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 | |||
605 | EAPI Eina_List * | ||
606 | eina_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 | |||
638 | EAPI Eina_List * | ||
639 | eina_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 | |||
657 | EAPI Eina_List * | ||
658 | eina_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 | |||
691 | EAPI Eina_List * | ||
692 | eina_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 | |||
707 | EAPI Eina_List * | ||
708 | eina_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 | |||
719 | EAPI Eina_List * | ||
720 | eina_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 | |||
753 | EAPI Eina_List * | ||
754 | eina_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 | |||
774 | EAPI Eina_List * | ||
775 | eina_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 | |||
817 | EAPI Eina_List * | ||
818 | eina_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 | |||
855 | EAPI void * | ||
856 | eina_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 | |||
864 | EAPI Eina_Bool | ||
865 | eina_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 | |||
884 | EAPI Eina_Bool | ||
885 | eina_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 | |||
899 | EAPI Eina_List * | ||
900 | eina_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 | |||
917 | EAPI void * | ||
918 | eina_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 | |||
926 | EAPI Eina_List * | ||
927 | eina_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 | |||
961 | EAPI Eina_List * | ||
962 | eina_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 | |||
990 | EAPI Eina_List * | ||
991 | eina_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 | |||
1009 | EAPI Eina_List * | ||
1010 | eina_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 | |||
1028 | EAPI Eina_List * | ||
1029 | eina_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 | |||
1097 | EAPI Eina_List * | ||
1098 | eina_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 | |||
1148 | EAPI Eina_List * | ||
1149 | eina_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 | |||
1193 | EAPI Eina_List * | ||
1194 | eina_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 | |||
1270 | EAPI Eina_List * | ||
1271 | eina_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 | |||
1348 | end: | ||
1349 | if (result_cmp) | ||
1350 | *result_cmp = cmp; | ||
1351 | |||
1352 | return (Eina_List *)ct; | ||
1353 | } | ||
1354 | |||
1355 | EAPI Eina_List * | ||
1356 | eina_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 | |||
1374 | EAPI void * | ||
1375 | eina_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 | |||
1382 | EAPI Eina_List * | ||
1383 | eina_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 | |||
1398 | EAPI void * | ||
1399 | eina_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 | |||
1407 | EAPI Eina_Iterator * | ||
1408 | eina_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 | |||
1435 | EAPI Eina_Iterator * | ||
1436 | eina_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 | |||
1463 | EAPI Eina_Accessor * | ||
1464 | eina_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. | ||
77 | typedef struct _Eina_Log_Domain_Level_Pending Eina_Log_Domain_Level_Pending; | ||
78 | struct _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 | */ | ||
90 | static Eina_Inlist *_pending_list = NULL; | ||
91 | static Eina_Inlist *_glob_list = NULL; | ||
92 | |||
93 | // Disable color flag (can be changed through the env var | ||
94 | // EINA_LOG_ENV_COLOR_DISABLE). | ||
95 | static Eina_Bool _disable_color = EINA_FALSE; | ||
96 | static Eina_Bool _disable_file = EINA_FALSE; | ||
97 | static Eina_Bool _disable_function = EINA_FALSE; | ||
98 | static Eina_Bool _abort_on_critical = EINA_FALSE; | ||
99 | static int _abort_level_on_critical = EINA_LOG_LEVEL_CRITICAL; | ||
100 | |||
101 | #ifdef EFL_HAVE_THREADS | ||
102 | |||
103 | static Eina_Bool _threads_enabled = EINA_FALSE; | ||
104 | static Eina_Bool _threads_inited = EINA_FALSE; | ||
105 | |||
106 | # ifdef EFL_HAVE_POSIX_THREADS | ||
107 | |||
108 | typedef pthread_t Thread; | ||
109 | |||
110 | static 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 | |||
128 | static pthread_spinlock_t _log_lock; | ||
129 | |||
130 | static 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 | |||
165 | static 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 | |||
175 | typedef DWORD Thread; | ||
176 | |||
177 | static 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 | |||
192 | static 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 | ||
215 | static Eina_Log_Domain *_log_domains = NULL; | ||
216 | static unsigned int _log_domains_count = 0; | ||
217 | static size_t _log_domains_allocated = 0; | ||
218 | |||
219 | // Default function for printing on domains | ||
220 | static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr; | ||
221 | static void *_print_cb_data = NULL; | ||
222 | |||
223 | #ifdef DEBUG | ||
224 | static Eina_Log_Level _log_level = EINA_LOG_LEVEL_DBG; | ||
225 | #elif DEBUG_CRITICAL | ||
226 | static Eina_Log_Level _log_level = EINA_LOG_LEVEL_CRITICAL; | ||
227 | #else | ||
228 | static 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 | */ | ||
235 | static const char *_names[] = { | ||
236 | "CRI", | ||
237 | "ERR", | ||
238 | "WRN", | ||
239 | "INF", | ||
240 | "DBG", | ||
241 | }; | ||
242 | |||
243 | #ifdef _WIN32 | ||
244 | static int | ||
245 | eina_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 | |||
316 | static inline unsigned int | ||
317 | eina_log_pid_get(void) | ||
318 | { | ||
319 | return (unsigned int)getpid(); | ||
320 | } | ||
321 | |||
322 | static inline void | ||
323 | eina_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 | ||
345 | static inline void | ||
346 | eina_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 | ||
370 | static inline void | ||
371 | eina_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 */ | ||
407 | static void | ||
408 | eina_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 | |||
420 | static void | ||
421 | eina_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 | |||
433 | static void | ||
434 | eina_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 */ | ||
447 | static void | ||
448 | eina_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 | |||
488 | static void | ||
489 | eina_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 | |||
526 | static void | ||
527 | eina_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 | ||
560 | static void | ||
561 | eina_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 | |||
583 | static void | ||
584 | eina_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 | |||
606 | static void | ||
607 | eina_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 */ | ||
631 | static void | ||
632 | eina_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 | |||
705 | static void | ||
706 | eina_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 | |||
774 | static void | ||
775 | eina_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 | |||
837 | static 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 | |||
843 | static inline void | ||
844 | eina_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 | */ | ||
912 | static const char * | ||
913 | eina_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 | */ | ||
946 | static Eina_Log_Domain * | ||
947 | eina_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 | */ | ||
970 | static void | ||
971 | eina_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 | */ | ||
985 | static void | ||
986 | eina_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 | |||
1022 | parse_end: | ||
1023 | start = strchr(tmp, ','); | ||
1024 | if (start) | ||
1025 | start++; | ||
1026 | else | ||
1027 | break; | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | static void | ||
1032 | eina_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 | |||
1068 | parse_end: | ||
1069 | start = strchr(tmp, ','); | ||
1070 | if (start) | ||
1071 | start++; | ||
1072 | else | ||
1073 | break; | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | static inline int | ||
1078 | eina_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 | |||
1122 | finish_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 | |||
1156 | static inline Eina_Bool | ||
1157 | eina_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 | |||
1200 | static inline void | ||
1201 | eina_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 | |||
1213 | static inline void | ||
1214 | eina_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 | */ | ||
1321 | Eina_Bool | ||
1322 | eina_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 | */ | ||
1413 | Eina_Bool | ||
1414 | eina_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 | */ | ||
1460 | void | ||
1461 | eina_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 | */ | ||
1478 | void | ||
1479 | eina_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 | |||
1498 | EAPI int EINA_LOG_DOMAIN_GLOBAL = 0; | ||
1499 | |||
1500 | /** | ||
1501 | * @endcond | ||
1502 | */ | ||
1503 | |||
1504 | EAPI void | ||
1505 | eina_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 | |||
1515 | EAPI void | ||
1516 | eina_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 | |||
1525 | EAPI void | ||
1526 | eina_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 | |||
1534 | EAPI int | ||
1535 | eina_log_level_get(void) | ||
1536 | { | ||
1537 | return _log_level; | ||
1538 | } | ||
1539 | |||
1540 | EAPI Eina_Bool | ||
1541 | eina_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 | |||
1550 | EAPI void | ||
1551 | eina_log_color_disable_set(Eina_Bool disabled) | ||
1552 | { | ||
1553 | _disable_color = disabled; | ||
1554 | } | ||
1555 | |||
1556 | EAPI Eina_Bool | ||
1557 | eina_log_color_disable_get(void) | ||
1558 | { | ||
1559 | return _disable_color; | ||
1560 | } | ||
1561 | |||
1562 | EAPI void | ||
1563 | eina_log_file_disable_set(Eina_Bool disabled) | ||
1564 | { | ||
1565 | _disable_file = disabled; | ||
1566 | } | ||
1567 | |||
1568 | EAPI Eina_Bool | ||
1569 | eina_log_file_disable_get(void) | ||
1570 | { | ||
1571 | return _disable_file; | ||
1572 | } | ||
1573 | |||
1574 | EAPI void | ||
1575 | eina_log_function_disable_set(Eina_Bool disabled) | ||
1576 | { | ||
1577 | _disable_function = disabled; | ||
1578 | } | ||
1579 | |||
1580 | EAPI Eina_Bool | ||
1581 | eina_log_function_disable_get(void) | ||
1582 | { | ||
1583 | return _disable_function; | ||
1584 | } | ||
1585 | |||
1586 | EAPI void | ||
1587 | eina_log_abort_on_critical_set(Eina_Bool abort_on_critical) | ||
1588 | { | ||
1589 | _abort_on_critical = abort_on_critical; | ||
1590 | } | ||
1591 | |||
1592 | EAPI Eina_Bool | ||
1593 | eina_log_abort_on_critical_get(void) | ||
1594 | { | ||
1595 | return _abort_on_critical; | ||
1596 | } | ||
1597 | |||
1598 | EAPI void | ||
1599 | eina_log_abort_on_critical_level_set(int critical_level) | ||
1600 | { | ||
1601 | _abort_level_on_critical = critical_level; | ||
1602 | } | ||
1603 | |||
1604 | EAPI int | ||
1605 | eina_log_abort_on_critical_level_get(void) | ||
1606 | { | ||
1607 | return _abort_level_on_critical; | ||
1608 | } | ||
1609 | |||
1610 | EAPI int | ||
1611 | eina_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 | |||
1623 | EAPI void | ||
1624 | eina_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 | |||
1632 | EAPI void | ||
1633 | eina_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 | |||
1677 | EAPI int | ||
1678 | eina_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 | |||
1716 | EAPI int | ||
1717 | eina_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 | |||
1727 | EAPI void | ||
1728 | eina_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 | |||
1742 | EAPI void | ||
1743 | eina_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 | |||
1757 | EAPI void | ||
1758 | eina_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 | ||
1786 | end: | ||
1787 | #endif | ||
1788 | vfprintf(f, fmt, args); | ||
1789 | putc('\n', f); | ||
1790 | } | ||
1791 | |||
1792 | EAPI void | ||
1793 | eina_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 | |||
1825 | EAPI void | ||
1826 | eina_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 | |||
47 | typedef struct _Eina_Magic_String Eina_Magic_String; | ||
48 | struct _Eina_Magic_String | ||
49 | { | ||
50 | Eina_Magic magic; | ||
51 | Eina_Bool string_allocated; | ||
52 | const char *string; | ||
53 | }; | ||
54 | |||
55 | static 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 | |||
67 | static Eina_Magic_String *_eina_magic_strings = NULL; | ||
68 | static size_t _eina_magic_strings_count = 0; | ||
69 | static size_t _eina_magic_strings_allocated = 0; | ||
70 | static Eina_Bool _eina_magic_strings_dirty = 0; | ||
71 | |||
72 | static 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 | |||
79 | static 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 | |||
87 | static 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 | */ | ||
143 | Eina_Bool | ||
144 | eina_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 | */ | ||
168 | Eina_Bool | ||
169 | eina_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 | *============================================================================*/ | ||
194 | EAPI const char * | ||
195 | eina_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 | |||
218 | EAPI Eina_Bool | ||
219 | eina_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 | |||
243 | EAPI Eina_Bool | ||
244 | eina_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 | |||
266 | EAPI void | ||
267 | eina_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 | |||
79 | static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV }; | ||
80 | |||
81 | static int _eina_main_count = 0; | ||
82 | #ifdef EFL_HAVE_THREADS | ||
83 | static int _eina_main_thread_count = 0; | ||
84 | #endif | ||
85 | static 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 | |||
97 | EAPI Eina_Bool _eina_threads_activated = EINA_FALSE; | ||
98 | EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0; | ||
99 | |||
100 | static const char EINA_ERROR_NOT_MAIN_LOOP_STR[] = "Main loop thread check failed."; | ||
101 | |||
102 | #ifdef EFL_HAVE_THREADS | ||
103 | # ifdef _WIN32 | ||
104 | EAPI DWORD _eina_main_loop; | ||
105 | # else | ||
106 | EAPI pthread_t _eina_main_loop; | ||
107 | # endif | ||
108 | static pid_t _eina_pid; | ||
109 | #endif | ||
110 | |||
111 | #ifdef MT | ||
112 | static int _mt_enabled = 0; | ||
113 | #endif | ||
114 | |||
115 | #ifdef EFL_HAVE_THREADS | ||
116 | EAPI int _eina_threads_debug = 0; | ||
117 | # if !defined(_WIN32_WCE) && !defined(_WIN32) | ||
118 | EAPI pthread_mutex_t _eina_tracking_lock; | ||
119 | EAPI 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 | |||
154 | struct eina_desc_setup | ||
155 | { | ||
156 | const char *name; | ||
157 | Eina_Bool (*init)(void); | ||
158 | Eina_Bool (*shutdown)(void); | ||
159 | }; | ||
160 | |||
161 | static 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 | }; | ||
189 | static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / | ||
190 | sizeof(_eina_desc_setup[0]); | ||
191 | |||
192 | static 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 | */ | ||
223 | EAPI Eina_Version *eina_version = &_version; | ||
224 | |||
225 | EAPI int | ||
226 | eina_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 | |||
290 | EAPI int | ||
291 | eina_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 | |||
314 | EAPI int | ||
315 | eina_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 | |||
340 | EAPI int | ||
341 | eina_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 | |||
384 | EAPI Eina_Bool | ||
385 | eina_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. */ | ||
416 | EAPI void | ||
417 | eina_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 | |||
60 | static const char EINA_MAGIC_MATRIXSPARSE_STR[] = "Eina Matrixsparse"; | ||
61 | static const char EINA_MAGIC_MATRIXSPARSE_ROW_STR[] = "Eina Matrixsparse Row"; | ||
62 | static const char EINA_MAGIC_MATRIXSPARSE_CELL_STR[] = "Eina Matrixsparse Cell"; | ||
63 | static const char EINA_MAGIC_MATRIXSPARSE_ITERATOR_STR[] = | ||
64 | "Eina Matrixsparse Iterator"; | ||
65 | static const char EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR_STR[] = | ||
66 | "Eina Matrixsparse Row Accessor"; | ||
67 | static const char EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR_STR[] = | ||
68 | "Eina Matrixsparse Row Iterator"; | ||
69 | static const char EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR_STR[] = | ||
70 | "Eina Matrixsparse Cell Accessor"; | ||
71 | static 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 | |||
111 | struct _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 | |||
124 | struct _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 | |||
139 | struct _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 | |||
160 | typedef struct _Eina_Matrixsparse_Iterator Eina_Matrixsparse_Iterator; | ||
161 | typedef struct _Eina_Matrixsparse_Iterator_Complete | ||
162 | Eina_Matrixsparse_Iterator_Complete; | ||
163 | |||
164 | struct _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 | |||
178 | struct _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 | |||
210 | static 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 | |||
222 | static Eina_Mempool *_eina_matrixsparse_cell_mp = NULL; | ||
223 | static Eina_Mempool *_eina_matrixsparse_row_mp = NULL; | ||
224 | |||
225 | static 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 | |||
237 | static 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 | |||
267 | static 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 | |||
281 | static 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 | |||
291 | static 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 | |||
321 | static 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 | |||
364 | static 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 | |||
407 | static 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 | |||
458 | static 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 | |||
510 | static 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 | |||
522 | static 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 | |||
555 | static 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 | |||
588 | static 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 | |||
639 | static 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 | |||
690 | static 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 | *============================================================================*/ | ||
717 | static 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 | |||
740 | static 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 | |||
747 | static 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 | |||
756 | static 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 | |||
800 | static 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 | |||
808 | static 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 | */ | ||
846 | Eina_Bool | ||
847 | eina_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 | |||
903 | on_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 | */ | ||
920 | Eina_Bool | ||
921 | eina_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 | |||
935 | EAPI Eina_Matrixsparse * | ||
936 | eina_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 | |||
967 | EAPI void | ||
968 | eina_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 | |||
991 | EAPI void | ||
992 | eina_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 | |||
1010 | EAPI Eina_Bool | ||
1011 | eina_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 | |||
1114 | EAPI Eina_Bool | ||
1115 | eina_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 | |||
1129 | EAPI void * | ||
1130 | eina_matrixsparse_cell_data_get(const Eina_Matrixsparse_Cell *cell) | ||
1131 | { | ||
1132 | EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, NULL); | ||
1133 | return cell->data; | ||
1134 | } | ||
1135 | |||
1136 | EAPI void * | ||
1137 | eina_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 | |||
1150 | EAPI Eina_Bool | ||
1151 | eina_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 | |||
1172 | EAPI Eina_Bool | ||
1173 | eina_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 | |||
1189 | EAPI Eina_Bool | ||
1190 | eina_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 | |||
1207 | EAPI Eina_Bool | ||
1208 | eina_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 | |||
1236 | EAPI Eina_Bool | ||
1237 | eina_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 | |||
1261 | EAPI Eina_Bool | ||
1262 | eina_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 | |||
1279 | EAPI Eina_Bool | ||
1280 | eina_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 | |||
1318 | EAPI Eina_Bool | ||
1319 | eina_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 | |||
1339 | EAPI Eina_Bool | ||
1340 | eina_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 | |||
1355 | EAPI Eina_Iterator * | ||
1356 | eina_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 | |||
1382 | EAPI Eina_Iterator * | ||
1383 | eina_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 | |||
47 | static Eina_Hash *_backends; | ||
48 | static Eina_Array *_modules; | ||
49 | static 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 | |||
62 | static 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 | |||
106 | on_error: | ||
107 | eina_error_set(err); | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | /* Built-in backend's prototypes */ | ||
112 | |||
113 | #ifdef EINA_STATIC_BUILD_BUDDY | ||
114 | Eina_Bool buddy_init(void); | ||
115 | void buddy_shutdown(void); | ||
116 | #endif | ||
117 | |||
118 | #ifdef EINA_STATIC_BUILD_CHAINED_POOL | ||
119 | Eina_Bool chained_init(void); | ||
120 | void chained_shutdown(void); | ||
121 | #endif | ||
122 | |||
123 | #ifdef EINA_STATIC_BUILD_EMEMOA_FIXED | ||
124 | Eina_Bool ememoa_fixed_init(void); | ||
125 | void ememoa_fixed_shutdown(void); | ||
126 | #endif | ||
127 | |||
128 | #ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN | ||
129 | Eina_Bool ememoa_unknown_init(void); | ||
130 | void ememoa_unknown_shutdown(void); | ||
131 | #endif | ||
132 | |||
133 | #ifdef EINA_STATIC_BUILD_FIXED_BITMAP | ||
134 | Eina_Bool fixed_bitmap_init(void); | ||
135 | void fixed_bitmap_shutdown(void); | ||
136 | #endif | ||
137 | |||
138 | #ifdef EINA_STATIC_BUILD_ONE_BIG | ||
139 | Eina_Bool one_big_init(void); | ||
140 | void one_big_shutdown(void); | ||
141 | #endif | ||
142 | |||
143 | #ifdef EINA_STATIC_BUILD_PASS_THROUGH | ||
144 | Eina_Bool pass_through_init(void); | ||
145 | void pass_through_shutdown(void); | ||
146 | #endif | ||
147 | |||
148 | /** | ||
149 | * @endcond | ||
150 | */ | ||
151 | |||
152 | /*============================================================================* | ||
153 | * Global * | ||
154 | *============================================================================*/ | ||
155 | |||
156 | /** | ||
157 | * @cond LOCAL | ||
158 | */ | ||
159 | |||
160 | EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0; | ||
161 | |||
162 | static const char EINA_ERROR_NOT_MEMPOOL_MODULE_STR[] = | ||
163 | "Not a memory pool module."; | ||
164 | |||
165 | /** | ||
166 | * @endcond | ||
167 | */ | ||
168 | |||
169 | EAPI Eina_Bool | ||
170 | eina_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 | |||
177 | EAPI void | ||
178 | eina_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 | |||
185 | Eina_Bool | ||
186 | eina_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 | |||
258 | mempool_init_error: | ||
259 | eina_log_domain_unregister(_eina_mempool_log_dom); | ||
260 | _eina_mempool_log_dom = -1; | ||
261 | |||
262 | return EINA_FALSE; | ||
263 | } | ||
264 | |||
265 | Eina_Bool | ||
266 | eina_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 | |||
308 | EAPI Eina_Mempool * | ||
309 | eina_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 | |||
331 | EAPI 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 | |||
341 | EAPI 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 | |||
350 | EAPI 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 | |||
358 | EAPI 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 | |||
366 | EAPI unsigned int | ||
367 | eina_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 | |||
61 | static Eina_Bool mmap_safe = EINA_FALSE; | ||
62 | #ifdef HAVE_SIGINFO_T | ||
63 | |||
64 | static int _eina_mmap_log_dom = -1; | ||
65 | static int _eina_mmap_zero_fd = -1; | ||
66 | static 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 | |||
78 | static 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 | |||
122 | EAPI Eina_Bool | ||
123 | eina_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 | |||
181 | EAPI Eina_Bool | ||
182 | eina_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 | ||
35 | extern "C" | ||
36 | # endif | ||
37 | void *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 | |||
78 | static 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 | |||
105 | struct _Eina_Module | ||
106 | { | ||
107 | void *handle; | ||
108 | int ref; | ||
109 | const char file[]; | ||
110 | }; | ||
111 | |||
112 | typedef 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 | |||
119 | typedef struct _Dir_List_Cb_Data | ||
120 | { | ||
121 | Eina_Module_Cb cb; | ||
122 | void *data; | ||
123 | } Dir_List_Cb_Data; | ||
124 | |||
125 | static 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 | |||
139 | static 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 | |||
171 | static 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 | |||
205 | static const char EINA_ERROR_WRONG_MODULE_STR[] = | ||
206 | "Wrong file format or no file module found"; | ||
207 | static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] = | ||
208 | "Module initialisation function failed"; | ||
209 | |||
210 | EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0; | ||
211 | EAPI 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 | */ | ||
232 | Eina_Bool | ||
233 | eina_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 | */ | ||
262 | Eina_Bool | ||
263 | eina_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 | |||
278 | EAPI 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 | |||
305 | EAPI 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 | |||
319 | EAPI 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; | ||
352 | ok: | ||
353 | DBG("successfully loaded %s", m->file); | ||
354 | m->handle = dl_handle; | ||
355 | loaded: | ||
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 | |||
367 | EAPI 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 | |||
395 | EAPI 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 | |||
408 | EAPI 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 | |||
414 | EAPI 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 | |||
456 | EAPI 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 | |||
490 | EAPI 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 | |||
508 | EAPI 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 | |||
532 | EAPI Eina_Module * | ||
533 | eina_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 | |||
563 | EAPI 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 | |||
575 | EAPI 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 | |||
587 | EAPI 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 | ||
43 | extern "C" | ||
44 | # endif | ||
45 | void *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 | |||
95 | struct _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 | |||
137 | static int _eina_prefix_log_dom = -1; | ||
138 | |||
139 | static 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 | ||
177 | static 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 | |||
231 | static 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 | |||
315 | static 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 | |||
338 | static 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 | |||
378 | EAPI Eina_Prefix * | ||
379 | eina_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 | |||
658 | EAPI void | ||
659 | eina_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 | |||
672 | EAPI const char * | ||
673 | eina_prefix_get(Eina_Prefix *pfx) | ||
674 | { | ||
675 | if (!pfx) return ""; | ||
676 | return pfx->prefix_path; | ||
677 | } | ||
678 | |||
679 | EAPI const char * | ||
680 | eina_prefix_bin_get(Eina_Prefix *pfx) | ||
681 | { | ||
682 | if (!pfx) return ""; | ||
683 | return pfx->prefix_path_bin; | ||
684 | } | ||
685 | |||
686 | EAPI const char * | ||
687 | eina_prefix_lib_get(Eina_Prefix *pfx) | ||
688 | { | ||
689 | if (!pfx) return ""; | ||
690 | return pfx->prefix_path_lib; | ||
691 | } | ||
692 | |||
693 | EAPI const char * | ||
694 | eina_prefix_data_get(Eina_Prefix *pfx) | ||
695 | { | ||
696 | if (!pfx) return ""; | ||
697 | return pfx->prefix_path_data; | ||
698 | } | ||
699 | |||
700 | EAPI const char * | ||
701 | eina_prefix_locale_get(Eina_Prefix *pfx) | ||
702 | { | ||
703 | if (!pfx) return ""; | ||
704 | return pfx->prefix_path_locale; | ||
705 | } | ||
706 | |||
707 | Eina_Bool | ||
708 | eina_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 | |||
721 | Eina_Bool | ||
722 | eina_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 | ||
131 | extern Eina_Bool _threads_activated; | ||
132 | |||
133 | void eina_share_common_threads_init(void); | ||
134 | void eina_share_common_threads_shutdown(void); | ||
135 | void eina_log_threads_init(void); | ||
136 | void 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 | |||
48 | typedef struct _Eina_QuadTree_Root Eina_QuadTree_Root; | ||
49 | |||
50 | static const char EINA_MAGIC_QUADTREE_STR[] = "Eina QuadTree"; | ||
51 | static const char EINA_MAGIC_QUADTREE_ROOT_STR[] = "Eina QuadTree Root"; | ||
52 | static 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 | |||
81 | struct _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 | |||
117 | struct _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 | |||
130 | struct _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 | |||
149 | static int _eina_quadtree_log_dom = -1; | ||
150 | static Eina_Mempool *eina_quadtree_root_mp = NULL; | ||
151 | static 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 | |||
164 | static 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 | |||
173 | static Eina_QuadTree_Root * | ||
174 | eina_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 | |||
195 | static Eina_QuadTree_Root * | ||
196 | eina_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 | |||
232 | static 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 | |||
343 | static 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 | |||
403 | static 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 | |||
486 | static 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 | |||
548 | static 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 | |||
585 | end: | ||
586 | object->root = NULL; | ||
587 | } | ||
588 | |||
589 | EAPI Eina_QuadTree * | ||
590 | eina_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 | |||
617 | EAPI void | ||
618 | eina_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 | |||
658 | EAPI Eina_QuadTree_Item * | ||
659 | eina_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 | |||
696 | EAPI Eina_Bool | ||
697 | eina_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 | |||
733 | EAPI Eina_Bool | ||
734 | eina_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 | |||
756 | EAPI Eina_Bool | ||
757 | eina_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 | |||
766 | EAPI Eina_Bool | ||
767 | eina_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 | |||
783 | EAPI Eina_Inlist * | ||
784 | eina_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 | |||
831 | EAPI void * | ||
832 | eina_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 | |||
851 | EAPI void | ||
852 | eina_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 | |||
865 | EAPI void | ||
866 | eina_quadtree_cycle(Eina_QuadTree *q) | ||
867 | { | ||
868 | EINA_MAGIC_CHECK_QUADTREE(q); | ||
869 | |||
870 | q->index = 0; | ||
871 | } | ||
872 | |||
873 | EAPI void | ||
874 | eina_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 | |||
887 | Eina_Bool | ||
888 | eina_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 | |||
923 | Eina_Bool | ||
924 | eina_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 | |||
43 | typedef struct _Eina_Iterator_Rbtree Eina_Iterator_Rbtree; | ||
44 | typedef struct _Eina_Iterator_Rbtree_List Eina_Iterator_Rbtree_List; | ||
45 | |||
46 | struct _Eina_Iterator_Rbtree | ||
47 | { | ||
48 | Eina_Iterator iterator; | ||
49 | |||
50 | Eina_Array *stack; | ||
51 | |||
52 | unsigned char mask; | ||
53 | }; | ||
54 | |||
55 | struct _Eina_Iterator_Rbtree_List | ||
56 | { | ||
57 | Eina_Rbtree *tree; | ||
58 | |||
59 | Eina_Rbtree_Direction dir : 1; | ||
60 | Eina_Bool up : 1; | ||
61 | }; | ||
62 | |||
63 | static 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 | |||
83 | static 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 | |||
92 | static 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 | |||
106 | static 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 | |||
176 | onfix: | ||
177 | *data = tree; | ||
178 | return EINA_TRUE; | ||
179 | } | ||
180 | |||
181 | static 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 | |||
217 | on_error: | ||
218 | eina_array_free(it->stack); | ||
219 | on_error2: | ||
220 | free(it); | ||
221 | |||
222 | return NULL; | ||
223 | } | ||
224 | |||
225 | static 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 | |||
237 | static inline Eina_Bool | ||
238 | _eina_rbtree_is_red(Eina_Rbtree *node) | ||
239 | { | ||
240 | return !!node && node->color == EINA_RBTREE_RED; | ||
241 | } | ||
242 | |||
243 | static 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 | |||
258 | static 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 | |||
274 | EAPI Eina_Rbtree * | ||
275 | eina_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 | |||
357 | end_add: | ||
358 | /* Make root black */ | ||
359 | root->color = EINA_RBTREE_BLACK; | ||
360 | |||
361 | return root; | ||
362 | } | ||
363 | |||
364 | EAPI Eina_Rbtree * | ||
365 | eina_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 | |||
489 | EAPI Eina_Iterator * | ||
490 | eina_rbtree_iterator_prefix(const Eina_Rbtree *root) | ||
491 | { | ||
492 | return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_PREFIX_MASK); | ||
493 | } | ||
494 | |||
495 | EAPI Eina_Iterator * | ||
496 | eina_rbtree_iterator_infix(const Eina_Rbtree *root) | ||
497 | { | ||
498 | return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_INFIX_MASK); | ||
499 | } | ||
500 | |||
501 | EAPI Eina_Iterator * | ||
502 | eina_rbtree_iterator_postfix(const Eina_Rbtree *root) | ||
503 | { | ||
504 | return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_POSTFIX_MASK); | ||
505 | } | ||
506 | |||
507 | EAPI void | ||
508 | eina_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 | |||
56 | typedef struct _Eina_Rectangle_Alloc Eina_Rectangle_Alloc; | ||
57 | |||
58 | struct _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 | |||
75 | struct _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 | |||
94 | static Eina_Mempool *_eina_rectangle_alloc_mp = NULL; | ||
95 | static Eina_Mempool *_eina_rectangle_mp = NULL; | ||
96 | |||
97 | static Eina_Trash *_eina_rectangles = NULL; | ||
98 | static unsigned int _eina_rectangles_count = 0; | ||
99 | static 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 | |||
111 | static 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 | |||
117 | static 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 | |||
131 | start_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 | |||
174 | static 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 | |||
254 | Eina_Bool | ||
255 | eina_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 | |||
295 | init_error: | ||
296 | eina_log_domain_unregister(_eina_rectangle_log_dom); | ||
297 | _eina_rectangle_log_dom = -1; | ||
298 | |||
299 | return EINA_FALSE; | ||
300 | } | ||
301 | |||
302 | Eina_Bool | ||
303 | eina_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 | |||
324 | EAPI Eina_Rectangle * | ||
325 | eina_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 | |||
345 | EAPI void | ||
346 | eina_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 | |||
359 | EAPI Eina_Rectangle_Pool * | ||
360 | eina_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 | |||
383 | EAPI void | ||
384 | eina_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 | |||
410 | EAPI int | ||
411 | eina_rectangle_pool_count(Eina_Rectangle_Pool *pool) | ||
412 | { | ||
413 | EINA_SAFETY_ON_NULL_RETURN_VAL(pool, 0); | ||
414 | return pool->references; | ||
415 | } | ||
416 | |||
417 | EAPI Eina_Rectangle * | ||
418 | eina_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 | |||
478 | EAPI void | ||
479 | eina_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 | |||
518 | EAPI Eina_Rectangle_Pool * | ||
519 | eina_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 | |||
531 | EAPI void | ||
532 | eina_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 | |||
543 | EAPI void * | ||
544 | eina_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 | |||
552 | EAPI Eina_Bool | ||
553 | eina_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 | */ | ||
47 | Eina_Bool | ||
48 | eina_safety_checks_shutdown(void) | ||
49 | { | ||
50 | return EINA_TRUE; | ||
51 | } | ||
52 | |||
53 | /*============================================================================* | ||
54 | * API * | ||
55 | *============================================================================*/ | ||
56 | |||
57 | /** | ||
58 | * @cond LOCAL | ||
59 | */ | ||
60 | |||
61 | EAPI Eina_Error EINA_ERROR_SAFETY_FAILED = 0; | ||
62 | |||
63 | static 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 | */ | ||
80 | Eina_Bool | ||
81 | eina_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 | |||
47 | EAPI void | ||
48 | eina_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, ¶m); | ||
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, ¶m); | ||
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 | |||
97 | static const char EINA_MAGIC_SHARE_STR[] = "Eina Share"; | ||
98 | static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head"; | ||
99 | |||
100 | static 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 | ||
122 | typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population; | ||
123 | #endif | ||
124 | |||
125 | typedef struct _Eina_Share_Common Eina_Share_Common; | ||
126 | typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node; | ||
127 | typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head; | ||
128 | |||
129 | int _eina_share_common_log_dom = -1; | ||
130 | |||
131 | struct _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 | |||
141 | struct _Eina_Share_Common | ||
142 | { | ||
143 | Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS]; | ||
144 | |||
145 | EINA_MAGIC | ||
146 | }; | ||
147 | |||
148 | struct _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 | |||
159 | struct _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 | |||
174 | Eina_Bool _share_common_threads_activated = EINA_FALSE; | ||
175 | |||
176 | static Eina_Lock _mutex_big; | ||
177 | |||
178 | #ifdef EINA_SHARE_COMMON_USAGE | ||
179 | struct _Eina_Share_Common_Population | ||
180 | { | ||
181 | int count; | ||
182 | int max; | ||
183 | }; | ||
184 | |||
185 | static Eina_Share_Common_Population population = { 0, 0 }; | ||
186 | |||
187 | static Eina_Share_Common_Population population_group[4] = | ||
188 | { | ||
189 | { 0, 0 }, | ||
190 | { 0, 0 }, | ||
191 | { 0, 0 }, | ||
192 | { 0, 0 } | ||
193 | }; | ||
194 | |||
195 | static 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 | |||
210 | static 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 | |||
229 | static 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 | |||
253 | void | ||
254 | eina_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 | |||
274 | void | ||
275 | eina_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 | |||
286 | static void | ||
287 | _eina_share_common_population_head_init(Eina_Share *share, | ||
288 | Eina_Share_Common_Head *head) | ||
289 | { | ||
290 | head->population = 1; | ||
291 | } | ||
292 | |||
293 | static 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 | |||
302 | static 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 | |||
311 | static void _eina_share_common_population_init(__UNUSED__ Eina_Share *share) { | ||
312 | } | ||
313 | static void _eina_share_common_population_shutdown(__UNUSED__ Eina_Share *share) | ||
314 | { | ||
315 | } | ||
316 | static void _eina_share_common_population_stats(__UNUSED__ Eina_Share *share) { | ||
317 | } | ||
318 | void eina_share_common_population_add(__UNUSED__ Eina_Share *share, | ||
319 | __UNUSED__ int slen) { | ||
320 | } | ||
321 | void eina_share_common_population_del(__UNUSED__ Eina_Share *share, | ||
322 | __UNUSED__ int slen) { | ||
323 | } | ||
324 | static void _eina_share_common_population_head_init( | ||
325 | __UNUSED__ Eina_Share *share, | ||
326 | __UNUSED__ Eina_Share_Common_Head *head) { | ||
327 | } | ||
328 | static void _eina_share_common_population_head_add( | ||
329 | __UNUSED__ Eina_Share *share, | ||
330 | __UNUSED__ | ||
331 | Eina_Share_Common_Head *head) { | ||
332 | } | ||
333 | static void _eina_share_common_population_head_del( | ||
334 | __UNUSED__ Eina_Share *share, | ||
335 | __UNUSED__ | ||
336 | Eina_Share_Common_Head *head) { | ||
337 | } | ||
338 | #endif | ||
339 | |||
340 | static 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 | |||
351 | static 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 | |||
365 | static 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 | |||
381 | static 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 | |||
397 | static 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 | |||
410 | static 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 | |||
444 | static 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 | |||
458 | static 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 | |||
467 | static 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 | |||
493 | static 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 | |||
517 | static 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 | |||
525 | static 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 | |||
538 | static 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 | |||
551 | static Eina_Bool | ||
552 | eina_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 | */ | ||
593 | Eina_Bool | ||
594 | eina_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 | */ | ||
659 | Eina_Bool | ||
660 | eina_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 | */ | ||
712 | void | ||
713 | eina_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 | */ | ||
727 | void | ||
728 | eina_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 | |||
743 | const char * | ||
744 | eina_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 | |||
811 | const char * | ||
812 | eina_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 | |||
836 | void | ||
837 | eina_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 | |||
891 | on_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 | |||
897 | int | ||
898 | eina_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 | |||
910 | void | ||
911 | eina_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 | |||
57 | typedef struct _Eina_Share Eina_Share; | ||
58 | |||
59 | struct dumpinfo | ||
60 | { | ||
61 | int used, saved, dups, unique; | ||
62 | }; | ||
63 | |||
64 | Eina_Bool eina_share_common_init(Eina_Share **share, | ||
65 | Eina_Magic node_magic, | ||
66 | const char *node_magic_STR); | ||
67 | Eina_Bool eina_share_common_shutdown(Eina_Share **share); | ||
68 | const char *eina_share_common_add_length(Eina_Share *share, | ||
69 | const char *str, | ||
70 | unsigned int slen, | ||
71 | unsigned int null_size) | ||
72 | EINA_WARN_UNUSED_RESULT; | ||
73 | const char *eina_share_common_ref(Eina_Share *share, const char *str); | ||
74 | void eina_share_common_del(Eina_Share *share, const char *str); | ||
75 | int eina_share_common_length(Eina_Share *share, | ||
76 | const char *str) EINA_CONST | ||
77 | EINA_WARN_UNUSED_RESULT; | ||
78 | void eina_share_common_dump(Eina_Share *share, void (*additional_dump)( | ||
79 | struct dumpinfo *), int used); | ||
80 | |||
81 | |||
82 | /* Population functions */ | ||
83 | void eina_share_common_population_add(Eina_Share *share, int slen); | ||
84 | void 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__) | ||
101 | extern 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 | ||
36 | extern "C" | ||
37 | # endif | ||
38 | void *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 | |||
64 | static Eina_Mempool *_eina_simple_xml_tag_mp = NULL; | ||
65 | static Eina_Mempool *_eina_simple_xml_attribute_mp = NULL; | ||
66 | static int _eina_simple_xml_log_dom = -1; | ||
67 | |||
68 | static const char EINA_MAGIC_SIMPLE_XML_TAG_STR[] = "Eina Simple XML Tag"; | ||
69 | static const char EINA_MAGIC_SIMPLE_XML_DATA_STR[] = "Eina Simple XML Data"; | ||
70 | static 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 | |||
120 | static 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 | |||
128 | static 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 | |||
136 | static 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 | |||
144 | static 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 | |||
150 | static 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 | */ | ||
179 | Eina_Bool | ||
180 | eina_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 | |||
228 | on_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 | */ | ||
246 | Eina_Bool | ||
247 | eina_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 | |||
263 | EAPI Eina_Bool | ||
264 | eina_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 | |||
451 | EAPI const char * | ||
452 | eina_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 | |||
476 | EAPI Eina_Bool | ||
477 | eina_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 | |||
538 | EAPI Eina_Simple_XML_Attribute * | ||
539 | eina_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 | |||
564 | EAPI void | ||
565 | eina_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 | |||
579 | static 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 | |||
590 | EAPI Eina_Simple_XML_Node_Tag * | ||
591 | eina_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 | |||
619 | void | ||
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 | |||
648 | EAPI void | ||
649 | eina_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 | |||
660 | static 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 | |||
688 | EAPI Eina_Simple_XML_Node_Data * | ||
689 | eina_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 | |||
695 | EAPI void | ||
696 | eina_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 | |||
707 | EAPI Eina_Simple_XML_Node_CData * | ||
708 | eina_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 | |||
714 | EAPI void | ||
715 | eina_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 | |||
726 | EAPI Eina_Simple_XML_Node_Processing * | ||
727 | eina_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 | |||
733 | EAPI void | ||
734 | eina_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 | |||
745 | EAPI Eina_Simple_XML_Node_Doctype * | ||
746 | eina_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 | |||
752 | EAPI void | ||
753 | eina_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 | |||
764 | EAPI Eina_Simple_XML_Node_Comment * | ||
765 | eina_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 | |||
771 | EAPI void | ||
772 | eina_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 | |||
783 | struct eina_simple_xml_node_load_ctxt | ||
784 | { | ||
785 | Eina_Simple_XML_Node_Root *root; | ||
786 | Eina_Simple_XML_Node_Tag *current; | ||
787 | }; | ||
788 | |||
789 | static 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 | |||
799 | static 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 | |||
884 | EAPI Eina_Simple_XML_Node_Root * | ||
885 | eina_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 | |||
906 | EAPI void | ||
907 | eina_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 | |||
919 | static 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 | |||
927 | static 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 | |||
936 | static void _eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level); | ||
937 | |||
938 | static 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 | |||
947 | static 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 | |||
1054 | EAPI char * | ||
1055 | eina_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 | */ | ||
51 | static inline Eina_Bool | ||
52 | eina_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 | |||
68 | static inline char ** | ||
69 | eina_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 | |||
180 | EAPI size_t | ||
181 | eina_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 | |||
212 | EAPI size_t | ||
213 | eina_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 | |||
243 | EAPI Eina_Bool | ||
244 | eina_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 | |||
257 | EAPI Eina_Bool | ||
258 | eina_str_has_suffix(const char *str, const char *suffix) | ||
259 | { | ||
260 | return eina_str_has_suffix_helper(str, suffix, strcmp); | ||
261 | } | ||
262 | |||
263 | EAPI Eina_Bool | ||
264 | eina_str_has_extension(const char *str, const char *ext) | ||
265 | { | ||
266 | return eina_str_has_suffix_helper(str, ext, strcasecmp); | ||
267 | } | ||
268 | |||
269 | EAPI char ** | ||
270 | eina_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 | |||
279 | EAPI char ** | ||
280 | eina_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 | |||
285 | EAPI size_t | ||
286 | eina_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 | ||
332 | EAPI char * | ||
333 | eina_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 | ||
409 | EAPI char * | ||
410 | eina_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 | |||
418 | EAPI char * | ||
419 | eina_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 | |||
442 | EAPI void | ||
443 | eina_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 | |||
453 | EAPI void | ||
454 | eina_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 | ||
66 | static 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 | |||
85 | EAPI Eina_Bool | ||
86 | eina_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 | |||
105 | EAPI Eina_Bool | ||
106 | eina_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 | |||
122 | EAPI Eina_Bool | ||
123 | eina_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 | |||
142 | EAPI Eina_Bool | ||
143 | eina_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 | |||
162 | EAPI void | ||
163 | eina_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 | |||
178 | EAPI void | ||
179 | eina_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 | |||
192 | EAPI void | ||
193 | eina_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 | */ | ||
52 | Eina_Bool | ||
53 | eina_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 | */ | ||
69 | Eina_Bool | ||
70 | eina_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 | */ | ||
84 | static 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 | */ | ||
111 | static 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 | */ | ||
136 | static 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 | */ | ||
186 | Eina_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 | */ | ||
207 | static 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 | */ | ||
249 | Eina_Strbuf * | ||
250 | eina_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 | */ | ||
287 | Eina_Strbuf * | ||
288 | eina_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 | */ | ||
318 | void | ||
319 | eina_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 | */ | ||
335 | void | ||
336 | eina_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 | */ | ||
361 | Eina_Bool | ||
362 | eina_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 | */ | ||
400 | Eina_Bool | ||
401 | eina_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 | */ | ||
440 | Eina_Bool | ||
441 | eina_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 | */ | ||
473 | Eina_Bool | ||
474 | eina_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 | */ | ||
506 | Eina_Bool | ||
507 | eina_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 | */ | ||
544 | Eina_Bool | ||
545 | eina_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 | */ | ||
571 | Eina_Bool | ||
572 | eina_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 | */ | ||
597 | Eina_Bool | ||
598 | eina_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 | */ | ||
624 | Eina_Bool | ||
625 | eina_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 | */ | ||
664 | const void * | ||
665 | eina_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 | */ | ||
685 | void * | ||
686 | eina_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 | */ | ||
706 | void | ||
707 | eina_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 | */ | ||
722 | size_t | ||
723 | eina_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 | ||
749 | static const char __STRBUF_STR_MAGIC_STR[] = "Eina Strbuf"; | ||
750 | |||
751 | |||
752 | /** | ||
753 | * @endcond | ||
754 | */ | ||
755 | |||
756 | |||
757 | EAPI Eina_Bool | ||
758 | eina_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 | |||
800 | EAPI int | ||
801 | eina_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 | */ | ||
14 | struct _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 | |||
33 | Eina_Bool | ||
34 | eina_strbuf_common_init(void); | ||
35 | |||
36 | Eina_Bool | ||
37 | eina_strbuf_common_shutdown(void); | ||
38 | Eina_Strbuf * | ||
39 | eina_strbuf_common_new(size_t csize); | ||
40 | Eina_Strbuf * | ||
41 | eina_strbuf_common_manage_new(size_t csize, | ||
42 | void *str, | ||
43 | size_t len); | ||
44 | void | ||
45 | eina_strbuf_common_free(Eina_Strbuf *buf); | ||
46 | void | ||
47 | eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf); | ||
48 | Eina_Bool | ||
49 | eina_strbuf_common_append(size_t csize, | ||
50 | Eina_Strbuf *buf, | ||
51 | const void *str, | ||
52 | size_t len); | ||
53 | Eina_Bool | ||
54 | eina_strbuf_common_append_escaped(size_t csize, | ||
55 | Eina_Strbuf *buf, | ||
56 | const void *str); | ||
57 | Eina_Bool | ||
58 | eina_strbuf_common_append_n(size_t csize, | ||
59 | Eina_Strbuf *buf, | ||
60 | const void *str, | ||
61 | size_t len, | ||
62 | size_t maxlen); | ||
63 | Eina_Bool | ||
64 | eina_strbuf_common_append_length(size_t csize, | ||
65 | Eina_Strbuf *buf, | ||
66 | const void *str, | ||
67 | size_t length); | ||
68 | Eina_Bool | ||
69 | eina_strbuf_common_insert(size_t csize, | ||
70 | Eina_Strbuf *buf, | ||
71 | const void *str, | ||
72 | size_t len, | ||
73 | size_t pos); | ||
74 | Eina_Bool | ||
75 | eina_strbuf_common_insert_escaped(size_t csize, | ||
76 | Eina_Strbuf *buf, | ||
77 | const void *str, | ||
78 | size_t len, | ||
79 | size_t pos); | ||
80 | Eina_Bool | ||
81 | eina_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); | ||
87 | Eina_Bool | ||
88 | eina_strbuf_common_insert_length(size_t csize, | ||
89 | Eina_Strbuf *buf, | ||
90 | const void *str, | ||
91 | size_t length, | ||
92 | size_t pos); | ||
93 | Eina_Bool | ||
94 | eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c); | ||
95 | Eina_Bool | ||
96 | eina_strbuf_common_insert_char(size_t csize, | ||
97 | Eina_Strbuf *buf, | ||
98 | const void *c, | ||
99 | size_t pos); | ||
100 | Eina_Bool | ||
101 | eina_strbuf_common_remove(size_t csize, | ||
102 | Eina_Strbuf *buf, | ||
103 | size_t start, | ||
104 | size_t end); | ||
105 | const void * | ||
106 | eina_strbuf_common_string_get(const Eina_Strbuf *buf); | ||
107 | void * | ||
108 | eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf); | ||
109 | void | ||
110 | eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf); | ||
111 | size_t | ||
112 | eina_strbuf_common_length_get(const Eina_Strbuf *buf); | ||
113 | |||
114 | Eina_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 | |||
25 | EAPI _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 | |||
34 | EAPI 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 | |||
41 | EAPI 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 | |||
59 | EAPI 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 | |||
66 | EAPI 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 | |||
73 | EAPI 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 | |||
91 | EAPI 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 | ||
41 | extern "C" | ||
42 | # endif | ||
43 | void *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 */ | ||
66 | static Eina_Share *stringshare_share; | ||
67 | static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node"; | ||
68 | |||
69 | extern Eina_Bool _share_common_threads_activated; | ||
70 | static Eina_Lock _mutex_small; | ||
71 | |||
72 | /* Stringshare optimizations */ | ||
73 | static 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 | |||
104 | typedef struct _Eina_Stringshare_Small Eina_Stringshare_Small; | ||
105 | typedef struct _Eina_Stringshare_Small_Bucket Eina_Stringshare_Small_Bucket; | ||
106 | |||
107 | struct _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 | |||
117 | struct _Eina_Stringshare_Small | ||
118 | { | ||
119 | Eina_Stringshare_Small_Bucket *buckets[256]; | ||
120 | }; | ||
121 | |||
122 | #define EINA_STRINGSHARE_SMALL_BUCKET_STEP 8 | ||
123 | static Eina_Stringshare_Small _eina_small_share; | ||
124 | |||
125 | static 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 | |||
165 | static 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 | |||
206 | static 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 | |||
243 | static 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 | |||
301 | static 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 | |||
341 | end: | ||
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 | |||
349 | static 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 | |||
372 | static 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 | |||
390 | error: | ||
391 | CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); | ||
392 | } | ||
393 | |||
394 | static 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 | |||
401 | static 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 | |||
432 | static 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 | |||
464 | static 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 | */ | ||
499 | Eina_Bool | ||
500 | eina_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 | */ | ||
523 | Eina_Bool | ||
524 | eina_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 | |||
536 | EAPI void | ||
537 | eina_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 | |||
570 | EAPI const char * | ||
571 | eina_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 | |||
591 | EAPI const char * | ||
592 | eina_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 | |||
612 | EAPI const char * | ||
613 | eina_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 | |||
636 | EAPI const char * | ||
637 | eina_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 | |||
657 | EAPI const char * | ||
658 | eina_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 | |||
682 | EAPI const char * | ||
683 | eina_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 | |||
723 | EAPI int | ||
724 | eina_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 | |||
745 | EAPI void | ||
746 | eina_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 */ | ||
42 | typedef struct list_node list_node_t; | ||
43 | typedef struct list list_t; | ||
44 | typedef struct rect rect_t; | ||
45 | typedef struct rect_node rect_node_t; | ||
46 | |||
47 | struct list_node | ||
48 | { | ||
49 | struct list_node *next; | ||
50 | }; | ||
51 | |||
52 | struct list | ||
53 | { | ||
54 | struct list_node *head; | ||
55 | struct list_node *tail; | ||
56 | }; | ||
57 | |||
58 | struct 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 | |||
69 | struct rect_node | ||
70 | { | ||
71 | struct list_node _lst; | ||
72 | struct rect rect; | ||
73 | }; | ||
74 | |||
75 | typedef struct splitter | ||
76 | { | ||
77 | Eina_Bool need_merge; | ||
78 | list_t rects; | ||
79 | } splitter_t; | ||
80 | |||
81 | typedef struct list_node_pool | ||
82 | { | ||
83 | list_node_t *node; | ||
84 | int len; | ||
85 | int max; | ||
86 | } list_node_pool_t; | ||
87 | |||
88 | |||
89 | static const list_node_t list_node_zeroed = { NULL }; | ||
90 | static const list_t list_zeroed = { NULL, NULL }; | ||
91 | static list_node_pool_t list_node_pool = { NULL, 0, 1024 }; | ||
92 | |||
93 | |||
94 | typedef 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 | |||
103 | struct _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 */ | ||
134 | static 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 | |||
148 | static inline list_node_t * | ||
149 | rect_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 | |||
166 | static 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 | |||
185 | static 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 | |||
199 | static 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 | |||
210 | static 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 | |||
222 | static 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 | |||
252 | static 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 | |||
315 | static 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 | |||
387 | enum | ||
388 | { | ||
389 | SPLIT_FUZZY_ACTION_NONE, | ||
390 | SPLIT_FUZZY_ACTION_SPLIT, | ||
391 | SPLIT_FUZZY_ACTION_MERGE | ||
392 | }; | ||
393 | |||
394 | static 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 | ||
471 | static 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 | |||
491 | static 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 | |||
507 | static 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 | ||
520 | static 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 | |||
525 | static 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 | |||
554 | static inline list_node_t * | ||
555 | rect_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 | |||
577 | static 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 | |||
585 | static 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 | |||
601 | static 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 | ||
654 | static 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 | |||
724 | static list_node_t * | ||
725 | rect_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 | |||
872 | static 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 | |||
909 | static 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 | |||
965 | static 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 | |||
987 | static inline void _splitter_new(Eina_Tiler *t) | ||
988 | { | ||
989 | t->splitter.rects = list_zeroed; | ||
990 | t->splitter.need_merge = EINA_FALSE; | ||
991 | } | ||
992 | |||
993 | static inline void _splitter_del(Eina_Tiler *t) | ||
994 | { | ||
995 | rect_list_clear(&t->splitter.rects); | ||
996 | rect_list_node_pool_flush(); | ||
997 | } | ||
998 | |||
999 | static 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 | |||
1007 | static 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 | |||
1032 | static 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 | |||
1059 | static 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 | |||
1066 | static 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 | |||
1094 | static void *_iterator_get_container(Eina_Iterator_Tiler *it) | ||
1095 | { | ||
1096 | EINA_MAGIC_CHECK_TILER_ITERATOR(it, NULL); | ||
1097 | return (void *)it->tiler; | ||
1098 | } | ||
1099 | |||
1100 | static 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 | |||
1114 | EAPI 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 | |||
1128 | EAPI void eina_tiler_free(Eina_Tiler *t) | ||
1129 | { | ||
1130 | EINA_MAGIC_CHECK_TILER(t); | ||
1131 | _splitter_del(t); | ||
1132 | free(t); | ||
1133 | } | ||
1134 | |||
1135 | EAPI 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 | |||
1146 | EAPI 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 | |||
1164 | EAPI 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 | |||
1182 | EAPI void eina_tiler_clear(Eina_Tiler *t) | ||
1183 | { | ||
1184 | EINA_MAGIC_CHECK_TILER(t); | ||
1185 | _splitter_clear(t); | ||
1186 | } | ||
1187 | |||
1188 | |||
1189 | EAPI 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 | |||
1227 | struct _Eina_Tile_Grid_Slicer_Iterator | ||
1228 | { | ||
1229 | Eina_Iterator iterator; | ||
1230 | Eina_Tile_Grid_Slicer priv; | ||
1231 | }; | ||
1232 | |||
1233 | typedef struct _Eina_Tile_Grid_Slicer_Iterator Eina_Tile_Grid_Slicer_Iterator; | ||
1234 | |||
1235 | static void | ||
1236 | eina_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 | |||
1242 | static Eina_Bool | ||
1243 | eina_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 | |||
1250 | EAPI Eina_Iterator * | ||
1251 | eina_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. */ | ||
28 | const Eina_Unicode _EINA_UNICODE_EMPTY_STRING[1] = {0}; | ||
29 | EAPI const Eina_Unicode *EINA_UNICODE_EMPTY_STRING = _EINA_UNICODE_EMPTY_STRING; | ||
30 | EAPI int | ||
31 | eina_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 | |||
43 | EAPI Eina_Unicode * | ||
44 | eina_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 | |||
54 | EAPI Eina_Unicode * | ||
55 | eina_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 | |||
66 | EAPI size_t | ||
67 | eina_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 | |||
75 | EAPI size_t | ||
76 | eina_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 | |||
88 | EAPI Eina_Unicode * | ||
89 | eina_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 | |||
99 | EAPI Eina_Unicode * | ||
100 | eina_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 | |||
108 | EAPI Eina_Unicode * | ||
109 | eina_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 | |||
128 | EAPI Eina_Unicode * | ||
129 | eina_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 | |||
161 | EAPI Eina_Unicode | ||
162 | eina_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 */ | ||
260 | error: | ||
261 | d = buf[*iindex]; | ||
262 | (*iindex)++; | ||
263 | return ERROR_REPLACEMENT_BASE | d; | ||
264 | } | ||
265 | |||
266 | EAPI Eina_Unicode | ||
267 | eina_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 | |||
289 | EAPI int | ||
290 | eina_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 | |||
301 | EAPI Eina_Unicode * | ||
302 | eina_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 | |||
323 | EAPI char * | ||
324 | eina_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 | ||
56 | static 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 */ | ||
36 | static Eina_Share *ustringshare_share; | ||
37 | static 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 | */ | ||
54 | Eina_Bool | ||
55 | eina_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 | */ | ||
73 | Eina_Bool | ||
74 | eina_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 | |||
85 | EAPI void | ||
86 | eina_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 | |||
94 | EAPI const Eina_Unicode * | ||
95 | eina_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 | |||
106 | EAPI const Eina_Unicode * | ||
107 | eina_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 | |||
113 | EAPI const Eina_Unicode * | ||
114 | eina_ustringshare_ref(const Eina_Unicode *str) | ||
115 | { | ||
116 | return (const Eina_Unicode *)eina_share_common_ref(ustringshare_share, | ||
117 | (const char *)str); | ||
118 | } | ||
119 | |||
120 | EAPI int | ||
121 | eina_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 | |||
128 | EAPI void | ||
129 | eina_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 | |||
42 | EAPI 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 | |||
46 | typedef struct _Eina_Xattr_Iterator Eina_Xattr_Iterator; | ||
47 | |||
48 | struct _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 | ||
59 | static 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 | |||
71 | static void * | ||
72 | _eina_xattr_ls_iterator_container(Eina_Xattr_Iterator *it __UNUSED__) | ||
73 | { | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | static 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 | |||
100 | EAPI Eina_Iterator * | ||
101 | eina_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 | |||
136 | EAPI void * | ||
137 | eina_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 | |||
174 | EAPI Eina_Bool | ||
175 | eina_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 | |||
207 | EAPI Eina_Bool | ||
208 | eina_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 | |||
215 | EAPI char * | ||
216 | eina_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 | |||
233 | EAPI Eina_Bool | ||
234 | eina_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 | |||
242 | EAPI Eina_Bool | ||
243 | eina_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 | |||
266 | EAPI Eina_Bool | ||
267 | eina_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 | |||
275 | EAPI Eina_Bool | ||
276 | eina_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 | } | ||