summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-07-31 11:27:21 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-08-31 16:51:04 -0300
commit4e5a7227da7179a8a798967d0b8a9fc4ed61414f (patch)
tree9edaeb62edbd02f06d2dca82d4be756f4b24d615
parent132e320017101f796473a93bf4e0feb0dc3698ad (diff)
eflat_xml_model: "Flat" Xml Model implementation
-rw-r--r--Makefile.am16
-rw-r--r--cmakeconfig/EflatXmlModelConfig.cmake.in32
-rw-r--r--cmakeconfig/EflatXmlModelCxxConfig.cmake.in30
-rw-r--r--configure.ac26
-rw-r--r--pc/eflat_xml_model-cxx.pc.in12
-rw-r--r--pc/eflat_xml_model.pc.in12
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile_EflatXmlModel.am84
-rw-r--r--src/Makefile_EflatXmlModel_Cxx.am22
-rw-r--r--src/lib/eflat_xml_model/Eflat_Xml_Model.h62
-rw-r--r--src/lib/eflat_xml_model/eflat_xml_model.c1049
-rw-r--r--src/lib/eflat_xml_model/eflat_xml_model.eo34
-rw-r--r--src/lib/eflat_xml_model/eflat_xml_model_private.h34
-rw-r--r--src/tests/eflat_xml_model/eflat_xml_model_suite.c121
-rw-r--r--src/tests/eflat_xml_model/eflat_xml_model_suite.h16
-rw-r--r--src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.c503
-rw-r--r--src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.h6
17 files changed, 2059 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index 56c298cb0b..f2fcd8119a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -152,7 +152,8 @@ pc/edje.pc \
152pc/emotion.pc \ 152pc/emotion.pc \
153pc/ethumb.pc \ 153pc/ethumb.pc \
154pc/ethumb_client.pc \ 154pc/ethumb_client.pc \
155pc/elocation.pc 155pc/elocation.pc \
156pc/eflat_xml_model.pc
156 157
157if HAVE_CXX11 158if HAVE_CXX11
158pkgconfig_DATA += \ 159pkgconfig_DATA += \
@@ -164,7 +165,8 @@ pc/eolian-cxx.pc \
164pc/edje-cxx.pc \ 165pc/edje-cxx.pc \
165pc/eet-cxx.pc \ 166pc/eet-cxx.pc \
166pc/eo-cxx.pc \ 167pc/eo-cxx.pc \
167pc/eio-cxx.pc 168pc/eio-cxx.pc \
169pc/eflat_xml_model-cxx.pc
168endif 170endif
169 171
170if HAVE_ELUA 172if HAVE_ELUA
@@ -383,6 +385,16 @@ emile_cmakeconfig_DATA = \
383cmakeconfig/EmileConfig.cmake \ 385cmakeconfig/EmileConfig.cmake \
384cmakeconfig/EmileConfigVersion.cmake 386cmakeconfig/EmileConfigVersion.cmake
385 387
388eflat_xml_model_cxx_cmakeconfigdir = $(libdir)/cmake/EflatXmlModelCxx/
389eflat_xml_model_cxx_cmakeconfig_DATA = \
390cmakeconfig/EflatXmlModelCxxConfig.cmake \
391cmakeconfig/EflatXmlModelCxxConfigVersion.cmake
392
393eflat_xml_model_cmakeconfigdir = $(libdir)/cmake/EflatXmlModel/
394eflat_xml_model_cmakeconfig_DATA = \
395cmakeconfig/EflatXmlModelConfig.cmake \
396cmakeconfig/EflatXmlModelConfigVersion.cmake
397
386# D-Bus services: 398# D-Bus services:
387 399
388servicedir = @dbusservicedir@ 400servicedir = @dbusservicedir@
diff --git a/cmakeconfig/EflatXmlModelConfig.cmake.in b/cmakeconfig/EflatXmlModelConfig.cmake.in
new file mode 100644
index 0000000000..95a307d57f
--- /dev/null
+++ b/cmakeconfig/EflatXmlModelConfig.cmake.in
@@ -0,0 +1,32 @@
1# - Try to find eflat_xml_model
2# Once done this will define
3# EFLAT_XML_MODEL_FOUND - System has eflat_xml_model
4# EFLAT_XML_MODEL_INCLUDE_DIRS - The eflat_xml_model include directories
5# EFLAT_XML_MODEL_LIBRARIES - The libraries needed to use eflat_xml_model
6# EFLAT_XML_MODEL_DEFINITIONS - Compiler switches required for using eflat_xml_model
7
8set(MY_PKG eflat_xml_model)
9
10find_package(PkgConfig)
11if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER "2.8.1")
12 # "QUIET" was introduced in 2.8.2
13 set(_QUIET QUIET)
14endif ()
15pkg_check_modules(PC_LIBEFLAT_XML_MODEL ${_QUIET} ${MY_PKG})
16
17find_library(EFLAT_XML_MODEL_LIBRARY
18 NAMES ${PC_LIBEFLAT_XML_MODEL_LIBRARIES}
19 HINTS ${PC_LIBEFLAT_XML_MODEL_LIBDIR} ${PC_LIBEFLAT_XML_MODEL_LIBRARY_DIRS} )
20
21set(EFLAT_XML_MODEL_DEFINITIONS ${PC_LIBEFLAT_XML_MODEL_CFLAGS_OTHER})
22set(EFLAT_XML_MODEL_LIBRARIES ${EFLAT_XML_MODEL_LIBRARY})
23set(EFLAT_XML_MODEL_INCLUDE_DIRS ${PC_LIBEFLAT_XML_MODEL_INCLUDE_DIRS})
24
25include(FindPackageHandleStandardArgs)
26# handle the QUIETLY and REQUIRED arguments and set EFLAT_XML_MODEL_FOUND to TRUE
27# if all listed variables are TRUE
28find_package_handle_standard_args(${MY_PKG} DEFAULT_MSG
29 EFLAT_XML_MODEL_LIBRARIES EFLAT_XML_MODEL_INCLUDE_DIRS)
30
31mark_as_advanced(EFLAT_XML_MODEL_INCLUDE_DIRS EFLAT_XML_MODEL_LIBRARY EFLAT_XML_MODEL_LIBRARIES EFLAT_XML_MODEL_DEFINITIONS)
32
diff --git a/cmakeconfig/EflatXmlModelCxxConfig.cmake.in b/cmakeconfig/EflatXmlModelCxxConfig.cmake.in
new file mode 100644
index 0000000000..c51ebff515
--- /dev/null
+++ b/cmakeconfig/EflatXmlModelCxxConfig.cmake.in
@@ -0,0 +1,30 @@
1# - Try to find eflat_xml_model
2# Once done this will define
3# EFLAT_XML_MODEL_CXX_FOUND - System has eflat_xml_model
4# EFLAT_XML_MODEL_CXX_INCLUDE_DIRS - The eflat_xml_model include directories
5# EFLAT_XML_MODEL_CXX_LIBRARIES - The libraries needed to use eflat_xml_model
6# EFLAT_XML_MODEL_CXX_DEFINITIONS - Compiler switches required for using eflat_xml_model
7
8set(MY_PKG eflat_xml_model_cxx)
9
10find_package(PkgConfig)
11if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER "2.8.1")
12 # "QUIET" was introduced in 2.8.2
13 set(_QUIET QUIET)
14endif ()
15pkg_check_modules(PC_EFLAT_XML_MODEL_CXX ${_QUIET} ${MY_PKG})
16find_library(EFLAT_XML_MODEL_CXX_LIBRARY
17 NAMES ${PC_EFLAT_XML_MODEL_CXX_LIBRARIES}
18 HINTS ${PC_EFLAT_XML_MODEL_CXX_LIBDIR} ${PC_EFLAT_XML_MODEL_CXX_LIBRARY_DIRS} )
19
20set(EFLAT_XML_MODEL_CXX_DEFINITIONS ${PC_EFLAT_XML_MODEL_CXX_CFLAGS_OTHER})
21set(EFLAT_XML_MODEL_CXX_LIBRARIES ${EFLAT_XML_MODEL_CXX_LIBRARY})
22set(EFLAT_XML_MODEL_CXX_INCLUDE_DIRS ${PC_EFLAT_XML_MODEL_CXX_INCLUDE_DIRS})
23
24include(FindPackageHandleStandardArgs)
25# handle the QUIETLY and REQUIRED arguments and set EFLAT_XML_MODEL_CXX_FOUND to TRUE
26# if all listed variables are TRUE
27find_package_handle_standard_args(${MY_PKG} DEFAULT_MSG
28 EFLAT_XML_MODEL_CXX_LIBRARIES EFLAT_XML_MODEL_CXX_INCLUDE_DIRS)
29
30mark_as_advanced(EFLAT_XML_MODEL_CXX_INCLUDE_DIRS EFLAT_XML_MODEL_CXX_LIBRARY EFLAT_XML_MODEL_CXX_LIBRARIES EFLAT_XML_MODEL_CXX_DEFINITIONS)
diff --git a/configure.ac b/configure.ac
index 442d7f399c..5951df9612 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4604,6 +4604,25 @@ EFL_EVAL_PKGS([EJSON_CXX])
4604EFL_LIB_END([Ejson_Cxx]) 4604EFL_LIB_END([Ejson_Cxx])
4605#### End of Ejson CXX 4605#### End of Ejson CXX
4606 4606
4607#### Eflat_Xml_Model
4608EFL_LIB_START([Eflat_Xml_Model])
4609
4610EFL_INTERNAL_DEPEND_PKG([EFLAT_XML_MODEL], [eo])
4611EFL_INTERNAL_DEPEND_PKG([EFLAT_XML_MODEL], [efl])
4612EFL_INTERNAL_DEPEND_PKG([EFLAT_XML_MODEL], [ecore])
4613
4614EFL_EVAL_PKGS([EFLAT_XML_MODEL])
4615
4616EFL_LIB_END([Eflat_Xml_Model])
4617#### End of Eflat_Xml_Model
4618
4619#### Eflat_Xml_Model CXX
4620EFL_LIB_START([Eflat_Xml_Model_Cxx])
4621
4622EFL_EVAL_PKGS([EFLAT_XML_MODEL_CXX])
4623
4624EFL_LIB_END([Eflat_Xml_Model_Cxx])
4625#### End of Eflat_Xml_Model CXX
4607 4626
4608### Add Wayland server library if test is enabled 4627### Add Wayland server library if test is enabled
4609if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then 4628if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then
@@ -4795,6 +4814,8 @@ pc/elocation.pc
4795pc/elua.pc 4814pc/elua.pc
4796pc/ejson.pc 4815pc/ejson.pc
4797pc/ejson-cxx.pc 4816pc/ejson-cxx.pc
4817pc/eflat_xml_model.pc
4818pc/eflat_xml_model-cxx.pc
4798dbus-services/org.enlightenment.Ethumb.service 4819dbus-services/org.enlightenment.Ethumb.service
4799systemd-services/ethumb.service 4820systemd-services/ethumb.service
4800$po_makefile_in 4821$po_makefile_in
@@ -4848,6 +4869,10 @@ cmakeconfig/EjsonConfig.cmake
4848cmakeconfig/EjsonConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in 4869cmakeconfig/EjsonConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4849cmakeconfig/EjsonCxxConfig.cmake 4870cmakeconfig/EjsonCxxConfig.cmake
4850cmakeconfig/EjsonCxxConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in 4871cmakeconfig/EjsonCxxConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4872cmakeconfig/EflatXmlModelConfig.cmake
4873cmakeconfig/EflatXmlModelConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4874cmakeconfig/EflatXmlModelCxxConfig.cmake
4875cmakeconfig/EflatXmlModelCxxConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4851]) 4876])
4852 4877
4853AC_OUTPUT 4878AC_OUTPUT
@@ -4962,6 +4987,7 @@ echo "Ethumb..........: yes"
4962echo "Ethumb_Client...: yes" 4987echo "Ethumb_Client...: yes"
4963echo "Elua............: $have_elua" 4988echo "Elua............: $have_elua"
4964echo "Ejson...........: yes" 4989echo "Ejson...........: yes"
4990echo "Eflat_Xml_Model.: yes"
4965if test "${build_tests}" = "none"; then 4991if test "${build_tests}" = "none"; then
4966echo "Tests...........: no" 4992echo "Tests...........: no"
4967elif test "${build_tests}" = "auto"; then 4993elif test "${build_tests}" = "auto"; then
diff --git a/pc/eflat_xml_model-cxx.pc.in b/pc/eflat_xml_model-cxx.pc.in
new file mode 100644
index 0000000000..7e80346e4f
--- /dev/null
+++ b/pc/eflat_xml_model-cxx.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: Eflat_xml_model C++
7Description: "Flat" XML model for EFL
8Requires.private: @requirements_pc_eflat_xml_model@ @requirements_pc_eo@
9Version: @VERSION@
10Libs: -L${libdir} -leflat_xml_model @requirements_public_libs_eflat_xml_model@ @requirements_public_libs_eo@
11Libs.private: @requirements_libs_eflat_xml_model@ @requirements_libs_eo@
12Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eo-@VMAJ@ -I${includedir}/eflat_xml_model-@VMAJ@ -I${includedir}/eflat_xml_model-cxx-@VMAJ@
diff --git a/pc/eflat_xml_model.pc.in b/pc/eflat_xml_model.pc.in
new file mode 100644
index 0000000000..a7c8e236c8
--- /dev/null
+++ b/pc/eflat_xml_model.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: Eflat_xml_model
7Description: "Flat" XML model for EFL
8Requires.private: @requirements_pc_eflat_xml_model@
9Version: @VERSION@
10Libs: -L${libdir} -leflat_xml_model @requirements_public_libs_eflat_xml_model@
11Libs.private: @requirements_libs_eflat_xml_model@
12Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eflat_xml_model-@VMAJ@
diff --git a/src/Makefile.am b/src/Makefile.am
index 0054ef7553..cb8398a0a1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,7 @@ include Makefile_Emotion.am
61include Makefile_Ethumb.am 61include Makefile_Ethumb.am
62include Makefile_Ethumb_Client.am 62include Makefile_Ethumb_Client.am
63include Makefile_Ejson.am 63include Makefile_Ejson.am
64include Makefile_EflatXmlModel.am
64 65
65include Makefile_Eina_Cxx.am 66include Makefile_Eina_Cxx.am
66include Makefile_Ecore_Cxx.am 67include Makefile_Ecore_Cxx.am
@@ -73,6 +74,7 @@ include Makefile_Edje_Cxx.am
73include Makefile_Evas_Cxx.am 74include Makefile_Evas_Cxx.am
74include Makefile_Eio_Cxx.am 75include Makefile_Eio_Cxx.am
75include Makefile_Ejson_Cxx.am 76include Makefile_Ejson_Cxx.am
77include Makefile_EflatXmlModel_Cxx.am
76 78
77include Makefile_Elua.am 79include Makefile_Elua.am
78include Makefile_Elocation.am 80include Makefile_Elocation.am
diff --git a/src/Makefile_EflatXmlModel.am b/src/Makefile_EflatXmlModel.am
new file mode 100644
index 0000000000..27c9bacf40
--- /dev/null
+++ b/src/Makefile_EflatXmlModel.am
@@ -0,0 +1,84 @@
1### Library
2
3eflat_xml_model_eolian_files = \
4lib/eflat_xml_model/eflat_xml_model.eo
5
6eflat_xml_model_eolian_c = $(eflat_xml_model_eolian_files:%.eo=%.eo.c)
7eflat_xml_model_eolian_h = $(eflat_xml_model_eolian_files:%.eo=%.eo.h)
8
9BUILT_SOURCES += \
10 $(eflat_xml_model_eolian_c) \
11 $(eflat_xml_model_eolian_h)
12
13CLEANFILES += \
14 $(eflat_xml_model_eolian_c) \
15 $(eflat_xml_model_eolian_h)
16
17eflat_xml_modeleolianfilesdir = $(datadir)/eolian/include/eflat_xml_model-@VMAJ@
18eflat_xml_modeleolianfiles_DATA = \
19 $(eflat_xml_model_eolian_files)
20
21EXTRA_DIST += \
22 ${eflat_xml_modeleolianfiles_DATA}
23
24lib_LTLIBRARIES += lib/eflat_xml_model/libeflat_xml_model.la
25
26installed_eflat_xml_modelmainheadersdir = $(includedir)/eflat_xml_model-@VMAJ@
27dist_installed_eflat_xml_modelmainheaders_DATA = \
28lib/eflat_xml_model/Eflat_Xml_Model.h
29
30nodist_installed_eflat_xml_modelmainheaders_DATA = \
31 $(eflat_xml_model_eolian_h)
32
33lib_eflat_xml_model_libeflat_xml_model_la_SOURCES = \
34lib/eflat_xml_model/eflat_xml_model_private.h \
35lib/eflat_xml_model/eflat_xml_model.c
36
37lib_eflat_xml_model_libeflat_xml_model_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EFLAT_XML_MODEL_CFLAGS@ @EFL_CFLAGS@
38lib_eflat_xml_model_libeflat_xml_model_la_LIBADD = @EFLAT_XML_MODEL_LIBS@ @EFL_LIBS@
39lib_eflat_xml_model_libeflat_xml_model_la_DEPENDENCIES = @EFLAT_XML_MODEL_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
40lib_eflat_xml_model_libeflat_xml_model_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
41
42### Unit tests
43
44if EFL_ENABLE_TESTS
45
46check_PROGRAMS += tests/eflat_xml_model/eflat_xml_model_suite
47TESTS += tests/eflat_xml_model/eflat_xml_model_suite
48
49tests_eflat_xml_model_eflat_xml_model_suite_SOURCES = \
50tests/eflat_xml_model/eflat_xml_model_suite.c \
51tests/eflat_xml_model/eflat_xml_model_suite.h \
52tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.c \
53tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.h
54
55tests_eflat_xml_model_eflat_xml_model_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
56-DTESTS_SRC_DIR=\"$(abs_top_srcdir)/src/tests/eflat_xml_model\" \
57-DTESTS_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eflat_xml_model\" \
58@CHECK_CFLAGS@ \
59@EFLAT_XML_MODEL_CFLAGS@ @EFL_CFLAGS@
60
61tests_eflat_xml_model_eflat_xml_model_suite_LDADD = \
62@CHECK_LIBS@ \
63@USE_EFLAT_XML_MODEL_LIBS@ \
64@USE_EFL_LIBS@
65
66tests_eflat_xml_model_eflat_xml_model_suite_DEPENDENCIES = \
67@USE_EFLAT_XML_MODEL_INTERNAL_LIBS@
68
69endif
70
71EXTRA_DIST += $(EFLAT_XML_MODEL_DATA_FILES)
72
73if HAVE_ELUA
74
75eflat_xml_model_eolian_lua = $(eflat_xml_model_eolian_files:%.eo=%.eo.lua)
76
77generated_eflat_xml_model_lua_all = $(eflat_xml_model_eolian_lua)
78
79CLEANFILES += $(generated_eflat_xml_model_lua_all)
80
81installed_eflat_xml_modelluadir = $(datadir)/elua/modules/eflat_xml_model
82nodist_installed_eflat_xml_modellua_DATA = $(generated_eflat_xml_model_lua_all)
83
84endif
diff --git a/src/Makefile_EflatXmlModel_Cxx.am b/src/Makefile_EflatXmlModel_Cxx.am
new file mode 100644
index 0000000000..ea5b451a01
--- /dev/null
+++ b/src/Makefile_EflatXmlModel_Cxx.am
@@ -0,0 +1,22 @@
1if HAVE_CXX11
2
3### Generated headers
4
5generated_eflat_xml_model_cxx_bindings = $(eflat_xml_model_eolian_files:%.eo=%.eo.hh)
6
7lib/eflat_xml_model/Eflat_xml_model.hh: $(generated_eflat_xml_model_cxx_bindings)
8 @echo @ECHO_E@ "#ifndef EFL_CXX_EFLAT_XML_MODEL_HH\n#define EFL_CXX_EFLAT_XML_MODEL_HH\n" > $(top_builddir)/src/lib/eflat_xml_model/Eflat_xml_model.hh
9 @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eflat_xml_model/Eflat_xml_model.hh
10 @for i in $(generated_eflat_xml_model_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eflat_xml_model/Eflat_xml_model.hh; done
11 @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eflat_xml_model/Eflat_xml_model.hh
12
13generated_eflat_xml_model_cxx_all = \
14 $(generated_eflat_xml_model_cxx_bindings) \
15 lib/eflat_xml_model/Eflat_xml_model.hh
16
17CLEANFILES += $(generated_eflat_xml_model_cxx_all)
18
19installed_eflat_xml_modelcxxmainheadersdir = $(includedir)/eflat_xml_model-cxx-@VMAJ@/
20nodist_installed_eflat_xml_modelcxxmainheaders_DATA = $(generated_eflat_xml_model_cxx_all)
21
22endif
diff --git a/src/lib/eflat_xml_model/Eflat_Xml_Model.h b/src/lib/eflat_xml_model/Eflat_Xml_Model.h
new file mode 100644
index 0000000000..19b17eb31a
--- /dev/null
+++ b/src/lib/eflat_xml_model/Eflat_Xml_Model.h
@@ -0,0 +1,62 @@
1#ifndef EFLAT_XML_H
2#define EFLAT_XML_H
3
4#include <Ecore.h>
5#include <Efl.h>
6#include <Efl_Config.h>
7
8#ifdef EAPI
9# undef EAPI
10#endif
11
12#ifdef _WIN32
13# ifdef EFL_EFLAT_XML_MODEL_BUILD
14# ifdef DLL_EXPORT
15# define EAPI __declspec(dllexport)
16# else
17# define EAPI
18# endif /* ! DLL_EXPORT */
19# else
20# define EAPI __declspec(dllimport)
21# endif /* ! EFL_EFLAT_XML_MODEL_BUILD */
22#else
23# ifdef __GNUC__
24# if __GNUC__ >= 4
25# define EAPI __attribute__ ((visibility("default")))
26# else
27# define EAPI
28# endif
29# else
30# define EAPI
31# endif
32#endif /* ! _WIN32 */
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38/**
39 * @brief Initialize eflat_xml_model.
40 *
41 * @return 1 or greater on success, 0 otherwise
42 */
43EAPI int eflat_xml_model_init(void);
44/**
45 * @brief Shutdown eflat_xml_model.
46 *
47 * @return 0 if eflat_xml_model shuts down, greater than 0 otherwise.
48 */
49EAPI int eflat_xml_model_shutdown(void);
50
51#ifdef EFL_EO_API_SUPPORT
52# include <eflat_xml_model.eo.h>
53#endif
54
55#ifdef __cplusplus
56}
57#endif
58
59#undef EAPI
60#define EAPI
61
62#endif
diff --git a/src/lib/eflat_xml_model/eflat_xml_model.c b/src/lib/eflat_xml_model/eflat_xml_model.c
new file mode 100644
index 0000000000..0588f92e49
--- /dev/null
+++ b/src/lib/eflat_xml_model/eflat_xml_model.c
@@ -0,0 +1,1049 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eflat_xml_model_private.h"
6
7#include <stdbool.h>
8#include <stdint.h>
9#include <stdlib.h>
10
11#define MY_CLASS EFLAT_XML_MODEL_CLASS
12#define MY_CLASS_NAME "Eflat_Xml_Model"
13
14typedef enum
15{
16 EFLAT_XML_MODEL_PATH_TYPE_DATA,
17 EFLAT_XML_MODEL_PATH_TYPE_ATTRIBUTE,
18 EFLAT_XML_MODEL_PATH_TYPE_PROCESSING,
19 EFLAT_XML_MODEL_PATH_TYPE_RAW_XML
20} Eflat_Xml_Model_Path_Type;
21
22typedef struct
23{
24 Eina_Simple_XML_Node_Tag *node;
25 Eflat_Xml_Model_Path_Type type;
26 union
27 {
28 Eina_Simple_XML_Attribute *attribute;
29 Eina_Simple_XML_Node_Processing *processing;
30 };
31} Eflat_Xml_Model_Path_Data;
32
33static void _properties_load(Eflat_Xml_Model_Data *);
34static void _children_load(Eflat_Xml_Model_Data *);
35static bool _init(Eflat_Xml_Model_Data *);
36static void _clear(Eflat_Xml_Model_Data *);
37static void _properties_setup(Eflat_Xml_Model_Data *);
38static Eina_Simple_XML_Node_Tag *_tag_find(Eina_Simple_XML_Node_Tag *, const char *);
39static Eina_Simple_XML_Attribute *_attribute_find(Eina_Simple_XML_Node_Tag *, const char *);
40static Eina_Simple_XML_Node_Tag *_node_from_path_new(Eina_Simple_XML_Node_Root *, const char *, Eflat_Xml_Model_Path_Data *);
41static Eina_Simple_XML_Node_Tag *_node_from_path_get(Eina_Simple_XML_Node_Root *, const char *, Eflat_Xml_Model_Path_Data *);
42static void _node_children_del(Eina_Simple_XML_Node_Tag *);
43static char *_path_from_node_get(Eina_Simple_XML_Node_Tag *);
44static char *_concatenate_path(const char *, const char *, char);
45static void _node_children_properties_del(Eflat_Xml_Model_Data *, Eina_Simple_XML_Node_Tag *, const char *);
46static void _node_attributes_properties_del(Eflat_Xml_Model_Data *, Eina_Simple_XML_Node_Tag *, const char *);
47static void _property_del(Eflat_Xml_Model_Data *, const char *);
48static void _property_add(Eflat_Xml_Model_Data *, const char *, const char *);
49static void _node_clear(Eflat_Xml_Model_Data *, Eina_Simple_XML_Node_Tag *);
50static void _generate_properties_from_node(Eflat_Xml_Model_Data *, Eina_Simple_XML_Node_Tag *);
51static Eina_Simple_XML_Node_Data *_data_value_set(Eina_Simple_XML_Node_Tag *, Eina_Simple_XML_Node_Data *, const char *);
52static char *_data_name_get(const Eina_Simple_XML_Node_Data *);
53static void _stream_load(Eflat_Xml_Model_Data *, Eina_Simple_XML_Node_Tag *, const char *);
54
55static int _eflat_xml_model_init_count = 0;
56int _eflat_xml_model_log_dom = -1;
57
58EAPI int
59eflat_xml_model_init(void)
60{
61 if (_eflat_xml_model_init_count++ > 0)
62 return _eflat_xml_model_init_count;
63
64 if (!eina_init())
65 {
66 fputs("Eflat_Xml_Model: Unable to initialize eina\n", stderr);
67 return 0;
68 }
69
70 _eflat_xml_model_log_dom = eina_log_domain_register("eflat_xml_model",
71 EINA_COLOR_CYAN);
72 if (_eflat_xml_model_log_dom < 0)
73 {
74 EINA_LOG_ERR("Unable to create an 'eflat_xml_model' log domain");
75 _eflat_xml_model_log_dom = -1;
76 eina_shutdown();
77 return 0;
78 }
79
80 if (!ecore_init())
81 {
82 ERR("Unable to initialize ecore");
83 eina_log_domain_unregister(_eflat_xml_model_log_dom);
84 _eflat_xml_model_log_dom = -1;
85 eina_shutdown();
86 return 0;
87 }
88
89 // ...
90
91 return _eflat_xml_model_init_count;
92}
93
94EAPI int
95eflat_xml_model_shutdown(void)
96{
97 if (_eflat_xml_model_init_count <= 0)
98 {
99 ERR("Init count not greater than 0 in shutdown.");
100 _eflat_xml_model_init_count = 0;
101 return 0;
102 }
103
104 if (--_eflat_xml_model_init_count)
105 return _eflat_xml_model_init_count;
106
107 // ...
108
109 ecore_shutdown();
110 eina_log_domain_unregister(_eflat_xml_model_log_dom);
111 _eflat_xml_model_log_dom = -1;
112 eina_shutdown();
113 return 0;
114}
115
116static void
117_eflat_xml_model_hash_free(Eina_Value *value)
118{
119 eina_value_free(value);
120}
121
122static Eo_Base *
123_eflat_xml_model_eo_base_constructor(Eo *obj, Eflat_Xml_Model_Data *pd)
124{
125 DBG("(%p)", obj);
126
127 pd->obj = obj;
128 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
129 pd->properties_array = NULL;
130 pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eflat_xml_model_hash_free));
131 pd->root = NULL;
132 pd->xml = NULL;
133 eina_value_setup(&pd->xml_value, EINA_VALUE_TYPE_STRING);
134
135 return eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
136}
137
138static void
139_eflat_xml_model_constructor(Eo *obj EINA_UNUSED,
140 Eflat_Xml_Model_Data *pd EINA_UNUSED,
141 const char *xml)
142{
143 DBG("(%p)", obj);
144 pd->xml = strdup(xml ? xml : "");
145}
146
147static void
148_eflat_xml_model_eo_base_destructor(Eo *obj, Eflat_Xml_Model_Data *pd)
149{
150 DBG("(%p)", obj);
151
152 _clear(pd);
153 eina_hash_free(pd->properties_hash);
154 free(pd->xml);
155 eina_value_flush(&pd->xml_value);
156
157 eo_do_super(obj, MY_CLASS, eo_destructor());
158}
159
160static Efl_Model_Load_Status
161_eflat_xml_model_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
162 Eflat_Xml_Model_Data *pd,
163 Eina_Array * const* properties_array)
164{
165 DBG("(%p)", obj);
166 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
167 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
168
169 *(Eina_Array**)properties_array = pd->properties_array;
170 return pd->load.status;
171}
172
173static void
174_eflat_xml_model_efl_model_base_properties_load(Eo *obj, Eflat_Xml_Model_Data *pd)
175{
176 DBG("(%p)", obj);
177
178 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
179 return;
180
181 if (!_init(pd))
182 return;
183
184 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
185
186 _properties_load(pd);
187
188 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
189}
190
191static void
192_properties_load(Eflat_Xml_Model_Data *pd)
193{
194 DBG("(%p)", pd->obj);
195
196 _properties_setup(pd);
197
198 if (!pd->xml)
199 return;
200
201 _generate_properties_from_node(pd, pd->root);
202}
203
204static Efl_Model_Load_Status
205_eflat_xml_model_efl_model_base_property_set(Eo *obj,
206 Eflat_Xml_Model_Data *pd,
207 const char *property,
208 const Eina_Value *value)
209{
210 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
211 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
212 DBG("(%p): property=%s", obj, property);
213
214 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
215 return EFL_MODEL_LOAD_STATUS_ERROR;
216
217 Eflat_Xml_Model_Path_Data data;
218 Eina_Simple_XML_Node_Tag *node = _node_from_path_new(pd->root,
219 property,
220 &data);
221 EINA_SAFETY_ON_NULL_RETURN_VAL(node, EFL_MODEL_LOAD_STATUS_ERROR);
222 DBG("(%p)", obj);
223
224 char *value_str = eina_value_to_string(value);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(value_str, EFL_MODEL_LOAD_STATUS_ERROR);
226
227 switch (data.type)
228 {
229 case EFLAT_XML_MODEL_PATH_TYPE_ATTRIBUTE:
230 {
231 eina_stringshare_del(data.attribute->value);
232 data.attribute->value = eina_stringshare_add(value_str);
233 break;
234 }
235 case EFLAT_XML_MODEL_PATH_TYPE_RAW_XML:
236 {
237 _stream_load(pd, node, value_str);
238 break;
239 }
240 case EFLAT_XML_MODEL_PATH_TYPE_DATA:
241 {
242 _node_clear(pd, node);
243
244 // checks if it's a empty tag
245 size_t len = strlen(value_str);
246 if (len)
247 eina_simple_xml_node_data_new(node, value_str, len);
248 break;
249 }
250 case EFLAT_XML_MODEL_PATH_TYPE_PROCESSING:
251 {
252 Eina_Simple_XML_Node_Data *processing = _data_value_set
253 (node, data.processing, value_str);
254 EINA_SAFETY_ON_NULL_GOTO(processing, on_error);
255 break;
256 }
257 }
258
259 if (data.type != EFLAT_XML_MODEL_PATH_TYPE_RAW_XML)
260 {
261 // TODO: Check if the property exists instead of deleting it
262 _property_del(pd, property);
263 _property_add(pd, property, value_str);
264 }
265
266 free(value_str);
267
268 efl_model_property_changed_notify(obj, property);
269
270 return pd->load.status;
271
272on_error:
273 free(value_str);
274 return EFL_MODEL_LOAD_STATUS_ERROR;
275}
276
277static Efl_Model_Load_Status
278_eflat_xml_model_efl_model_base_property_get(Eo *obj EINA_UNUSED,
279 Eflat_Xml_Model_Data *pd,
280 const char *property,
281 const Eina_Value **value)
282{
283 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
284 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
285 DBG("(%p): property=%s", obj, property);
286
287 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
288 return EFL_MODEL_LOAD_STATUS_ERROR;
289
290 Eflat_Xml_Model_Path_Data data;
291 Eina_Simple_XML_Node_Tag *node = _node_from_path_get(pd->root,
292 property,
293 &data);
294 if (!node)
295 {
296 ERR("Property doesn't exists: %s", property);
297 return EFL_MODEL_LOAD_STATUS_ERROR;
298 };
299
300 if (data.type == EFLAT_XML_MODEL_PATH_TYPE_RAW_XML)
301 {
302 Eina_Strbuf *buf = eina_strbuf_new();
303 EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EFL_MODEL_LOAD_STATUS_ERROR);
304
305 Eina_Simple_XML_Node *child;
306 EINA_INLIST_FOREACH(node->children, child)
307 {
308 char *dump = eina_simple_xml_node_dump(child, " ");
309 Eina_Bool ret = eina_strbuf_append(buf, dump);
310 free(dump);
311 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
312 }
313
314 Eina_Bool ret = eina_value_set(&pd->xml_value, eina_strbuf_string_get(buf));
315 eina_strbuf_free(buf);
316 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
317
318 *value = &pd->xml_value;
319 return pd->load.status;
320 }
321
322 *value = eina_hash_find(pd->properties_hash, property);
323 if (!(*value))
324 {
325 ERR("Property doesn't exist: %s", property);
326 return EFL_MODEL_LOAD_STATUS_ERROR;
327 }
328
329 return pd->load.status;
330}
331
332static void
333_eflat_xml_model_efl_model_base_load(Eo *obj, Eflat_Xml_Model_Data *pd)
334{
335 DBG("(%p)", obj);
336
337 if ((pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED) == EFL_MODEL_LOAD_STATUS_LOADED)
338 return;
339
340 if (!_init(pd))
341 return;
342
343 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
344 {
345 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
346 _properties_load(pd);
347 }
348
349 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
350 {
351 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
352 _children_load(pd);
353 }
354
355 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED);
356}
357
358static Efl_Model_Load_Status
359_eflat_xml_model_efl_model_base_load_status_get(Eo *obj EINA_UNUSED,
360 Eflat_Xml_Model_Data *pd)
361{
362 DBG("(%p)", obj);
363 return pd->load.status;
364}
365
366static void
367_eflat_xml_model_efl_model_base_unload(Eo *obj, Eflat_Xml_Model_Data *pd)
368{
369 DBG("(%p)", obj);
370
371 _clear(pd);
372
373 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
374}
375
376Eo *
377_eflat_xml_model_efl_model_base_child_add(Eo *obj EINA_UNUSED,
378 Eflat_Xml_Model_Data *pd EINA_UNUSED)
379{
380 DBG("(%p)", obj);
381 return NULL;
382}
383
384static Efl_Model_Load_Status
385_eflat_xml_model_efl_model_base_child_del(Eo *obj EINA_UNUSED,
386 Eflat_Xml_Model_Data *pd EINA_UNUSED,
387 Eo *child EINA_UNUSED)
388{
389 DBG("(%p)", obj);
390 return EFL_MODEL_LOAD_STATUS_ERROR;
391}
392
393static Efl_Model_Load_Status
394_eflat_xml_model_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
395 Eflat_Xml_Model_Data *pd,
396 unsigned start EINA_UNUSED,
397 unsigned count EINA_UNUSED,
398 Eina_Accessor **children_accessor)
399{
400 DBG("(%p)", obj);
401 *children_accessor = NULL;
402 return pd->load.status;
403}
404
405static Efl_Model_Load_Status
406_eflat_xml_model_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
407 Eflat_Xml_Model_Data *pd,
408 unsigned *children_count)
409{
410 DBG("(%p)", obj);
411 *children_count = 0;
412 return pd->load.status;
413}
414
415static void
416_eflat_xml_model_efl_model_base_children_load(Eo *obj, Eflat_Xml_Model_Data *pd)
417{
418 DBG("(%p)", obj);
419
420 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
421 return;
422
423 if (!_init(pd))
424 return;
425
426 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
427
428 _children_load(pd);
429
430 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
431}
432
433static void
434_children_load(Eflat_Xml_Model_Data *pd)
435{
436 DBG("(%p)", pd->obj);
437}
438
439static bool
440_init(Eflat_Xml_Model_Data *pd)
441{
442 if (!pd->root)
443 pd->root = eina_simple_xml_node_load(pd->xml, strlen(pd->xml), EINA_TRUE);
444 return true;
445}
446
447static void
448_clear(Eflat_Xml_Model_Data *pd)
449{
450 EINA_SAFETY_ON_NULL_RETURN(pd);
451
452 eina_hash_free_buckets(pd->properties_hash);
453
454 if (pd->properties_array)
455 {
456 size_t i;
457 char *property;
458 Eina_Array_Iterator it;
459 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
460 free(property);
461 eina_array_free(pd->properties_array);
462 pd->properties_array = NULL;
463 }
464
465 eina_simple_xml_node_root_free(pd->root);
466 pd->root = NULL;
467
468 free(pd->xml);
469 pd->xml = strdup("");
470 eina_value_set(&pd->xml_value, "");
471}
472
473static void
474_properties_setup(Eflat_Xml_Model_Data *pd)
475{
476 DBG("(%p)", pd->obj);
477
478 pd->properties_array = eina_array_new(1);
479}
480
481static Eina_Simple_XML_Node_Tag *
482_tag_find(Eina_Simple_XML_Node_Tag *node, const char *name)
483{
484 if (!node) return NULL;
485
486 Eina_Simple_XML_Node *child;
487 EINA_INLIST_FOREACH(node->children, child)
488 {
489 if (EINA_SIMPLE_XML_NODE_TAG == child->type)
490 {
491 Eina_Simple_XML_Node_Tag *tag = (Eina_Simple_XML_Node_Tag*)child;
492 if (strcmp(name, tag->name) == 0)
493 return tag;
494 }
495 }
496
497 return NULL;
498}
499
500static bool
501_space_is(char c)
502{
503 return '\x20' == c || '\x9' == c || '\xD' == c || '\xA' == c;
504}
505
506static char *
507_data_name_get(const Eina_Simple_XML_Node_Data *data)
508{
509 if (!data) return NULL;
510
511 size_t name_length = data->length;
512
513 const char *separator = NULL;
514 const char *pos = data->data;
515 const char *end = pos + name_length;
516 while (pos < end)
517 {
518 if (_space_is(*pos))
519 {
520 separator = pos;
521 break;
522 }
523 ++pos;
524 }
525 if (separator)
526 name_length = (size_t)(ptrdiff_t)(separator - data->data);
527
528 char *name = malloc(name_length + 1);
529 strncpy(name, data->data, name_length);
530 name[name_length] = '\0';
531 return name;
532}
533
534static Eina_Simple_XML_Node_Data *
535_eflat_xml_model_data_find(Eina_Simple_XML_Node_Tag *node,
536 const char *name,
537 Eina_Simple_XML_Node_Type type)
538{
539 if (!node) return NULL;
540
541 const size_t name_length = strlen(name);
542
543 Eina_Simple_XML_Node *child;
544 EINA_INLIST_FOREACH(node->children, child)
545 {
546 if (type != child->type)
547 continue;
548
549 Eina_Simple_XML_Node_Data *data = (Eina_Simple_XML_Node_Data*)child;
550 if (name_length > data->length)
551 continue;
552
553 if (strncmp(data->data, name, name_length) != 0)
554 continue;
555
556 if ((data->length > name_length) && !_space_is(data->data[name_length]))
557 continue;
558
559 return data;
560 }
561
562 return NULL;
563}
564
565static Eina_Simple_XML_Attribute *
566_attribute_find(Eina_Simple_XML_Node_Tag *node, const char *key)
567{
568 if (!node) return NULL;
569
570 Eina_Simple_XML_Attribute *attr;
571 EINA_INLIST_FOREACH(node->attributes, attr)
572 {
573 if (strcmp(key, attr->key) == 0)
574 return attr;
575 }
576
577 return NULL;
578}
579
580static Eina_Simple_XML_Node_Tag *
581_node_new(Eina_Simple_XML_Node_Tag *parent, const char *name)
582{
583 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
584 Eina_Simple_XML_Node_Tag *child = _tag_find(parent, name);
585 if (!child)
586 child = eina_simple_xml_node_tag_new(parent, name);
587
588 return child;
589}
590
591static Eina_Simple_XML_Attribute *
592_attr_new(Eina_Simple_XML_Node_Tag *parent, const char *key)
593{
594 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
595 Eina_Simple_XML_Attribute *attr = _attribute_find(parent, key);
596 if (!attr)
597 attr = eina_simple_xml_attribute_new(parent, key, "");
598
599 return attr;
600}
601
602static Eina_Simple_XML_Node_Data *
603_data_new(Eina_Simple_XML_Node_Tag *parent,
604 const char *name,
605 Eina_Simple_XML_Node_Type type)
606{
607 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
608 Eina_Simple_XML_Node_Data *data = _eflat_xml_model_data_find(parent, name, type);
609 if (data)
610 return data;
611
612 switch (type)
613 {
614 case EINA_SIMPLE_XML_NODE_PROCESSING:
615 return eina_simple_xml_node_processing_new(parent, name, strlen(name));
616 default:
617 ERR("Node type not supported: %d", type);
618 return NULL;
619 }
620}
621
622static const char *
623_next_node_name(char **it, char c)
624{
625 char *separator = strchr(*it, c);
626 if (!separator) return NULL;
627
628 *separator = '\0';
629 char *node_name = *it;
630 *it = separator + 1;
631 return node_name;
632}
633
634typedef struct
635{
636 Eina_Simple_XML_Node_Tag *(*node_find)(Eina_Simple_XML_Node_Tag *, const char *);
637 Eina_Simple_XML_Attribute *(*attr_find)(Eina_Simple_XML_Node_Tag *, const char *);
638 Eina_Simple_XML_Node_Data *(*data_find)(Eina_Simple_XML_Node_Tag *, const char *, Eina_Simple_XML_Node_Type);
639} Eflat_Xml_Model_Path_Operators;
640
641static const Eflat_Xml_Model_Path_Operators
642_const_path_operators = {
643 .node_find = _tag_find,
644 .attr_find = _attribute_find,
645 .data_find = _eflat_xml_model_data_find,
646};
647
648static const Eflat_Xml_Model_Path_Operators
649_new_path_operators = {
650 .node_find = _node_new,
651 .attr_find = _attr_new,
652 .data_find = _data_new,
653};
654
655static Eina_Simple_XML_Node_Tag *
656_node_path(Eina_Simple_XML_Node_Root *root,
657 const char *path,
658 Eflat_Xml_Model_Path_Data *data,
659 Eflat_Xml_Model_Path_Operators ops)
660{
661 EINA_SAFETY_ON_NULL_RETURN_VAL(root, NULL);
662 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
663
664 *data = (Eflat_Xml_Model_Path_Data){0};
665 Eina_Simple_XML_Node_Tag *node = (Eina_Simple_XML_Node_Tag*)root;
666
667 char *path_tmp = strdup(path);
668 char *it = path_tmp;
669
670 const char *node_name;
671 while ((node_name = _next_node_name(&it, '/')))
672 {
673 if (strlen(node_name))
674 {
675 node = ops.node_find(node, node_name);
676 if (!node) goto on_error;
677 }
678 }
679
680 if ((node_name = _next_node_name(&it, '@')))
681 {
682 if (!strlen(node_name)) goto on_error; // attribute cannot be assigned to root
683
684 node = ops.node_find(node, node_name);
685 if (!node) goto on_error;
686
687 char *attr_key = it;
688 if (strlen(attr_key) == 0)
689 {
690 ERR("Attributes cannot have null key: %s", path);
691 goto on_error;
692 }
693
694 data->attribute = ops.attr_find(node, attr_key);
695 if (!data->attribute) goto on_error;
696 data->type = EFLAT_XML_MODEL_PATH_TYPE_ATTRIBUTE;
697 }
698 else
699 if ((node_name = _next_node_name(&it, '?')))
700 {
701 if (strlen(node_name))
702 {
703 node = ops.node_find(node, node_name);
704 if (!node) goto on_error;
705 }
706
707 char *processing_key = it;
708 if (strlen(processing_key) == 0)
709 {
710 ERR("Processing tags cannot have null name: %s", path);
711 goto on_error;
712 }
713
714 data->processing = (Eina_Simple_XML_Node_Processing*)
715 ops.data_find(node, processing_key, EINA_SIMPLE_XML_NODE_PROCESSING);
716 if (!data->processing) goto on_error;
717 data->type = EFLAT_XML_MODEL_PATH_TYPE_PROCESSING;
718 }
719 else
720 {
721 node_name = it;
722 if (strlen(node_name) == 0) // terminating with '/'
723 data->type = EFLAT_XML_MODEL_PATH_TYPE_RAW_XML;
724 else
725 {
726 node = ops.node_find(node, node_name);
727 if (!node) goto on_error;
728 data->type = EFLAT_XML_MODEL_PATH_TYPE_DATA;
729 }
730 }
731
732 free(path_tmp);
733 return node;
734
735on_error:
736 free(path_tmp);
737 return NULL;
738}
739
740static Eina_Simple_XML_Node_Tag *
741_node_from_path_new(Eina_Simple_XML_Node_Root *root,
742 const char *path,
743 Eflat_Xml_Model_Path_Data *data)
744{
745 return _node_path(root, path, data, _new_path_operators);
746}
747
748static Eina_Simple_XML_Node_Tag *
749_node_from_path_get(Eina_Simple_XML_Node_Root *root,
750 const char *path,
751 Eflat_Xml_Model_Path_Data *data)
752{
753 return _node_path(root, path, data, _const_path_operators);
754}
755
756static void
757_node_children_del(Eina_Simple_XML_Node_Tag *tag)
758{
759 while (tag->children)
760 {
761 Eina_Simple_XML_Node *node = EINA_INLIST_CONTAINER_GET(tag->children,
762 Eina_Simple_XML_Node);
763 if (EINA_SIMPLE_XML_NODE_TAG == node->type)
764 eina_simple_xml_node_tag_free((Eina_Simple_XML_Node_Tag*)node);
765 else
766 eina_simple_xml_node_data_free((Eina_Simple_XML_Node_Data*)node);
767 }
768}
769
770static char *
771_path_from_node_get(Eina_Simple_XML_Node_Tag *tag)
772{
773 EINA_SAFETY_ON_NULL_RETURN_VAL(tag, NULL);
774
775 Eina_Strbuf *buf = eina_strbuf_new();
776 EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
777
778 Eina_Bool ret = eina_strbuf_append(buf, tag->name ? tag->name : "");
779 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
780
781 Eina_Simple_XML_Node_Tag *parent = tag;
782 while ((parent = parent->base.parent) && parent->name)
783 {
784 ret = eina_strbuf_prepend(buf, "/")
785 && eina_strbuf_prepend(buf, parent->name);
786 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
787 }
788
789 char *result = eina_strbuf_string_steal(buf);
790 eina_strbuf_free(buf);
791 return result;
792
793on_error:
794 eina_strbuf_free(buf);
795 return NULL;
796}
797
798static char *
799_concatenate_path(const char *path, const char *child, char separator)
800{
801 int len = strlen(path) + sizeof(separator) + strlen(child) + 1;
802
803 char *child_path = malloc(len);
804 EINA_SAFETY_ON_NULL_RETURN_VAL(child_path, NULL);
805
806 int written = snprintf(child_path, len, "%s%c%s", path, separator, child);
807 EINA_SAFETY_ON_FALSE_GOTO((written > 0) && (written < len), on_error);
808
809 return child_path;
810
811on_error:
812 free(child_path);
813 return NULL;
814}
815
816static void
817_node_children_properties_del(Eflat_Xml_Model_Data *pd,
818 Eina_Simple_XML_Node_Tag *tag,
819 const char *path)
820{
821 DBG("(%p)", pd->obj);
822 Eina_Simple_XML_Node *child;
823 EINA_INLIST_FOREACH(tag->children, child)
824 {
825 switch (child->type)
826 {
827 case EINA_SIMPLE_XML_NODE_TAG:
828 {
829 Eina_Simple_XML_Node_Tag *child_tag = (Eina_Simple_XML_Node_Tag*)child;
830
831 char *child_path = _concatenate_path(path, child_tag->name, '/');
832 EINA_SAFETY_ON_NULL_RETURN(child_path);
833
834 _property_del(pd, child_path);
835 _node_children_properties_del(pd, child_tag, child_path);
836 _node_attributes_properties_del(pd, child_tag, child_path);
837
838 free(child_path);
839 break;
840 }
841 default:
842 break;
843 }
844 }
845}
846
847static void
848_node_attributes_properties_del(Eflat_Xml_Model_Data *pd,
849 Eina_Simple_XML_Node_Tag *tag,
850 const char *path)
851{
852 Eina_Simple_XML_Attribute *attr;
853 EINA_INLIST_FOREACH(tag->attributes, attr)
854 {
855 char *attr_path = _concatenate_path(path, attr->key, '@');
856 _property_del(pd, attr_path);
857 free(attr_path);
858 }
859}
860
861static Eina_Bool
862_property_array_keep_cb(void *data, void *gdata)
863{
864 char *a = (char *)data;
865 const char *b = (char *)gdata;
866
867 if (strcmp(a, b) != 0) return EINA_TRUE;
868
869 free(a);
870 return EINA_FALSE;
871}
872
873static void
874_property_del(Eflat_Xml_Model_Data *pd, const char *property)
875{
876 DBG("(%p) deleting property %s", pd->obj, property);
877 eina_hash_del(pd->properties_hash, property, NULL);
878
879 eina_array_remove(pd->properties_array,
880 _property_array_keep_cb,
881 (void*)property);
882}
883
884static void
885_property_add(Eflat_Xml_Model_Data *pd, const char *property, const char *value)
886{
887 EINA_SAFETY_ON_NULL_RETURN(property);
888 EINA_SAFETY_ON_NULL_RETURN(value);
889
890 DBG("(%p) adding property %s=%s", pd->obj, property, value);
891
892 char *property_copy = strdup(property);
893 EINA_SAFETY_ON_NULL_RETURN(property_copy);
894
895 Eina_Bool ret = eina_array_push(pd->properties_array, property_copy);
896 EINA_SAFETY_ON_FALSE_RETURN(ret);
897
898 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, property);
899 if (!prop_value)
900 {
901 prop_value = eina_value_new(EINA_VALUE_TYPE_STRING);
902 EINA_SAFETY_ON_NULL_RETURN(prop_value);
903
904 ret = eina_hash_add(pd->properties_hash, property, prop_value);
905 EINA_SAFETY_ON_FALSE_RETURN(ret);
906 }
907
908 ret = eina_value_set(prop_value, value);
909 EINA_SAFETY_ON_FALSE_RETURN(ret);
910}
911
912static void
913_node_clear(Eflat_Xml_Model_Data *pd, Eina_Simple_XML_Node_Tag *node)
914{
915 DBG("(%p)", pd->obj);
916 EINA_SAFETY_ON_NULL_RETURN(node);
917 char *path = _path_from_node_get(node);
918 EINA_SAFETY_ON_NULL_RETURN(path);
919
920 DBG("(%p)", pd->obj);
921 _node_children_properties_del(pd, node, path);
922 free(path);
923
924 _node_children_del(node);
925}
926
927static void
928_generate_properties_from_node(Eflat_Xml_Model_Data *pd,
929 Eina_Simple_XML_Node_Tag *node)
930{
931 char *path = _path_from_node_get(node);
932
933 Eina_Simple_XML_Attribute *attr;
934 EINA_INLIST_FOREACH(node->attributes, attr)
935 {
936 char *attr_path = _concatenate_path(path, attr->key, '@');
937 _property_add(pd, attr_path, attr->value);
938 free(attr_path);
939 }
940
941 size_t lines_count = 0;
942 Eina_Strbuf *buf = eina_strbuf_new();
943
944 Eina_Simple_XML_Node *child;
945 EINA_INLIST_FOREACH(node->children, child)
946 {
947 switch (child->type)
948 {
949 case EINA_SIMPLE_XML_NODE_TAG:
950 _generate_properties_from_node(pd, (Eina_Simple_XML_Node_Tag*)child);
951 break;
952 case EINA_SIMPLE_XML_NODE_DATA:
953 {
954 Eina_Simple_XML_Node_Data *data = (Eina_Simple_XML_Node_Data*)child;
955 if (!data->length) break;
956 eina_strbuf_append_length(buf, data->data, data->length);
957 if (lines_count > 0)
958 eina_strbuf_append(buf, "\n");
959 ++lines_count;
960 break;
961 }
962 case EINA_SIMPLE_XML_NODE_PROCESSING:
963 {
964 const Eina_Simple_XML_Node_Processing *data = (Eina_Simple_XML_Node_Processing*)child;
965
966 char *name = _data_name_get(data);
967 char *processing_path = _concatenate_path(path, name, '?');
968
969 size_t name_length = strlen(name);
970 if (data->length == name_length)
971 _property_add(pd, processing_path, "");
972 else
973 _property_add(pd, processing_path, data->data + name_length + 1);
974
975 free(processing_path);
976 free(name);
977 break;
978 }
979 default:
980 ERR("Node type not supported: %d", child->type);
981 break;
982 }
983 }
984
985 if (lines_count)
986 _property_add(pd, path, eina_strbuf_string_get(buf));
987
988 eina_strbuf_free(buf);
989 free(path);
990}
991
992static Eina_Simple_XML_Node_Data *
993_data_value_set(Eina_Simple_XML_Node_Tag *node,
994 Eina_Simple_XML_Node_Data *data,
995 const char *value)
996{
997 Eina_Strbuf *buf = eina_strbuf_new();
998 EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
999
1000 char *name = _data_name_get(data);
1001 EINA_SAFETY_ON_NULL_GOTO(name, on_error_1);
1002
1003 Eina_Bool ret = eina_strbuf_append_printf(buf, "%s %s", name, value);
1004 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error_2);
1005
1006 Eina_Simple_XML_Node_Data *processing = eina_simple_xml_node_processing_new
1007 (node, eina_strbuf_string_get(buf), eina_strbuf_length_get(buf));
1008
1009 eina_simple_xml_node_processing_free(data);
1010 free(name);
1011 eina_strbuf_free(buf);
1012 return processing;
1013
1014on_error_2:
1015 free(name);
1016on_error_1:
1017 eina_strbuf_free(buf);
1018 return NULL;
1019}
1020
1021static void
1022_stream_load(Eflat_Xml_Model_Data *pd,
1023 Eina_Simple_XML_Node_Tag *node,
1024 const char *xml)
1025{
1026 _node_clear(pd, node);
1027
1028 Eina_Simple_XML_Node_Root *root = eina_simple_xml_node_load(xml,
1029 strlen(xml),
1030 EINA_TRUE);
1031 // steals root items
1032 Eina_Simple_XML_Node *child;
1033 EINA_INLIST_FOREACH(root->children, child)
1034 child->parent = node;
1035 node->children = root->children;
1036 root->children = NULL;
1037
1038 Eina_Simple_XML_Attribute *attr;
1039 EINA_INLIST_FOREACH(root->attributes, attr)
1040 attr->parent = node;
1041 node->attributes = root->attributes;
1042 root->attributes = NULL;
1043
1044 eina_simple_xml_node_root_free(root);
1045
1046 _generate_properties_from_node(pd, node);
1047}
1048
1049#include "eflat_xml_model.eo.c"
diff --git a/src/lib/eflat_xml_model/eflat_xml_model.eo b/src/lib/eflat_xml_model/eflat_xml_model.eo
new file mode 100644
index 0000000000..6cf9eebc7e
--- /dev/null
+++ b/src/lib/eflat_xml_model/eflat_xml_model.eo
@@ -0,0 +1,34 @@
1class Eflat_Xml.Model (Eo.Base, Efl.Model.Base) {
2 legacy_prefix: null;
3 methods {
4 constructor {
5 [[Custom Eflat_Xml_Model constructor.
6 @.constructor
7
8 @since 1.13
9 ]]
10 params {
11 xml: const(char)*; [[The XML document]]
12 }
13 }
14 }
15 implements {
16 Eo.Base.constructor;
17 Eo.Base.destructor;
18 Efl.Model.Base.properties.get;
19 Efl.Model.Base.properties_load;
20 Efl.Model.Base.property.set;
21 Efl.Model.Base.property.get;
22 Efl.Model.Base.load;
23 Efl.Model.Base.load_status.get;
24 Efl.Model.Base.unload;
25 Efl.Model.Base.child_add;
26 Efl.Model.Base.child_del;
27 Efl.Model.Base.children_slice.get;
28 Efl.Model.Base.children_count.get;
29 Efl.Model.Base.children_load;
30 }
31 constructors {
32 .constructor;
33 }
34}
diff --git a/src/lib/eflat_xml_model/eflat_xml_model_private.h b/src/lib/eflat_xml_model/eflat_xml_model_private.h
new file mode 100644
index 0000000000..f27837f5fe
--- /dev/null
+++ b/src/lib/eflat_xml_model/eflat_xml_model_private.h
@@ -0,0 +1,34 @@
1#ifndef _EFLAT_XML_MODEL_PRIVATE_H
2#define _EFLAT_XML_MODEL_PRIVATE_H
3
4#include "Eflat_Xml_Model.h"
5
6#include <stdbool.h>
7
8/* logging support */
9extern int _eflat_xml_model_log_dom;
10
11#define CRI(...) EINA_LOG_DOM_CRIT(_eflat_xml_model_log_dom, __VA_ARGS__)
12#define ERR(...) EINA_LOG_DOM_ERR(_eflat_xml_model_log_dom, __VA_ARGS__)
13#define WRN(...) EINA_LOG_DOM_WARN(_eflat_xml_model_log_dom, __VA_ARGS__)
14#define INF(...) EINA_LOG_DOM_INFO(_eflat_xml_model_log_dom, __VA_ARGS__)
15#define DBG(...) EINA_LOG_DOM_DBG(_eflat_xml_model_log_dom, __VA_ARGS__)
16
17typedef struct _Eflat_Xml_Model_Data Eflat_Xml_Model_Data;
18
19/**
20 * eflat_xml_model
21 */
22struct _Eflat_Xml_Model_Data
23{
24 Eo *obj;
25 Efl_Model_Load load;
26 Eina_Array *properties_array;
27 Eina_Hash *properties_hash;
28 Eina_Simple_XML_Node_Root *root;
29 char *xml;
30 Eina_Value xml_value;
31};
32
33#endif
34
diff --git a/src/tests/eflat_xml_model/eflat_xml_model_suite.c b/src/tests/eflat_xml_model/eflat_xml_model_suite.c
new file mode 100644
index 0000000000..185a053c22
--- /dev/null
+++ b/src/tests/eflat_xml_model/eflat_xml_model_suite.c
@@ -0,0 +1,121 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eflat_xml_model_suite.h"
6
7#include <Eina.h>
8
9#include <stdbool.h>
10#include <stdio.h>
11#include <stdlib.h>
12
13int _test_eflat_xml_model_log_dom = -1;
14
15typedef struct _Eflat_Xml_Test_Case Eflat_Xml_Test_Case;
16
17struct _Eflat_Xml_Test_Case
18{
19 const char *test_case;
20 void (*build)(TCase *tc);
21};
22
23static const Eflat_Xml_Test_Case etc[] = {
24 { "Eflat_Xml_Model", eflat_xml_test_eflat_xml_model },
25 { NULL, NULL }
26};
27
28static void
29_list_tests(void)
30{
31 const Eflat_Xml_Test_Case *it = etc;
32 fputs("Available Test Cases:\n", stderr);
33 for (; it->test_case; it++)
34 fprintf(stderr, "\t%s\n", it->test_case);
35}
36
37static bool
38_use_test(int argc, const char **argv, const char *test_case)
39{
40 if (argc < 1)
41 return true;
42
43 for (; argc > 0; argc--, argv++)
44 if (strcmp(test_case, *argv) == 0)
45 return true;
46 return false;
47}
48
49static Suite *
50_eflat_xml_suite_build(int argc, const char **argv)
51{
52 Suite *s = suite_create("Eflat_Xml");
53
54 for (int i = 0; etc[i].test_case; ++i)
55 {
56 if (!_use_test(argc, argv, etc[i].test_case)) continue;
57 TCase *tc = tcase_create(etc[i].test_case);
58
59 etc[i].build(tc);
60
61 suite_add_tcase(s, tc);
62 //tcase_set_timeout(tc, 0);
63 }
64
65 return s;
66}
67
68static void
69_init_logging(void)
70{
71 _test_eflat_xml_model_log_dom = eina_log_domain_register("test_eflat_xml_model", EINA_COLOR_LIGHTBLUE);
72 if (_test_eflat_xml_model_log_dom < 0)
73 ck_abort_msg("Could not register log domain: test_eflat_xml_model");
74
75 //eina_log_domain_level_set("esskyuehl", EINA_LOG_LEVEL_DBG);
76 //eina_log_domain_level_set("eflat_xml_model", EINA_LOG_LEVEL_DBG);
77 eina_log_domain_level_set("test_eflat_xml_model", EINA_LOG_LEVEL_DBG);
78}
79
80static void
81_shutdown_logging(void)
82{
83 eina_log_domain_unregister(_test_eflat_xml_model_log_dom);
84 _test_eflat_xml_model_log_dom = -1;
85}
86
87int
88main(int argc, char **argv)
89{
90 for (int i = 1; i < argc; ++i)
91 {
92 if ((strcmp(argv[i], "-h") == 0) ||
93 (strcmp(argv[i], "--help") == 0))
94 {
95 fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n", argv[0]);
96 _list_tests();
97 return 0;
98 }
99 else if ((strcmp(argv[i], "-l") == 0) ||
100 (strcmp(argv[i], "--list") == 0))
101 {
102 _list_tests();
103 return 0;
104 }
105 }
106
107 _init_logging();
108
109 Suite *s = _eflat_xml_suite_build(argc - 1, (const char **)argv + 1);
110 SRunner *sr = srunner_create(s);
111
112 srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
113
114 srunner_run_all(sr, CK_ENV);
115 int failed_count = srunner_ntests_failed(sr);
116 srunner_free(sr);
117
118 _shutdown_logging();
119
120 return (failed_count == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
121}
diff --git a/src/tests/eflat_xml_model/eflat_xml_model_suite.h b/src/tests/eflat_xml_model/eflat_xml_model_suite.h
new file mode 100644
index 0000000000..d90a2c5a6d
--- /dev/null
+++ b/src/tests/eflat_xml_model/eflat_xml_model_suite.h
@@ -0,0 +1,16 @@
1#ifndef _EFLAT_XML_SUITE_H
2#define _EFLAT_XML_SUITE_H
3
4#include <check.h>
5
6extern int _test_eflat_xml_model_log_dom;
7
8#define CRI(...) EINA_LOG_DOM_CRIT(_test_eflat_xml_model_log_dom, __VA_ARGS__)
9#define ERR(...) EINA_LOG_DOM_ERR(_test_eflat_xml_model_log_dom, __VA_ARGS__)
10#define WRN(...) EINA_LOG_DOM_WARN(_test_eflat_xml_model_log_dom, __VA_ARGS__)
11#define INF(...) EINA_LOG_DOM_INFO(_test_eflat_xml_model_log_dom, __VA_ARGS__)
12#define DBG(...) EINA_LOG_DOM_DBG(_test_eflat_xml_model_log_dom, __VA_ARGS__)
13
14void eflat_xml_test_eflat_xml_model(TCase *tc);
15
16#endif
diff --git a/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.c b/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.c
new file mode 100644
index 0000000000..2e05f1a511
--- /dev/null
+++ b/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.c
@@ -0,0 +1,503 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eflat_xml_model_test_eflat_xml_model.h"
6#include "eflat_xml_model_suite.h"
7
8#include <Ecore.h>
9#include <Eina.h>
10#include <Eflat_Xml_Model.h>
11
12#include <stdbool.h>
13
14static void
15_setup(void)
16{
17 int ret = eflat_xml_model_init();
18 ck_assert_int_ge(ret, 1);
19}
20
21static void
22_teardown(void)
23{
24 int ret = eflat_xml_model_shutdown();
25 ck_assert_int_eq(ret, 0);
26}
27
28static Eina_Bool
29_eo_event_load_status_cb(void *data,
30 Eo *obj EINA_UNUSED,
31 const Eo_Event_Description *desc EINA_UNUSED,
32 void *event_info EINA_UNUSED)
33{
34 Efl_Model_Load_Status expected_status = *((Efl_Model_Load_Status*)data);
35 Efl_Model_Load load = *((Efl_Model_Load*)event_info);
36 if ((load.status & expected_status) != expected_status)
37 return EINA_TRUE;
38
39 ecore_main_loop_quit();
40 return EINA_FALSE;
41}
42
43static void
44_wait_until_load_status(Efl_Model_Base *emodel,
45 Efl_Model_Load_Status expected_status)
46{
47 Efl_Model_Load_Status actual_status;
48 eo_do(emodel, actual_status = efl_model_load_status_get());
49 if (expected_status == actual_status) return;
50
51 eo_do(emodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_LOAD_STATUS,
52 _eo_event_load_status_cb,
53 &expected_status));
54 ecore_main_loop_begin();
55 eo_do(emodel, eo_event_callback_del(EFL_MODEL_BASE_EVENT_LOAD_STATUS,
56 _eo_event_load_status_cb,
57 &expected_status));
58}
59
60static void
61_check_efl_model_property_str_eq(Efl_Model_Base *emodel,
62 const char *property,
63 const char *expected_value)
64{
65 const Eina_Value *value;
66 Efl_Model_Load_Status status;
67 eo_do(emodel, status = efl_model_property_get(property, &value));
68 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
69 ck_assert_ptr_ne(NULL, value);
70
71 const Eina_Value_Type *property_type = eina_value_type_get(value);
72 fail_if(EINA_VALUE_TYPE_STRING != property_type &&
73 EINA_VALUE_TYPE_STRINGSHARE != property_type);
74
75 const char *actual_value = NULL;
76 eina_value_get(value, &actual_value);
77 ck_assert_str_eq(expected_value, actual_value);
78}
79
80static void
81_check_efl_model_load(Efl_Model_Base *model)
82{
83 eo_do(model, efl_model_load());
84 _wait_until_load_status(model, EFL_MODEL_LOAD_STATUS_LOADED);
85}
86
87static void
88_check_efl_model_properties(Efl_Model_Base *model,
89 const char *expected_properties[])
90{
91 Eina_Array *properties = NULL;
92 Efl_Model_Load_Status status;
93 eo_do(model, status = efl_model_properties_get(&properties));
94 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
95 ck_assert_ptr_ne(NULL, properties);
96
97 unsigned int actual_properties_count = eina_array_count(properties);
98
99 unsigned int expected_properties_count = 0;
100 const char *expected_property = NULL;
101 while ((expected_property = *expected_properties++))
102 {
103 const char *actual_property = eina_array_data_get(properties,
104 expected_properties_count);
105 ck_assert_str_eq(expected_property, actual_property);
106 ++expected_properties_count;
107 ck_assert_int_le(expected_properties_count, actual_properties_count);
108 }
109
110 ck_assert_int_eq(expected_properties_count, actual_properties_count);
111}
112
113static Eflat_Xml_Model *
114_create_flat_xml_model(void)
115{
116 Efl_Model_Base *xml_model = eo_add(EFLAT_XML_MODEL_CLASS,
117 NULL,
118 eflat_xml_model_constructor(NULL));
119 ck_assert_ptr_ne(NULL, xml_model);
120 return xml_model;
121}
122
123START_TEST(smoke)
124{
125 Efl_Model_Base *xml_model = _create_flat_xml_model();
126 eo_unref(xml_model);
127}
128END_TEST
129
130static void
131_check_string_property_set(Efl_Model_Base *model,
132 const char *property,
133 const char *v)
134{
135 Eina_Value value;
136 eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
137 eina_value_set(&value, v);
138 Efl_Model_Load_Status status;
139 eo_do(model, status = efl_model_property_set(property, &value));
140 eina_value_flush(&value);
141 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
142}
143
144static void
145_check_xml_string(Efl_Model_Base *model, const char *expected_xml_string)
146{
147 _check_efl_model_property_str_eq(model, "/", expected_xml_string);
148}
149
150static const char *SAMPLE_XML =
151 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
152 "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n"
153 " <soap:Header>\n"
154 " <m:Trans xmlns:m=\"http://my.namespace/header\" soap:mustUnderstand=\"1\">\n"
155 " 1234\n"
156 " </m:Trans>\n"
157 " </soap:Header>\n"
158 " <soap:Body>\n"
159 " <m:MethodName xmlns:m=\"http://my.namespece/body\">\n"
160 " <m:Item>\n"
161 " Value\n"
162 " </m:Item>\n"
163 " </m:MethodName>\n"
164 " </soap:Body>\n"
165 "</soap:Envelope>\n";
166
167static void
168_check_sample_xml_properties_names(Efl_Model_Base *xml_model)
169{
170 _check_efl_model_properties(xml_model, (const char*[]){
171 "?xml",
172 "soap:Envelope@xmlns:soap",
173 "soap:Envelope@soap:encodingStyle",
174 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
175 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
176 "soap:Envelope/soap:Header/m:Trans",
177 "soap:Envelope/soap:Body/m:MethodName@xmlns:m",
178 "soap:Envelope/soap:Body/m:MethodName/m:Item",
179 NULL});
180}
181
182static void
183_check_sample_xml_properties_values(Efl_Model_Base *xml_model)
184{
185 _check_efl_model_property_str_eq(xml_model, "?xml", "version=\"1.0\" encoding=\"UTF-8\"");
186 _check_efl_model_property_str_eq(xml_model, "soap:Envelope@xmlns:soap", "http://www.w3.org/2001/12/soap-envelope");
187 _check_efl_model_property_str_eq(xml_model, "soap:Envelope@soap:encodingStyle", "http://www.w3.org/2001/12/soap-encoding");
188 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Header/m:Trans@xmlns:m", "http://my.namespace/header");
189 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand", "1");
190 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Header/m:Trans", "1234");
191 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Body/m:MethodName@xmlns:m", "http://my.namespece/body");
192 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Body/m:MethodName/m:Item", "Value");
193}
194
195static void
196_check_property_set(Efl_Model_Base *xml_model)
197{
198 _check_string_property_set(xml_model, "?xml", "version=\"1.0\" encoding=\"UTF-8\"");
199 _check_string_property_set(xml_model, "soap:Envelope@xmlns:soap", "http://www.w3.org/2001/12/soap-envelope");
200 _check_string_property_set(xml_model, "soap:Envelope@soap:encodingStyle", "http://www.w3.org/2001/12/soap-encoding");
201 _check_string_property_set(xml_model, "soap:Envelope/soap:Header/m:Trans@xmlns:m", "http://my.namespace/header");
202 _check_string_property_set(xml_model, "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand", "1");
203 _check_string_property_set(xml_model, "soap:Envelope/soap:Header/m:Trans", "1234");
204 _check_string_property_set(xml_model, "soap:Envelope/soap:Body/m:MethodName@xmlns:m", "http://my.namespece/body");
205 _check_string_property_set(xml_model, "soap:Envelope/soap:Body/m:MethodName/m:Item", "Value");
206
207 _check_xml_string(xml_model, SAMPLE_XML);
208
209 _check_sample_xml_properties_names(xml_model);
210
211 _check_efl_model_property_str_eq(xml_model, "?xml", "version=\"1.0\" encoding=\"UTF-8\"");
212}
213
214START_TEST(property_set_basic)
215{
216 Efl_Model_Base *xml_model = _create_flat_xml_model();
217
218 _check_efl_model_load(xml_model);
219
220 _check_property_set(xml_model);
221
222 eo_unref(xml_model);
223}
224END_TEST
225
226static void
227_check_property_not_exists(Efl_Model_Base *model, const char *property)
228{
229 const Eina_Value *value;
230 Efl_Model_Load_Status status;
231 eo_do(model, status = efl_model_property_get(property, &value));
232 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
233
234 Eina_Array *properties = NULL;
235 eo_do(model, status = efl_model_properties_get(&properties));
236 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
237 ck_assert_ptr_ne(NULL, properties);
238
239 unsigned int i;
240 char *item;
241 Eina_Array_Iterator it;
242 EINA_ARRAY_ITER_NEXT(properties, i, item, it)
243 ck_assert_str_ne(property, item);
244}
245
246START_TEST(property_set_existing)
247{
248 Efl_Model_Base *xml_model = _create_flat_xml_model();
249
250 _check_efl_model_load(xml_model);
251
252 _check_property_set(xml_model);
253
254 // replaces an attribute
255 _check_string_property_set(xml_model, "soap:Envelope/soap:Header/m:Trans@xmlns:m", "http://other.namespace/header");
256
257 _check_efl_model_properties(xml_model, (const char*[]){
258 "?xml",
259 "soap:Envelope@xmlns:soap",
260 "soap:Envelope@soap:encodingStyle",
261 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
262 "soap:Envelope/soap:Header/m:Trans",
263 "soap:Envelope/soap:Body/m:MethodName@xmlns:m",
264 "soap:Envelope/soap:Body/m:MethodName/m:Item",
265 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
266 NULL});
267
268 // replaces a value
269 _check_string_property_set(xml_model, "soap:Envelope/soap:Header/m:Trans", "4321");
270
271 _check_efl_model_properties(xml_model, (const char*[]){
272 "?xml",
273 "soap:Envelope@xmlns:soap",
274 "soap:Envelope@soap:encodingStyle",
275 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
276 "soap:Envelope/soap:Body/m:MethodName@xmlns:m",
277 "soap:Envelope/soap:Body/m:MethodName/m:Item",
278 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
279 "soap:Envelope/soap:Header/m:Trans",
280 NULL});
281
282 // clears a value
283 _check_string_property_set(xml_model, "soap:Envelope/soap:Body/m:MethodName/m:Item", "");
284
285 _check_xml_string(xml_model,
286 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
287 "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n"
288 " <soap:Header>\n"
289 " <m:Trans xmlns:m=\"http://other.namespace/header\" soap:mustUnderstand=\"1\">\n"
290 " 4321\n"
291 " </m:Trans>\n"
292 " </soap:Header>\n"
293 " <soap:Body>\n"
294 " <m:MethodName xmlns:m=\"http://my.namespece/body\">\n"
295 " <m:Item/>\n"
296 " </m:MethodName>\n"
297 " </soap:Body>\n"
298 "</soap:Envelope>\n"
299 );
300
301 _check_efl_model_properties(xml_model, (const char*[]){
302 "?xml",
303 "soap:Envelope@xmlns:soap",
304 "soap:Envelope@soap:encodingStyle",
305 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
306 "soap:Envelope/soap:Body/m:MethodName@xmlns:m",
307 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
308 "soap:Envelope/soap:Header/m:Trans",
309 "soap:Envelope/soap:Body/m:MethodName/m:Item",
310 NULL});
311
312 // clearing a value clears its children too
313 _check_string_property_set(xml_model, "soap:Envelope/soap:Body", "");
314
315 _check_property_not_exists(xml_model, "soap:Envelope/soap:Body/m:MethodName/m:Item");
316 _check_property_not_exists(xml_model, "soap:Envelope/soap:Body/m:MethodName@xmlns:m");
317
318 _check_xml_string(xml_model,
319 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
320 "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n"
321 " <soap:Header>\n"
322 " <m:Trans xmlns:m=\"http://other.namespace/header\" soap:mustUnderstand=\"1\">\n"
323 " 4321\n"
324 " </m:Trans>\n"
325 " </soap:Header>\n"
326 " <soap:Body/>\n"
327 "</soap:Envelope>\n"
328 );
329
330 _check_efl_model_properties(xml_model, (const char*[]){
331 "?xml",
332 "soap:Envelope@xmlns:soap",
333 "soap:Envelope@soap:encodingStyle",
334 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
335 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
336 "soap:Envelope/soap:Header/m:Trans",
337 "soap:Envelope/soap:Body",
338 NULL});
339
340 eo_unref(xml_model);
341}
342END_TEST
343
344START_TEST(property_set_stream)
345{
346 Efl_Model_Base *xml_model = _create_flat_xml_model();
347
348 _check_efl_model_load(xml_model);
349
350 // root level
351 _check_string_property_set(xml_model, "/", SAMPLE_XML);
352 _check_sample_xml_properties_names(xml_model);
353 _check_sample_xml_properties_values(xml_model);
354
355 _check_string_property_set(xml_model, "soap:Envelope/soap:Body/",
356 " <m:OtherMethod xmlns:m=\"http://my.namespece/body\">\n"
357 " <m:OtherItem>\n"
358 " OtherValue\n"
359 " </m:OtherItem>\n"
360 " </m:OtherMethod>\n"
361 );
362
363 _check_efl_model_properties(xml_model, (const char*[]){
364 "?xml",
365 "soap:Envelope@xmlns:soap",
366 "soap:Envelope@soap:encodingStyle",
367 "soap:Envelope/soap:Header/m:Trans@xmlns:m",
368 "soap:Envelope/soap:Header/m:Trans@soap:mustUnderstand",
369 "soap:Envelope/soap:Header/m:Trans",
370 "soap:Envelope/soap:Body/m:OtherMethod@xmlns:m",
371 "soap:Envelope/soap:Body/m:OtherMethod/m:OtherItem",
372 NULL});
373
374
375 _check_xml_string(xml_model,
376 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
377 "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n"
378 " <soap:Header>\n"
379 " <m:Trans xmlns:m=\"http://my.namespace/header\" soap:mustUnderstand=\"1\">\n"
380 " 1234\n"
381 " </m:Trans>\n"
382 " </soap:Header>\n"
383 " <soap:Body>\n"
384 " <m:OtherMethod xmlns:m=\"http://my.namespece/body\">\n"
385 " <m:OtherItem>\n"
386 " OtherValue\n"
387 " </m:OtherItem>\n"
388 " </m:OtherMethod>\n"
389 " </soap:Body>\n"
390 "</soap:Envelope>\n"
391 );
392
393 eo_unref(xml_model);
394}
395END_TEST
396
397START_TEST(property_get_stream)
398{
399 Efl_Model_Base *xml_model = _create_flat_xml_model();
400
401 _check_efl_model_load(xml_model);
402
403 _check_property_set(xml_model);
404
405 // sublevel
406 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/",
407 "<soap:Header>\n"
408 " <m:Trans xmlns:m=\"http://my.namespace/header\" soap:mustUnderstand=\"1\">\n"
409 " 1234\n"
410 " </m:Trans>\n"
411 "</soap:Header>\n"
412 "<soap:Body>\n"
413 " <m:MethodName xmlns:m=\"http://my.namespece/body\">\n"
414 " <m:Item>\n"
415 " Value\n"
416 " </m:Item>\n"
417 " </m:MethodName>\n"
418 "</soap:Body>\n"
419 );
420
421 // sublevel
422 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Header/",
423 "<m:Trans xmlns:m=\"http://my.namespace/header\" soap:mustUnderstand=\"1\">\n"
424 " 1234\n"
425 "</m:Trans>\n"
426 );
427
428 // sublevel data
429 _check_efl_model_property_str_eq(xml_model, "soap:Envelope/soap:Header/m:Trans/",
430 "1234\n"
431 );
432
433 eo_unref(xml_model);
434}
435END_TEST
436
437START_TEST(load_status_get)
438{
439 Efl_Model_Base *xml_model = _create_flat_xml_model();
440
441 Efl_Model_Load_Status status;
442 eo_do(xml_model, status = efl_model_load_status_get());
443 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
444
445 _check_efl_model_load(xml_model);
446
447 eo_do(xml_model, status = efl_model_load_status_get());
448 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
449
450 eo_unref(xml_model);
451}
452END_TEST
453
454START_TEST(unload)
455{
456 Efl_Model_Base *xml_model = _create_flat_xml_model();
457
458 _check_efl_model_load(xml_model);
459 _check_property_set(xml_model);
460
461 eo_do(xml_model, efl_model_unload());
462
463 // status must be unloaded now
464 Efl_Model_Load_Status status;
465 eo_do(xml_model, status = efl_model_load_status_get());
466 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
467
468 // reload and manipulate content
469 _check_efl_model_load(xml_model);
470 _check_property_set(xml_model);
471
472 eo_unref(xml_model);
473}
474END_TEST
475
476START_TEST(xml_load)
477{
478 Efl_Model_Base *xml_model = eo_add(EFLAT_XML_MODEL_CLASS,
479 NULL,
480 eflat_xml_model_constructor(SAMPLE_XML));
481 ck_assert_ptr_ne(NULL, xml_model);
482
483 _check_efl_model_load(xml_model);
484 _check_sample_xml_properties_names(xml_model);
485 _check_sample_xml_properties_values(xml_model);
486
487 eo_unref(xml_model);
488}
489END_TEST
490
491void
492eflat_xml_test_eflat_xml_model(TCase *tc)
493{
494 tcase_add_checked_fixture(tc, _setup, _teardown);
495 tcase_add_test(tc, smoke);
496 tcase_add_test(tc, property_set_basic);
497 tcase_add_test(tc, property_set_existing);
498 tcase_add_test(tc, property_set_stream);
499 tcase_add_test(tc, property_get_stream);
500 tcase_add_test(tc, load_status_get);
501 tcase_add_test(tc, unload);
502 tcase_add_test(tc, xml_load);
503}
diff --git a/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.h b/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.h
new file mode 100644
index 0000000000..b9c836363b
--- /dev/null
+++ b/src/tests/eflat_xml_model/eflat_xml_model_test_eflat_xml_model.h
@@ -0,0 +1,6 @@
1#ifndef _EFLAT_XML_MODEL_TEST_EFLAT_XML_MODEL_H
2#define _EFLAT_XML_MODEL_TEST_EFLAT_XML_MODEL_H
3
4#include <Eflat_Xml_Model.h>
5
6#endif