summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-07-30 15:51:02 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-08-31 16:45:45 -0300
commit6a1025c09e7c2f0489c64a3d09e48fd4197213fc (patch)
tree590343aa9b193327637d8ffa5a25c5947c986316
parentcb2cea98cdad2a76098139b1cf40b2b61dcbe4f0 (diff)
ejson: Json Efl.Model implementation
-rw-r--r--cmakeconfig/EjsonConfig.cmake.in32
-rw-r--r--cmakeconfig/EjsonCxxConfig.cmake.in30
-rw-r--r--configure.ac54
-rw-r--r--pc/ejson-cxx.pc.in12
-rw-r--r--pc/ejson.pc.in12
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile_Ejson.am86
-rw-r--r--src/Makefile_Ejson_Cxx.am22
-rw-r--r--src/lib/ejson/Ejson.h67
-rw-r--r--src/lib/ejson/ejson_main.c65
-rw-r--r--src/lib/ejson/ejson_model.c1117
-rw-r--r--src/lib/ejson/ejson_model.eo50
-rw-r--r--src/lib/ejson/ejson_model_private.h31
-rw-r--r--src/lib/ejson/ejson_private.h15
-rw-r--r--src/tests/ejson/Makefile.am11
-rw-r--r--src/tests/ejson/ejson_suite.c121
-rw-r--r--src/tests/ejson/ejson_suite.h16
-rw-r--r--src/tests/ejson/ejson_test_ejson_model.c782
-rw-r--r--src/tests/ejson/ejson_test_ejson_model.h6
19 files changed, 2530 insertions, 1 deletions
diff --git a/cmakeconfig/EjsonConfig.cmake.in b/cmakeconfig/EjsonConfig.cmake.in
new file mode 100644
index 0000000000..0d603b48d4
--- /dev/null
+++ b/cmakeconfig/EjsonConfig.cmake.in
@@ -0,0 +1,32 @@
1# - Try to find ejson
2# Once done this will define
3# EJSON_FOUND - System has ejson
4# EJSON_INCLUDE_DIRS - The ejson include directories
5# EJSON_LIBRARIES - The libraries needed to use ejson
6# EJSON_DEFINITIONS - Compiler switches required for using ejson
7
8set(MY_PKG ejson)
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_LIBEJSON ${_QUIET} ${MY_PKG})
16
17find_library(EJSON_LIBRARY
18 NAMES ${PC_LIBEJSON_LIBRARIES}
19 HINTS ${PC_LIBEJSON_LIBDIR} ${PC_LIBEJSON_LIBRARY_DIRS} )
20
21set(EJSON_DEFINITIONS ${PC_LIBEJSON_CFLAGS_OTHER})
22set(EJSON_LIBRARIES ${EJSON_LIBRARY})
23set(EJSON_INCLUDE_DIRS ${PC_LIBEJSON_INCLUDE_DIRS})
24
25include(FindPackageHandleStandardArgs)
26# handle the QUIETLY and REQUIRED arguments and set EJSON_FOUND to TRUE
27# if all listed variables are TRUE
28find_package_handle_standard_args(${MY_PKG} DEFAULT_MSG
29 EJSON_LIBRARIES EJSON_INCLUDE_DIRS)
30
31mark_as_advanced(EJSON_INCLUDE_DIRS EJSON_LIBRARY EJSON_LIBRARIES EJSON_DEFINITIONS)
32
diff --git a/cmakeconfig/EjsonCxxConfig.cmake.in b/cmakeconfig/EjsonCxxConfig.cmake.in
new file mode 100644
index 0000000000..e3fcf1ac28
--- /dev/null
+++ b/cmakeconfig/EjsonCxxConfig.cmake.in
@@ -0,0 +1,30 @@
1# - Try to find ejson
2# Once done this will define
3# EJSON_CXX_FOUND - System has ejson
4# EJSON_CXX_INCLUDE_DIRS - The ejson include directories
5# EJSON_CXX_LIBRARIES - The libraries needed to use ejson
6# EJSON_CXX_DEFINITIONS - Compiler switches required for using ejson
7
8set(MY_PKG ejson_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_EJSON_CXX ${_QUIET} ${MY_PKG})
16find_library(EJSON_CXX_LIBRARY
17 NAMES ${PC_EJSON_CXX_LIBRARIES}
18 HINTS ${PC_EJSON_CXX_LIBDIR} ${PC_EJSON_CXX_LIBRARY_DIRS} )
19
20set(EJSON_CXX_DEFINITIONS ${PC_EJSON_CXX_CFLAGS_OTHER})
21set(EJSON_CXX_LIBRARIES ${EJSON_CXX_LIBRARY})
22set(EJSON_CXX_INCLUDE_DIRS ${PC_EJSON_CXX_INCLUDE_DIRS})
23
24include(FindPackageHandleStandardArgs)
25# handle the QUIETLY and REQUIRED arguments and set EJSON_CXX_FOUND to TRUE
26# if all listed variables are TRUE
27find_package_handle_standard_args(${MY_PKG} DEFAULT_MSG
28 EJSON_CXX_LIBRARIES EJSON_CXX_INCLUDE_DIRS)
29
30mark_as_advanced(EJSON_CXX_INCLUDE_DIRS EJSON_CXX_LIBRARY EJSON_CXX_LIBRARIES EJSON_CXX_DEFINITIONS)
diff --git a/configure.ac b/configure.ac
index 01c7850290..442d7f399c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3911,7 +3911,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [emile])
3911ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}]) 3911ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}])
3912ECORE_EVAS_MODULE([ews], [yes]) 3912ECORE_EVAS_MODULE([ews], [yes])
3913ECORE_EVAS_MODULE([fb], [${want_fb}]) 3913ECORE_EVAS_MODULE([fb], [${want_fb}])
3914ECORE_EVAS_MODULE([drm], [${want_drm}], 3914ECORE_EVAS_MODULE([drm], [${want_drm}],
3915 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])]) 3915 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])])
3916ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}], 3916ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}],
3917 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])]) 3917 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])])
@@ -4560,6 +4560,51 @@ EFL_ADD_LIBS([ELOCATION], [-lm])
4560EFL_LIB_END([Elocation]) 4560EFL_LIB_END([Elocation])
4561#### End of Elocation 4561#### End of Elocation
4562 4562
4563
4564
4565
4566#### Ejson
4567EFL_LIB_START([Ejson])
4568
4569### Additional options to configure
4570
4571### Default values
4572
4573### Checks for programs
4574
4575### Checks for libraries
4576EFL_INTERNAL_DEPEND_PKG([EJSON], [eo])
4577EFL_INTERNAL_DEPEND_PKG([EJSON], [efl])
4578EFL_INTERNAL_DEPEND_PKG([EJSON], [ecore])
4579
4580EFL_DEPEND_PKG([EJSON], [JSONC], [json-c >= 0.11])
4581
4582EFL_EVAL_PKGS([EJSON])
4583
4584### Checks for header files
4585
4586### Checks for types
4587
4588### Checks for structures
4589
4590### Checks for compiler characteristics
4591
4592### Checks for linker characteristics
4593
4594### Checks for library functions
4595
4596EFL_LIB_END([Ejson])
4597#### End of Ejson
4598
4599#### Ejson CXX
4600EFL_LIB_START([Ejson_Cxx])
4601
4602EFL_EVAL_PKGS([EJSON_CXX])
4603
4604EFL_LIB_END([Ejson_Cxx])
4605#### End of Ejson CXX
4606
4607
4563### Add Wayland server library if test is enabled 4608### Add Wayland server library if test is enabled
4564if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then 4609if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then
4565 EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.8.0]) 4610 EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.8.0])
@@ -4748,6 +4793,8 @@ pc/ethumb.pc
4748pc/ethumb_client.pc 4793pc/ethumb_client.pc
4749pc/elocation.pc 4794pc/elocation.pc
4750pc/elua.pc 4795pc/elua.pc
4796pc/ejson.pc
4797pc/ejson-cxx.pc
4751dbus-services/org.enlightenment.Ethumb.service 4798dbus-services/org.enlightenment.Ethumb.service
4752systemd-services/ethumb.service 4799systemd-services/ethumb.service
4753$po_makefile_in 4800$po_makefile_in
@@ -4797,6 +4844,10 @@ cmakeconfig/EluaConfig.cmake
4797cmakeconfig/EluaConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in 4844cmakeconfig/EluaConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4798cmakeconfig/EmileConfig.cmake 4845cmakeconfig/EmileConfig.cmake
4799cmakeconfig/EmileConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in 4846cmakeconfig/EmileConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4847cmakeconfig/EjsonConfig.cmake
4848cmakeconfig/EjsonConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4849cmakeconfig/EjsonCxxConfig.cmake
4850cmakeconfig/EjsonCxxConfigVersion.cmake:cmakeconfig/EFLConfigVersion.cmake.in
4800]) 4851])
4801 4852
4802AC_OUTPUT 4853AC_OUTPUT
@@ -4910,6 +4961,7 @@ echo "Emotion.........: yes (${features_emotion})"
4910echo "Ethumb..........: yes" 4961echo "Ethumb..........: yes"
4911echo "Ethumb_Client...: yes" 4962echo "Ethumb_Client...: yes"
4912echo "Elua............: $have_elua" 4963echo "Elua............: $have_elua"
4964echo "Ejson...........: yes"
4913if test "${build_tests}" = "none"; then 4965if test "${build_tests}" = "none"; then
4914echo "Tests...........: no" 4966echo "Tests...........: no"
4915elif test "${build_tests}" = "auto"; then 4967elif test "${build_tests}" = "auto"; then
diff --git a/pc/ejson-cxx.pc.in b/pc/ejson-cxx.pc.in
new file mode 100644
index 0000000000..81ae839011
--- /dev/null
+++ b/pc/ejson-cxx.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: Ejson C++
7Description: Json convenience library for EFL
8Requires.private: @requirements_pc_ejson@ @requirements_pc_eo@
9Version: @VERSION@
10Libs: -L${libdir} -lejson @requirements_public_libs_ejson@ @requirements_public_libs_eo@
11Libs.private: @requirements_libs_ejson@ @requirements_libs_eo@
12Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eo-@VMAJ@ -I${includedir}/ejson-@VMAJ@ -I${includedir}/ejson-cxx-@VMAJ@
diff --git a/pc/ejson.pc.in b/pc/ejson.pc.in
new file mode 100644
index 0000000000..15d8f81bda
--- /dev/null
+++ b/pc/ejson.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: Ejson
7Description: Json convenience library for EFL
8Requires.private: @requirements_pc_ejson@
9Version: @VERSION@
10Libs: -L${libdir} -lejson @requirements_public_libs_ejson@
11Libs.private: @requirements_libs_ejson@
12Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/ejson-@VMAJ@
diff --git a/src/Makefile.am b/src/Makefile.am
index dccc538af2..0054ef7553 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,6 +60,7 @@ include Makefile_Edje.am
60include Makefile_Emotion.am 60include 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
63 64
64include Makefile_Eina_Cxx.am 65include Makefile_Eina_Cxx.am
65include Makefile_Ecore_Cxx.am 66include Makefile_Ecore_Cxx.am
@@ -71,6 +72,7 @@ include Makefile_Efl_Cxx.am
71include Makefile_Edje_Cxx.am 72include Makefile_Edje_Cxx.am
72include Makefile_Evas_Cxx.am 73include Makefile_Evas_Cxx.am
73include Makefile_Eio_Cxx.am 74include Makefile_Eio_Cxx.am
75include Makefile_Ejson_Cxx.am
74 76
75include Makefile_Elua.am 77include Makefile_Elua.am
76include Makefile_Elocation.am 78include Makefile_Elocation.am
diff --git a/src/Makefile_Ejson.am b/src/Makefile_Ejson.am
new file mode 100644
index 0000000000..6caa9d5469
--- /dev/null
+++ b/src/Makefile_Ejson.am
@@ -0,0 +1,86 @@
1### Library
2
3ejson_eolian_files = \
4lib/ejson/ejson_model.eo
5
6ejson_eolian_c = $(ejson_eolian_files:%.eo=%.eo.c)
7ejson_eolian_h = $(ejson_eolian_files:%.eo=%.eo.h)
8
9BUILT_SOURCES += \
10 $(ejson_eolian_c) \
11 $(ejson_eolian_h)
12
13CLEANFILES += \
14 $(ejson_eolian_c) \
15 $(ejson_eolian_h)
16
17ejsoneolianfilesdir = $(datadir)/eolian/include/ejson-@VMAJ@
18ejsoneolianfiles_DATA = \
19 $(ejson_eolian_files)
20
21EXTRA_DIST += \
22 ${ejsoneolianfiles_DATA}
23
24lib_LTLIBRARIES += lib/ejson/libejson.la
25
26installed_ejsonmainheadersdir = $(includedir)/ejson-@VMAJ@
27dist_installed_ejsonmainheaders_DATA = \
28lib/ejson/Ejson.h
29
30nodist_installed_ejsonmainheaders_DATA = \
31 $(ejson_eolian_h)
32
33lib_ejson_libejson_la_SOURCES = \
34lib/ejson/ejson_main.c \
35lib/ejson/ejson_private.h \
36lib/ejson/ejson_model.c \
37lib/ejson/ejson_model_private.h
38
39lib_ejson_libejson_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EJSON_CFLAGS@ @EFL_CFLAGS@
40lib_ejson_libejson_la_LIBADD = @EJSON_LIBS@ @EFL_LIBS@
41lib_ejson_libejson_la_DEPENDENCIES = @EJSON_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
42lib_ejson_libejson_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
43
44### Unit tests
45
46if EFL_ENABLE_TESTS
47
48check_PROGRAMS += tests/ejson/ejson_suite
49TESTS += tests/ejson/ejson_suite
50
51tests_ejson_ejson_suite_SOURCES = \
52tests/ejson/ejson_suite.c \
53tests/ejson/ejson_suite.h \
54tests/ejson/ejson_test_ejson_model.c \
55tests/ejson/ejson_test_ejson_model.h
56
57tests_ejson_ejson_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
58-DTESTS_SRC_DIR=\"$(abs_top_srcdir)/src/tests/ejson\" \
59-DTESTS_BUILD_DIR=\"$(abs_top_builddir)/src/tests/ejson\" \
60@CHECK_CFLAGS@ \
61@EJSON_CFLAGS@ @EFL_CFLAGS@
62
63tests_ejson_ejson_suite_LDADD = \
64@CHECK_LIBS@ \
65@USE_EJSON_LIBS@ \
66@USE_EFL_LIBS@
67
68tests_ejson_ejson_suite_DEPENDENCIES = \
69@USE_EJSON_INTERNAL_LIBS@
70
71endif
72
73EXTRA_DIST += $(EJSON_DATA_FILES)
74
75if HAVE_ELUA
76
77ejson_eolian_lua = $(ejson_eolian_files:%.eo=%.eo.lua)
78
79generated_ejson_lua_all = $(ejson_eolian_lua)
80
81CLEANFILES += $(generated_ejson_lua_all)
82
83installed_ejsonluadir = $(datadir)/elua/modules/ejson
84nodist_installed_ejsonlua_DATA = $(generated_ejson_lua_all)
85
86endif
diff --git a/src/Makefile_Ejson_Cxx.am b/src/Makefile_Ejson_Cxx.am
new file mode 100644
index 0000000000..5503676edf
--- /dev/null
+++ b/src/Makefile_Ejson_Cxx.am
@@ -0,0 +1,22 @@
1if HAVE_CXX11
2
3### Generated headers
4
5generated_ejson_cxx_bindings = $(ejson_eolian_files:%.eo=%.eo.hh)
6
7lib/ejson/Ejson.hh: $(generated_ejson_cxx_bindings)
8 @echo @ECHO_E@ "#ifndef EFL_CXX_EJSON_HH\n#define EFL_CXX_EJSON_HH\n" > $(top_builddir)/src/lib/ejson/Ejson.hh
9 @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/ejson/Ejson.hh
10 @for i in $(generated_ejson_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/ejson/Ejson.hh; done
11 @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/ejson/Ejson.hh
12
13generated_ejson_cxx_all = \
14 $(generated_ejson_cxx_bindings) \
15 lib/ejson/Ejson.hh
16
17CLEANFILES += $(generated_ejson_cxx_all)
18
19installed_ejsoncxxmainheadersdir = $(includedir)/ejson-cxx-@VMAJ@/
20nodist_installed_ejsoncxxmainheaders_DATA = $(generated_ejson_cxx_all)
21
22endif
diff --git a/src/lib/ejson/Ejson.h b/src/lib/ejson/Ejson.h
new file mode 100644
index 0000000000..6e5657c668
--- /dev/null
+++ b/src/lib/ejson/Ejson.h
@@ -0,0 +1,67 @@
1#ifndef EJSON_H
2#define EJSON_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_EJSON_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_EJSON_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#define EJSON_MODEL_NAME_PROPERTY "name"
39#define EJSON_MODEL_VALUE_PROPERTY "value"
40#define EJSON_MODEL_JSON_PROPERTY "json"
41
42/**
43 * @brief Initialize ejson.
44 *
45 * @return 1 or greater on success, 0 otherwise
46 */
47EAPI int ejson_init(void);
48
49/**
50 * @brief Shutdown ejson.
51 *
52 * @return 0 if ejson shuts down, greater than 0 otherwise.
53 */
54EAPI int ejson_shutdown(void);
55
56#ifdef EFL_EO_API_SUPPORT
57# include <ejson_model.eo.h>
58#endif
59
60#ifdef __cplusplus
61}
62#endif
63
64#undef EAPI
65#define EAPI
66
67#endif
diff --git a/src/lib/ejson/ejson_main.c b/src/lib/ejson/ejson_main.c
new file mode 100644
index 0000000000..7ce2374c7c
--- /dev/null
+++ b/src/lib/ejson/ejson_main.c
@@ -0,0 +1,65 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "ejson_private.h"
6
7static int _ejson_init_count = 0;
8int _ejson_log_dom = -1;
9
10EAPI int
11ejson_init(void)
12{
13 if (_ejson_init_count++ > 0)
14 return _ejson_init_count;
15
16 if (!eina_init())
17 {
18 fputs("Ejson: Unable to initialize eina\n", stderr);
19 return 0;
20 }
21
22 _ejson_log_dom = eina_log_domain_register("ejson_model", EINA_COLOR_CYAN);
23 if (_ejson_log_dom < 0)
24 {
25 EINA_LOG_ERR("Unable to create an 'ejson_model' log domain");
26 _ejson_log_dom = -1;
27 eina_shutdown();
28 return 0;
29 }
30
31 if (!ecore_init())
32 {
33 ERR("Unable to initialize ecore");
34 eina_log_domain_unregister(_ejson_log_dom);
35 _ejson_log_dom = -1;
36 eina_shutdown();
37 return 0;
38 }
39
40 // ...
41
42 return _ejson_init_count;
43}
44
45EAPI int
46ejson_shutdown(void)
47{
48 if (_ejson_init_count <= 0)
49 {
50 ERR("Init count not greater than 0 in shutdown.");
51 _ejson_init_count = 0;
52 return 0;
53 }
54
55 if (--_ejson_init_count)
56 return _ejson_init_count;
57
58 // ...
59
60 ecore_shutdown();
61 eina_log_domain_unregister(_ejson_log_dom);
62 _ejson_log_dom = -1;
63 eina_shutdown();
64 return 0;
65}
diff --git a/src/lib/ejson/ejson_model.c b/src/lib/ejson/ejson_model.c
new file mode 100644
index 0000000000..6c1d1e8db2
--- /dev/null
+++ b/src/lib/ejson/ejson_model.c
@@ -0,0 +1,1117 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "ejson_model_private.h"
6
7#include <stdint.h>
8#include <stdlib.h>
9
10#define MY_CLASS EJSON_MODEL_CLASS
11#define MY_CLASS_NAME "Ejson_Model"
12
13typedef struct _Ejson_Model_Child_Data
14{
15 Eina_Stringshare *name;
16 int index;
17} Ejson_Model_Child_Data;
18
19static void _properties_load(Ejson_Model_Data *);
20static void _children_load(Ejson_Model_Data *);
21static bool _init(Ejson_Model_Data *);
22static void _clear(Ejson_Model_Data *);
23static void _properties_setup(Ejson_Model_Data *);
24static Ejson_Model_Type _parent_type_get(Ejson_Model_Data *);
25static void _children_hash_free(Ejson_Model_Child_Data *);
26static void _properties_hash_free(Eina_Value *);
27static bool _name_property_set(Ejson_Model_Data *, const Eina_Value *);
28static bool _value_property_set(Ejson_Model_Data *, const Eina_Value *);
29static bool _json_property_set(Ejson_Model_Data *, const Eina_Value *);
30static void _invalidate(Ejson_Model_Data *);
31static bool _stream_load(Ejson_Model_Data *);
32static Eina_Bool _eina_value_as(const Eina_Value *, const Eina_Value_Type *, void *);
33static Ejson_Model_Type _type_from_json_object(json_object *json);
34static bool _object_child_add(Ejson_Model_Data *, Ejson_Model_Data *, const char *);
35static bool _array_child_add(Ejson_Model_Data *, Ejson_Model_Data *, int);
36static bool _child_add(Ejson_Model_Data *, Ejson_Model_Data *, Ejson_Model_Child_Data *);
37static Ejson_Model_Child_Data *_object_child_data_new(const char *);
38static Ejson_Model_Child_Data *_array_child_data_new(int*);
39typedef Ejson_Model_Child_Data *(*Ejson_Model_Child_Data_New)(void *);
40static void _child_new(Ejson_Model_Data *, json_object *, void *, Ejson_Model_Child_Data_New);
41
42static Eo_Base *
43_ejson_model_eo_base_constructor(Eo *obj, Ejson_Model_Data *pd)
44{
45 DBG("(%p)", obj);
46
47 pd->obj = obj;
48 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
49 pd->json = NULL;
50 pd->properties_array = NULL;
51 pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_properties_hash_free));
52 pd->children_list = NULL;
53 pd->children_hash = eina_hash_pointer_new(EINA_FREE_CB(_children_hash_free));
54 pd->stream = NULL;
55 pd->type = EJSON_MODEL_TYPE_NULL;
56 pd->properties_calc = eina_array_new(1);
57 eina_array_push(pd->properties_calc, EJSON_MODEL_JSON_PROPERTY);
58 pd->json_property_valid = false;
59
60 return eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
61}
62
63static void
64_ejson_model_constructor(Eo *obj EINA_UNUSED,
65 Ejson_Model_Data *pd,
66 Ejson_Model_Type type)
67{
68 DBG("(%p)", obj);
69 pd->type = type;
70}
71
72static void
73_ejson_model_eo_base_destructor(Eo *obj, Ejson_Model_Data *pd)
74{
75 DBG("(%p)", obj);
76
77 _clear(pd);
78
79 eina_hash_free(pd->children_hash);
80 eina_hash_free(pd->properties_hash);
81 eina_array_free(pd->properties_calc);
82
83 eo_do_super(obj, MY_CLASS, eo_destructor());
84}
85
86static Efl_Model_Load_Status
87_ejson_model_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
88 Ejson_Model_Data *pd,
89 Eina_Array * const* properties_array)
90{
91 DBG("(%p)", obj);
92 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
93 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
94
95 *(Eina_Array**)properties_array = pd->properties_array;
96 return pd->load.status;
97}
98
99static void
100_ejson_model_efl_model_base_properties_load(Eo *obj, Ejson_Model_Data *pd)
101{
102 DBG("(%p)", obj);
103
104 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
105 return;
106
107 if (!_init(pd))
108 return;
109
110 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
111
112 _properties_load(pd);
113
114 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
115}
116
117static void
118_properties_load(Ejson_Model_Data *pd)
119{
120 _properties_setup(pd);
121 if (!pd->json)
122 return;
123
124 Eina_Array *changed_properties = eina_array_new(1);
125 Eina_Value *value = NULL;
126 switch (pd->type)
127 {
128 case EJSON_MODEL_TYPE_NULL:
129 break;
130 case EJSON_MODEL_TYPE_BOOLEAN:
131 {
132 value = eina_hash_find(pd->properties_hash, EJSON_MODEL_VALUE_PROPERTY);
133 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
134 json_bool v = json_object_get_boolean(pd->json);
135 Eina_Bool ret = eina_value_set(value, v);
136 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
137 break;
138 }
139 case EJSON_MODEL_TYPE_DOUBLE:
140 {
141 value = eina_hash_find(pd->properties_hash, EJSON_MODEL_VALUE_PROPERTY);
142 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
143 double v = json_object_get_boolean(pd->json);
144 Eina_Bool ret = eina_value_set(value, v);
145 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
146 break;
147 }
148 case EJSON_MODEL_TYPE_INT:
149 {
150 value = eina_hash_find(pd->properties_hash, EJSON_MODEL_VALUE_PROPERTY);
151 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
152 int64_t v = json_object_get_int64(pd->json);
153 Eina_Bool ret = eina_value_set(value, v);
154 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
155 break;
156 }
157 case EJSON_MODEL_TYPE_STRING:
158 {
159 value = eina_hash_find(pd->properties_hash, EJSON_MODEL_VALUE_PROPERTY);
160 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
161 const char *v = json_object_get_string(pd->json);
162 Eina_Bool ret = eina_value_set(value, v);
163 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
164 break;
165 }
166 case EJSON_MODEL_TYPE_OBJECT:
167 break;
168 case EJSON_MODEL_TYPE_ARRAY:
169 break;
170 }
171
172 if (value)
173 eina_array_push(changed_properties, EJSON_MODEL_VALUE_PROPERTY);
174
175 if (EJSON_MODEL_TYPE_OBJECT == _parent_type_get(pd))
176 {
177 Eo *parent = eo_do_ret(pd->obj, parent, eo_parent_get());
178
179 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
180 EINA_SAFETY_ON_NULL_GOTO(parent_pd, on_error);
181
182 Ejson_Model_Child_Data *child_data = eina_hash_find(parent_pd->children_hash,
183 &pd->obj);
184 EINA_SAFETY_ON_NULL_GOTO(child_data, on_error);
185
186 value = eina_hash_find(pd->properties_hash, EJSON_MODEL_NAME_PROPERTY);
187 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
188
189 Eina_Bool ret = eina_value_set(value, child_data->name);
190 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
191
192 ret = eina_array_push(changed_properties, EJSON_MODEL_NAME_PROPERTY);
193 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
194 }
195
196 Efl_Model_Property_Event evt = {
197 .changed_properties = changed_properties,
198 .invalidated_properties = pd->properties_calc
199 };
200 eo_do(pd->obj,
201 eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
202
203on_error:
204 eina_array_free(changed_properties);
205}
206
207static Efl_Model_Load_Status
208_ejson_model_efl_model_base_property_set(Eo *obj,
209 Ejson_Model_Data *pd,
210 const char *property,
211 const Eina_Value *value)
212{
213 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
214 DBG("(%p): property=%s", obj, property);
215
216 Eina_Array *changed_properties = eina_array_new(1);
217 const bool is_json_property = strcmp(EJSON_MODEL_JSON_PROPERTY, property) == 0;
218 if (is_json_property)
219 {
220 if (!_json_property_set(pd, value))
221 goto on_error;
222
223 // only notify properties_changed if loaded
224 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED)
225 eina_array_push(changed_properties, EJSON_MODEL_JSON_PROPERTY);
226 }
227 else
228 {
229 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
230 goto on_error;
231
232 const bool is_name_property = strcmp(EJSON_MODEL_NAME_PROPERTY, property) == 0;
233 const bool is_value_property = strcmp(EJSON_MODEL_VALUE_PROPERTY, property) == 0;
234
235 if (!is_name_property && !is_value_property)
236 {
237 ERR("Unrecognized property: %s", property);
238 goto on_error;
239 }
240
241 if (is_name_property)
242 {
243 if (!_name_property_set(pd, value))
244 goto on_error;
245 eina_array_push(changed_properties, EJSON_MODEL_NAME_PROPERTY);
246 }
247 else if (is_value_property)
248 {
249 if (!_value_property_set(pd, value))
250 goto on_error;
251 eina_array_push(changed_properties, EJSON_MODEL_VALUE_PROPERTY);
252 }
253 }
254
255 if (eina_array_count(changed_properties))
256 {
257 pd->json_property_valid = false;
258 Efl_Model_Property_Event evt = {
259 .changed_properties = changed_properties,
260 .invalidated_properties = pd->properties_calc
261 };
262 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
263 }
264
265 eina_array_free(changed_properties);
266 return pd->load.status;
267
268on_error:
269 eina_array_free(changed_properties);
270 return EFL_MODEL_LOAD_STATUS_ERROR;
271}
272
273static bool
274_name_property_set(Ejson_Model_Data *pd, const Eina_Value *value)
275{
276 DBG("(%p)", pd->obj);
277 Ejson_Model_Type parent_type = _parent_type_get(pd);
278 if (EJSON_MODEL_TYPE_OBJECT != parent_type)
279 {
280 ERR("Only object types have the '" EJSON_MODEL_NAME_PROPERTY "' property");
281 return false;
282 }
283
284 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, EJSON_MODEL_NAME_PROPERTY);
285 EINA_SAFETY_ON_NULL_RETURN_VAL(prop_value, false);
286
287 eina_value_flush(prop_value);
288 Eina_Bool ret = eina_value_copy(value, prop_value);
289 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
290
291 return true;
292}
293
294static bool
295_value_property_set(Ejson_Model_Data *pd, const Eina_Value *value)
296{
297 DBG("(%p)", pd->obj);
298 const Eina_Value_Type * const value_type = eina_value_type_get(value);
299 EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
300
301 json_object *json = NULL;
302 switch (pd->type)
303 {
304 case EJSON_MODEL_TYPE_BOOLEAN:
305 {
306 int v;
307 Eina_Bool ret = _eina_value_as(value, EINA_VALUE_TYPE_INT, &v);
308 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
309
310 json = json_object_new_boolean(v ? TRUE : FALSE);
311 break;
312 }
313 case EJSON_MODEL_TYPE_DOUBLE:
314 {
315 double v;
316 Eina_Bool ret = _eina_value_as(value, EINA_VALUE_TYPE_DOUBLE, &v);
317 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
318
319 json = json_object_new_double(v);
320 break;
321 }
322 case EJSON_MODEL_TYPE_INT:
323 {
324 int64_t v;
325 Eina_Bool ret = _eina_value_as(value, EINA_VALUE_TYPE_INT64, &v);
326 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
327
328 json = json_object_new_int64(v);
329 break;
330 }
331 case EJSON_MODEL_TYPE_STRING:
332 {
333 const char *v;
334 Eina_Bool ret = _eina_value_as(value, EINA_VALUE_TYPE_STRING, &v);
335 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
336
337 json = json_object_new_string(v);
338 break;
339 }
340 case EJSON_MODEL_TYPE_NULL:
341 return false;
342 case EJSON_MODEL_TYPE_OBJECT:
343 return false;
344 case EJSON_MODEL_TYPE_ARRAY:
345 return false;
346 }
347
348 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, EJSON_MODEL_VALUE_PROPERTY);
349 EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error);
350
351 eina_value_flush(prop_value);
352 Eina_Bool ret = eina_value_copy(value, prop_value);
353 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
354
355 json_object_put(pd->json);
356 pd->json = json;
357
358 return true;
359
360on_error:
361 json_object_put(json);
362 return false;
363}
364
365static bool
366_json_property_set(Ejson_Model_Data *pd, const Eina_Value *value)
367{
368 DBG("(%p)", pd->obj);
369 char *stream = eina_value_to_string(value);
370 EINA_SAFETY_ON_NULL_RETURN_VAL(stream, false);
371
372 Efl_Model_Load_Status old_status = pd->load.status;
373 switch (old_status & EFL_MODEL_LOAD_STATUS_LOADED)
374 {
375 case EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES:
376 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
377 break;
378 case EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN:
379 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
380 break;
381 case EFL_MODEL_LOAD_STATUS_LOADED:
382 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING);
383 break;
384 default: break;
385 }
386
387 _clear(pd);
388
389 pd->stream = stream;
390
391 _stream_load(pd);
392
393 if (old_status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
394 _properties_load(pd);
395
396 if (old_status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
397 _children_load(pd);
398
399 efl_model_load_set(pd->obj, &pd->load, old_status);
400 return true;
401}
402
403static Efl_Model_Load_Status
404_ejson_model_efl_model_base_property_get(Eo *obj EINA_UNUSED,
405 Ejson_Model_Data *pd,
406 const char *property,
407 const Eina_Value **value)
408{
409 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
410 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
411 DBG("(%p): property=%s", obj, property);
412
413 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
414 return EFL_MODEL_LOAD_STATUS_ERROR;
415
416 *value = eina_hash_find(pd->properties_hash, property);
417 if (!(*value))
418 return EFL_MODEL_LOAD_STATUS_ERROR;
419
420 if ((strcmp(EJSON_MODEL_JSON_PROPERTY, property) == 0) && !pd->json_property_valid)
421 {
422 const char *json = json_object_to_json_string(pd->json);
423 Eina_Bool ret = eina_value_set((Eina_Value*)*value, json);
424 pd->json_property_valid = EINA_TRUE == ret;
425
426 if (!pd->json_property_valid)
427 return EFL_MODEL_LOAD_STATUS_ERROR;
428 }
429
430 return pd->load.status;
431}
432
433static void
434_ejson_model_efl_model_base_load(Eo *obj, Ejson_Model_Data *pd)
435{
436 DBG("(%p)", obj);
437
438 if ((pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED) == EFL_MODEL_LOAD_STATUS_LOADED)
439 return;
440
441 if (!_init(pd))
442 return;
443
444 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
445 {
446 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
447 _properties_load(pd);
448 }
449
450 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
451 {
452 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
453 _children_load(pd);
454 }
455
456 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED);
457}
458
459static Efl_Model_Load_Status
460_ejson_model_efl_model_base_load_status_get(Eo *obj EINA_UNUSED,
461 Ejson_Model_Data *pd)
462{
463 DBG("(%p)", obj);
464 return pd->load.status;
465}
466
467static void
468_ejson_model_efl_model_base_unload(Eo *obj, Ejson_Model_Data *pd)
469{
470 DBG("(%p)", obj);
471
472 _clear(pd);
473
474 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
475}
476
477static Eina_Bool
478_ejson_model_child_properties_changed_cb(void *data,
479 Eo *child,
480 const Eo_Event_Description *desc EINA_UNUSED,
481 void *event_info)
482{
483 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EO_CALLBACK_STOP);
484 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info, EO_CALLBACK_STOP);
485 Ejson_Model_Data *pd = (Ejson_Model_Data*)data;
486 DBG("(%p)", pd->obj);
487
488 // Only user changes count
489 Efl_Model_Load_Status child_status;
490 eo_do(child, child_status = efl_model_load_status_get());
491 if (!(child_status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
492 return EO_CALLBACK_CONTINUE;
493
494 Ejson_Model_Data *child_pd = eo_data_scope_get(child, EJSON_MODEL_CLASS);
495 EINA_SAFETY_ON_NULL_RETURN_VAL(child_pd, EO_CALLBACK_STOP);
496
497 const char *current_name = NULL;
498 if (EJSON_MODEL_TYPE_OBJECT == pd->type)
499 {
500 Eina_Value *value = eina_hash_find(child_pd->properties_hash,
501 EJSON_MODEL_NAME_PROPERTY);
502 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EO_CALLBACK_STOP);
503
504 Eina_Bool ret = eina_value_get(value, &current_name);
505 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EO_CALLBACK_STOP);
506
507 // Continue only if the name is already assigned
508 if (!current_name || !strlen(current_name))
509 return EO_CALLBACK_CONTINUE;
510 }
511
512 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->children_hash, EO_CALLBACK_STOP);
513 Ejson_Model_Child_Data *child_data = eina_hash_find(pd->children_hash, &child);
514 if (child_data)
515 {
516 DBG("(%p) Setting child %p value", pd->obj, child_pd->obj);
517 switch (pd->type)
518 {
519 case EJSON_MODEL_TYPE_OBJECT:
520 {
521 const bool is_name_changed = strcmp(current_name, child_data->name) == 0;
522 if (!is_name_changed)
523 {
524 json_object_object_del(pd->json, child_data->name);
525 eina_stringshare_del(child_data->name);
526 child_data->name = eina_stringshare_add(current_name);
527 }
528
529 json_object_object_add(pd->json,
530 child_data->name,
531 json_object_get(child_pd->json));
532 break;
533 }
534 case EJSON_MODEL_TYPE_ARRAY:
535 json_object_array_put_idx(pd->json,
536 child_data->index,
537 json_object_get(child_pd->json));
538 break;
539 default:
540 ERR("Type cannot have children: %d", pd->type);
541 return EO_CALLBACK_STOP;
542 }
543 }
544 else
545 {
546
547 bool ok = false;
548 switch (pd->type)
549 {
550 case EJSON_MODEL_TYPE_OBJECT:
551 json_object_object_add(pd->json,
552 current_name,
553 json_object_get(child_pd->json));
554 ok = _object_child_add(pd, child_pd, current_name);
555 break;
556 case EJSON_MODEL_TYPE_ARRAY:
557 {
558 int index = json_object_array_add(pd->json,
559 json_object_get(child_pd->json));
560 ok = _array_child_add(pd, child_pd, index);
561 break;
562 }
563 default:
564 ERR("Current type cannot have children: %d", pd->type);
565 }
566
567 EINA_SAFETY_ON_FALSE_RETURN_VAL(ok, EO_CALLBACK_STOP);
568
569 unsigned int count = eina_list_count(pd->children_list);
570 Efl_Model_Children_Event evt = {.child = child, .index = count};
571 eo_do(pd->obj,
572 eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILD_ADDED, &evt),
573 eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
574 }
575
576 _invalidate(pd);
577
578 Efl_Model_Property_Event evt = {
579 .invalidated_properties = pd->properties_calc
580 };
581 eo_do(pd->obj,
582 eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
583
584 return EO_CALLBACK_CONTINUE;
585}
586
587Eo *
588_ejson_model_efl_model_base_child_add(Eo *obj, Ejson_Model_Data *pd)
589{
590 DBG("(%p)", obj);
591
592 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
593 return NULL;
594
595 json_type type = json_object_get_type(pd->json);
596 switch (type)
597 {
598 case json_type_array:
599 case json_type_object:
600 break;
601 default:
602 ERR("Value types cannot have children: %d", type);
603 return NULL;
604 }
605
606 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->json, NULL);
607
608 Eo *child = eo_add(EJSON_MODEL_CLASS,
609 obj,
610 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
611 eo_do(child, eo_event_callback_add(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED,
612 _ejson_model_child_properties_changed_cb,
613 pd));
614 return child;
615}
616
617static Efl_Model_Load_Status
618_ejson_model_efl_model_base_child_del(Eo *obj,
619 Ejson_Model_Data *pd,
620 Eo *child)
621{
622 DBG("(%p)", obj);
623 EINA_SAFETY_ON_NULL_RETURN_VAL(child, EFL_MODEL_LOAD_STATUS_ERROR);
624
625 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
626 return EFL_MODEL_LOAD_STATUS_ERROR;
627
628 Ejson_Model_Child_Data *child_data = eina_hash_find(pd->children_hash, &child);
629 if (!child_data)
630 {
631 ERR("Child not found: %p", child);
632 return EFL_MODEL_LOAD_STATUS_ERROR;
633 }
634
635 switch (pd->type)
636 {
637 case EJSON_MODEL_TYPE_OBJECT:
638 {
639 json_object_object_del(pd->json, child_data->name);
640 break;
641 }
642 case EJSON_MODEL_TYPE_ARRAY:
643 {
644 int index = child_data->index;
645 json_object *json = json_object_new_array();
646
647 int length = json_object_array_length(pd->json);
648
649 for (int i = 0; i < index; ++i)
650 {
651 json_object *item = json_object_array_get_idx(pd->json, i);
652 json_object_array_add(json, json_object_get(item));
653 }
654
655 for (int i = index + 1; i < length; ++i)
656 {
657 json_object *item = json_object_array_get_idx(pd->json, i);
658 json_object_array_add(json, json_object_get(item));
659 }
660
661 Ejson_Model_Child_Data *data;
662 Eina_Iterator *it = eina_hash_iterator_data_new(pd->children_hash);
663 EINA_ITERATOR_FOREACH(it, data)
664 {
665 if (data->index > index)
666 --data->index;
667 }
668 eina_iterator_free(it);
669
670 json_object_put(pd->json);
671 pd->json = json;
672 break;
673 }
674 default: return EFL_MODEL_LOAD_STATUS_ERROR;
675 }
676
677 pd->children_list = eina_list_remove(pd->children_list, child);
678 Eina_Bool ret = eina_hash_del(pd->children_hash, &child, NULL);
679 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
680 eo_del(child);
681
682 pd->json_property_valid = false;
683 unsigned int count = eina_list_count(pd->children_list);
684 Efl_Model_Property_Event prop_event = {
685 .changed_properties = pd->properties_array,
686 .invalidated_properties = pd->properties_calc
687 };
688 Efl_Model_Children_Event added_event = {.child = child, .index = count};
689 eo_do(obj,
690 eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &prop_event),
691 eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILD_ADDED, &added_event),
692 eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
693
694 return pd->load.status;
695}
696
697static Efl_Model_Load_Status
698_ejson_model_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
699 Ejson_Model_Data *pd,
700 unsigned start,
701 unsigned count,
702 Eina_Accessor **children_accessor)
703{
704 DBG("(%p)", obj);
705
706 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
707 {
708 WRN("(%p): Children not loaded", obj);
709 *children_accessor = NULL;
710 return pd->load.status;
711 }
712
713 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
714 return pd->load.status;
715}
716
717static Efl_Model_Load_Status
718_ejson_model_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
719 Ejson_Model_Data *pd,
720 unsigned *children_count)
721{
722 DBG("(%p)", obj);
723 *children_count = eina_list_count(pd->children_list);
724 return pd->load.status;
725}
726
727static void
728_ejson_model_efl_model_base_children_load(Eo *obj, Ejson_Model_Data *pd)
729{
730 DBG("(%p)", obj);
731
732 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
733 return;
734
735 if (!_init(pd))
736 return;
737
738 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
739
740 _children_load(pd);
741
742 efl_model_load_set(obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
743}
744
745static void
746_children_load(Ejson_Model_Data *pd)
747{
748 DBG("(%p)", pd->obj);
749 if (!pd->json)
750 return;
751
752 switch (pd->type)
753 {
754 case EJSON_MODEL_TYPE_OBJECT:
755 {
756 Ejson_Model_Child_Data_New cb = (Ejson_Model_Child_Data_New)_object_child_data_new;
757 json_object_object_foreach(pd->json, name, json)
758 _child_new(pd, json, name, cb);
759 break;
760 }
761 case EJSON_MODEL_TYPE_ARRAY:
762 {
763 Ejson_Model_Child_Data_New cb = (Ejson_Model_Child_Data_New)_array_child_data_new;
764 int length = json_object_array_length(pd->json);
765 for (int i = 0; i < length; ++i)
766 {
767 json_object *json = json_object_array_get_idx(pd->json, i);
768 _child_new(pd, json, &i, cb);
769 }
770 break;
771 }
772 default:
773 ERR("Current type cannot have children: %d", pd->type);
774 }
775
776 unsigned int count = eina_list_count(pd->children_list);
777 if (count)
778 eo_do(pd->obj,
779 eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
780}
781
782static void
783_child_new(Ejson_Model_Data *pd,
784 json_object *json,
785 void *data,
786 Ejson_Model_Child_Data_New child_data_new)
787{
788 Ejson_Model_Type type = _type_from_json_object(json);
789
790 Eo *child = eo_add(EJSON_MODEL_CLASS,
791 pd->obj,
792 ejson_model_constructor(type));
793
794 Ejson_Model_Data *child_pd = eo_data_scope_get(child, EJSON_MODEL_CLASS);
795 EINA_SAFETY_ON_NULL_RETURN(child_pd);
796
797 child_pd->json = json_object_get(json);
798
799 Ejson_Model_Child_Data *child_data = child_data_new(data);
800 _child_add(pd, child_pd, child_data);
801
802 eo_do(child, eo_event_callback_add(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED,
803 _ejson_model_child_properties_changed_cb,
804 pd));
805}
806
807static Ejson_Model_Type
808_ejson_model_type_get(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
809{
810 DBG("(%p)", obj);
811 return pd->type;
812}
813
814static void
815_ejson_model_type_set(Eo *obj EINA_UNUSED,
816 Ejson_Model_Data *pd,
817 const Ejson_Model_Type value)
818{
819 DBG("(%p)", obj);
820 EINA_SAFETY_ON_FALSE_RETURN(value >= 0 && value <= EJSON_MODEL_TYPE_ARRAY);
821 pd->type = value;
822}
823
824static bool
825_init(Ejson_Model_Data *pd)
826{
827 if (pd->json)
828 return true;
829
830 if (pd->stream)
831 {
832 if (!_stream_load(pd))
833 return false;
834 }
835 else
836 {
837 switch (pd->type)
838 {
839 case EJSON_MODEL_TYPE_OBJECT:
840 pd->json = json_object_new_object();
841 break;
842 case EJSON_MODEL_TYPE_ARRAY:
843 pd->json = json_object_new_array();
844 break;
845 default: break;
846 }
847 }
848
849 return true;
850}
851
852static void
853_clear(Ejson_Model_Data *pd)
854{
855 EINA_SAFETY_ON_NULL_RETURN(pd);
856
857 eina_hash_free_buckets(pd->children_hash);
858
859 Eo *child;
860 EINA_LIST_FREE(pd->children_list, child)
861 eo_del(child);
862
863 eina_hash_free_buckets(pd->properties_hash);
864
865 if (pd->properties_array)
866 {
867 eina_array_free(pd->properties_array);
868 pd->properties_array = NULL;
869 }
870
871 json_object_put(pd->json);
872 pd->json = NULL;
873 pd->json_property_valid = false;
874
875 free(pd->stream);
876 pd->stream = NULL;
877}
878
879typedef struct
880{
881 Ejson_Model_Data *pd;
882 const char *member_name[3];
883 const Eina_Value_Type *member_type[3];
884} Ejson_Model_Properties_Setup;
885
886static void
887_properties_setup(Ejson_Model_Data *pd)
888{
889 DBG("(%p) Setup type: %d", pd->obj, pd->type);
890
891 Ejson_Model_Properties_Setup setup = {.pd = pd};
892
893 setup.member_name[0] = EJSON_MODEL_JSON_PROPERTY;
894 setup.member_type[0] = EINA_VALUE_TYPE_STRING;
895 unsigned int member_count = 1;
896
897 switch (pd->type)
898 {
899 case EJSON_MODEL_TYPE_BOOLEAN:
900 setup.member_type[member_count] = EINA_VALUE_TYPE_INT;
901 break;
902 case EJSON_MODEL_TYPE_INT:
903 setup.member_type[member_count] = EINA_VALUE_TYPE_INT64;
904 break;
905 case EJSON_MODEL_TYPE_DOUBLE:
906 setup.member_type[member_count] = EINA_VALUE_TYPE_DOUBLE;
907 break;
908 case EJSON_MODEL_TYPE_STRING:
909 setup.member_type[member_count] = EINA_VALUE_TYPE_STRING;
910 break;
911 case EJSON_MODEL_TYPE_NULL:
912 case EJSON_MODEL_TYPE_OBJECT:
913 case EJSON_MODEL_TYPE_ARRAY:
914 break;
915 }
916
917 switch (pd->type)
918 {
919 case EJSON_MODEL_TYPE_BOOLEAN:
920 case EJSON_MODEL_TYPE_INT:
921 case EJSON_MODEL_TYPE_DOUBLE:
922 case EJSON_MODEL_TYPE_STRING:
923 setup.member_name[member_count] = EJSON_MODEL_VALUE_PROPERTY;
924 ++member_count;
925 break;
926 case EJSON_MODEL_TYPE_NULL:
927 case EJSON_MODEL_TYPE_OBJECT:
928 case EJSON_MODEL_TYPE_ARRAY:
929 break;
930 }
931
932 Ejson_Model_Type parent_type = _parent_type_get(pd);
933
934 if (EJSON_MODEL_TYPE_OBJECT == parent_type)
935 {
936 setup.member_name[member_count] = EJSON_MODEL_NAME_PROPERTY;
937 setup.member_type[member_count] = EINA_VALUE_TYPE_STRING;
938 ++member_count;
939 }
940
941 pd->properties_array = eina_array_new(member_count);
942 for (size_t i = 0; i < member_count; ++i)
943 {
944 Eina_Bool ret = eina_array_push(pd->properties_array,
945 setup.member_name[i]);
946 EINA_SAFETY_ON_FALSE_RETURN(ret);
947
948 const Eina_Value_Type *type = setup.member_type[i];
949 Eina_Value *value = eina_value_new(type);
950 EINA_SAFETY_ON_NULL_RETURN(value);
951
952 ret = eina_hash_add(pd->properties_hash, setup.member_name[i], value);
953 EINA_SAFETY_ON_FALSE_RETURN(ret);
954 }
955
956 DBG("(%p) Properties setup done", pd->obj);
957}
958
959static Ejson_Model_Type
960_parent_type_get(Ejson_Model_Data *pd)
961{
962 Eo *parent = eo_do_ret(pd->obj, parent, eo_parent_get());
963 if (!parent)
964 return EJSON_MODEL_TYPE_NULL;
965
966 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
967 EINA_SAFETY_ON_NULL_RETURN_VAL(parent_pd, EJSON_MODEL_TYPE_NULL);
968
969 return parent_pd->type;
970}
971
972static void
973_children_hash_free(Ejson_Model_Child_Data *child)
974{
975 eina_stringshare_del(child->name);
976 free(child);
977}
978
979static void
980_properties_hash_free(Eina_Value *value)
981{
982 eina_value_free(value);
983}
984
985static void
986_invalidate(Ejson_Model_Data *pd)
987{
988 Eo *parent = pd->obj;
989 while ((parent = eo_do_ret(parent, parent, eo_parent_get())))
990 {
991 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
992 parent_pd->json_property_valid = false;
993
994 Efl_Model_Property_Event evt = {
995 .invalidated_properties = parent_pd->properties_calc
996 };
997 eo_do(parent,
998 eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
999 }
1000
1001 pd->json_property_valid = false;
1002}
1003
1004static bool
1005_stream_load(Ejson_Model_Data *pd)
1006{
1007 enum json_tokener_error error;
1008 pd->json = json_tokener_parse_verbose(pd->stream, &error);
1009 if (json_tokener_success != error)
1010 {
1011 ERR("Invalid json stream. Error: %d, stream = %s", error, pd->stream);
1012 return false;
1013 }
1014
1015 pd->type = _type_from_json_object(pd->json);
1016 return true;
1017}
1018
1019static Ejson_Model_Type
1020_type_from_json_object(json_object *json)
1021{
1022 json_type type = json_object_get_type(json);
1023 switch (type)
1024 {
1025 case json_type_null: return EJSON_MODEL_TYPE_NULL;
1026 case json_type_boolean: return EJSON_MODEL_TYPE_BOOLEAN;
1027 case json_type_double: return EJSON_MODEL_TYPE_DOUBLE;
1028 case json_type_int: return EJSON_MODEL_TYPE_INT;
1029 case json_type_object: return EJSON_MODEL_TYPE_OBJECT;
1030 case json_type_array: return EJSON_MODEL_TYPE_ARRAY;
1031 case json_type_string: return EJSON_MODEL_TYPE_STRING;
1032 default:
1033 ERR("Unrecognized type: %d", type);
1034 return EJSON_MODEL_TYPE_NULL;
1035 }
1036}
1037
1038static Eina_Bool
1039_eina_value_as(const Eina_Value *value, const Eina_Value_Type *type, void *mem)
1040{
1041 const Eina_Value_Type * const value_type = eina_value_type_get(value);
1042 EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
1043
1044 if (value_type == type)
1045 return eina_value_get(value, mem);
1046
1047 Eina_Value convert;
1048 Eina_Bool ret = eina_value_setup(&convert, type)
1049 && eina_value_convert(value, &convert)
1050 && eina_value_get(&convert, mem);
1051 eina_value_flush(&convert);
1052
1053 return ret;
1054}
1055
1056static Ejson_Model_Child_Data *
1057_object_child_data_new(const char *name)
1058{
1059 Ejson_Model_Child_Data *child_data = calloc(1, sizeof(Ejson_Model_Child_Data));
1060 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, NULL);
1061 child_data->name = eina_stringshare_add(name);
1062
1063 return child_data;
1064}
1065
1066static Ejson_Model_Child_Data *
1067_array_child_data_new(int *index)
1068{
1069 Ejson_Model_Child_Data *child_data = calloc(1, sizeof(Ejson_Model_Child_Data));
1070 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, NULL);
1071 child_data->index = *index;
1072
1073 return child_data;
1074}
1075
1076static bool
1077_object_child_add(Ejson_Model_Data *pd,
1078 Ejson_Model_Data *child_pd,
1079 const char *name)
1080{
1081 Ejson_Model_Child_Data *child_data = _object_child_data_new(name);
1082 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1083
1084 return _child_add(pd, child_pd, child_data);
1085}
1086
1087static bool
1088_array_child_add(Ejson_Model_Data *pd, Ejson_Model_Data *child_pd, int index)
1089{
1090 Ejson_Model_Child_Data *child_data = _array_child_data_new(&index);
1091 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1092
1093 return _child_add(pd, child_pd, child_data);
1094}
1095
1096static bool
1097_child_add(Ejson_Model_Data *pd,
1098 Ejson_Model_Data *child_pd,
1099 Ejson_Model_Child_Data *child_data)
1100{
1101 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, false);
1102 EINA_SAFETY_ON_NULL_RETURN_VAL(child_pd, false);
1103 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1104
1105 DBG("(%p) Adding new child %p of type: %d", pd->obj, child_pd->obj, child_pd->type);
1106 pd->children_list = eina_list_append(pd->children_list, child_pd->obj);
1107
1108 Eina_Bool ret = eina_hash_add(pd->children_hash, &child_pd->obj, child_data);
1109 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
1110 return true;
1111
1112on_error:
1113 free(child_data);
1114 return false;
1115}
1116
1117#include "ejson_model.eo.c"
diff --git a/src/lib/ejson/ejson_model.eo b/src/lib/ejson/ejson_model.eo
new file mode 100644
index 0000000000..ab4703cdb7
--- /dev/null
+++ b/src/lib/ejson/ejson_model.eo
@@ -0,0 +1,50 @@
1enum Ejson.Model.Type {
2 NULL,
3 BOOLEAN,
4 DOUBLE,
5 INT,
6 STRING,
7 OBJECT,
8 ARRAY
9}
10
11class Ejson.Model (Eo.Base, Efl.Model.Base) {
12 legacy_prefix: null;
13 methods {
14 constructor {
15 [[
16 Custom Ejson_Model constructor.
17 @.constructor
18
19 @since 1.13
20 ]]
21 params {
22 type: Ejson.Model.Type; [[Json object type]]
23 }
24 }
25 @property type {
26 values {
27 value: Ejson.Model.Type;
28 }
29 }
30 }
31 implements {
32 Eo.Base.constructor;
33 Eo.Base.destructor;
34 Efl.Model.Base.properties.get;
35 Efl.Model.Base.properties_load;
36 Efl.Model.Base.property.set;
37 Efl.Model.Base.property.get;
38 Efl.Model.Base.load;
39 Efl.Model.Base.load_status.get;
40 Efl.Model.Base.unload;
41 Efl.Model.Base.child_add;
42 Efl.Model.Base.child_del;
43 Efl.Model.Base.children_slice.get;
44 Efl.Model.Base.children_count.get;
45 Efl.Model.Base.children_load;
46 }
47 constructors {
48 .constructor;
49 }
50}
diff --git a/src/lib/ejson/ejson_model_private.h b/src/lib/ejson/ejson_model_private.h
new file mode 100644
index 0000000000..beaacb21f2
--- /dev/null
+++ b/src/lib/ejson/ejson_model_private.h
@@ -0,0 +1,31 @@
1#ifndef _EJSON_MODEL_PRIVATE_H
2#define _EJSON_MODEL_PRIVATE_H
3
4#include "ejson_private.h"
5
6#include <json.h>
7
8#include <stdbool.h>
9
10typedef struct _Ejson_Model_Data Ejson_Model_Data;
11
12/**
13 * ejson_model
14 */
15struct _Ejson_Model_Data
16{
17 Eo *obj;
18 Efl_Model_Load load;
19 json_object *json;
20 Eina_Array *properties_array;
21 Eina_Hash *properties_hash;
22 Eina_List *children_list;
23 Eina_Hash *children_hash;
24 Ejson_Model_Type type;
25 Eina_Array *properties_calc;
26 bool json_property_valid;
27 char *stream;
28};
29
30#endif
31
diff --git a/src/lib/ejson/ejson_private.h b/src/lib/ejson/ejson_private.h
new file mode 100644
index 0000000000..502c850d22
--- /dev/null
+++ b/src/lib/ejson/ejson_private.h
@@ -0,0 +1,15 @@
1#ifndef _EJSON_PRIVATE_H
2#define _EJSON_PRIVATE_H
3
4#include <Ejson.h>
5
6/* logging support */
7extern int _ejson_log_dom;
8
9#define CRI(...) EINA_LOG_DOM_CRIT(_ejson_log_dom, __VA_ARGS__)
10#define ERR(...) EINA_LOG_DOM_ERR(_ejson_log_dom, __VA_ARGS__)
11#define WRN(...) EINA_LOG_DOM_WARN(_ejson_log_dom, __VA_ARGS__)
12#define INF(...) EINA_LOG_DOM_INFO(_ejson_log_dom, __VA_ARGS__)
13#define DBG(...) EINA_LOG_DOM_DBG(_ejson_log_dom, __VA_ARGS__)
14
15#endif
diff --git a/src/tests/ejson/Makefile.am b/src/tests/ejson/Makefile.am
new file mode 100644
index 0000000000..01b722e8e2
--- /dev/null
+++ b/src/tests/ejson/Makefile.am
@@ -0,0 +1,11 @@
1check_PROGRAMS = \
2 src/tests/ejson_suite
3TESTS = src/tests/ejson_suite
4
5src_tests_ejson_suite_SOURCES = \
6 src/tests/ejson_suite.c \
7 src/tests/ejson_test_ejson_model.c
8src_tests_ejson_suite_CFLAGS = $(MOD_CFLAGS) \
9 -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests\"
10src_tests_ejson_suite_LDADD = $(MOD_LIBS) $(CHECK_LIBS)
11
diff --git a/src/tests/ejson/ejson_suite.c b/src/tests/ejson/ejson_suite.c
new file mode 100644
index 0000000000..cd50da5bc8
--- /dev/null
+++ b/src/tests/ejson/ejson_suite.c
@@ -0,0 +1,121 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "ejson_suite.h"
6
7#include <Eina.h>
8
9#include <stdbool.h>
10#include <stdio.h>
11#include <stdlib.h>
12
13int _test_ejson_model_log_dom = -1;
14
15typedef struct _Ejson_Test_Case Ejson_Test_Case;
16
17struct _Ejson_Test_Case
18{
19 const char *test_case;
20 void (*build)(TCase *tc);
21};
22
23static const Ejson_Test_Case etc[] = {
24 { "Ejson_Model", ejson_test_ejson_model },
25 { NULL, NULL }
26};
27
28static void
29_list_tests(void)
30{
31 const Ejson_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_ejson_suite_build(int argc, const char **argv)
51{
52 Suite *s = suite_create("Ejson");
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_ejson_model_log_dom = eina_log_domain_register("test_ejson_model", EINA_COLOR_LIGHTBLUE);
72 if (_test_ejson_model_log_dom < 0)
73 ck_abort_msg("Could not register log domain: test_ejson_model");
74
75 //eina_log_domain_level_set("esskyuehl", EINA_LOG_LEVEL_DBG);
76 //eina_log_domain_level_set("ejson_model", EINA_LOG_LEVEL_DBG);
77 eina_log_domain_level_set("test_ejson_model", EINA_LOG_LEVEL_DBG);
78}
79
80static void
81_shutdown_logging(void)
82{
83 eina_log_domain_unregister(_test_ejson_model_log_dom);
84 _test_ejson_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 = _ejson_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/ejson/ejson_suite.h b/src/tests/ejson/ejson_suite.h
new file mode 100644
index 0000000000..ac1dbcdf47
--- /dev/null
+++ b/src/tests/ejson/ejson_suite.h
@@ -0,0 +1,16 @@
1#ifndef _EJSON_SUITE_H
2#define _EJSON_SUITE_H
3
4#include <check.h>
5
6extern int _test_ejson_model_log_dom;
7
8#define CRI(...) EINA_LOG_DOM_CRIT(_test_ejson_model_log_dom, __VA_ARGS__)
9#define ERR(...) EINA_LOG_DOM_ERR(_test_ejson_model_log_dom, __VA_ARGS__)
10#define WRN(...) EINA_LOG_DOM_WARN(_test_ejson_model_log_dom, __VA_ARGS__)
11#define INF(...) EINA_LOG_DOM_INFO(_test_ejson_model_log_dom, __VA_ARGS__)
12#define DBG(...) EINA_LOG_DOM_DBG(_test_ejson_model_log_dom, __VA_ARGS__)
13
14void ejson_test_ejson_model(TCase *tc);
15
16#endif
diff --git a/src/tests/ejson/ejson_test_ejson_model.c b/src/tests/ejson/ejson_test_ejson_model.c
new file mode 100644
index 0000000000..51d3780efc
--- /dev/null
+++ b/src/tests/ejson/ejson_test_ejson_model.c
@@ -0,0 +1,782 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "ejson_test_ejson_model.h"
6#include "ejson_suite.h"
7
8#include <Ecore.h>
9#include <Eina.h>
10#include <Ejson.h>
11
12#include <stdbool.h>
13
14static void
15_setup(void)
16{
17 int ret = ejson_init();
18 ck_assert_int_ge(ret, 1);
19}
20
21static void
22_teardown(void)
23{
24 int ret = ejson_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, _eo_event_load_status_cb, &expected_status));
52 ecore_main_loop_begin();
53 eo_do(emodel, eo_event_callback_del(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _eo_event_load_status_cb, &expected_status));
54}
55
56static void
57_check_json_string(Efl_Model_Base *model, const char *expected_json_string)
58{
59 const Eina_Value *json_value;
60 Efl_Model_Load_Status status;
61 eo_do(model, status = efl_model_property_get(EJSON_MODEL_JSON_PROPERTY, &json_value));
62 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES, status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
63 ck_assert_ptr_ne(NULL, json_value);
64
65 const char *actual_json_string;
66 fail_unless(eina_value_get(json_value, &actual_json_string));
67
68 ck_assert_str_eq(expected_json_string, actual_json_string);
69}
70
71static void
72_check_value_type_cannot_have_children(Efl_Model_Base *model)
73{
74 Efl_Model_Base *child = eo_do_ret(model, child, efl_model_child_add());
75 ck_assert_ptr_eq(NULL, child);
76}
77
78static Efl_Model_Load_Status
79_json_property_set(Efl_Model_Base *model, const char *v)
80{
81 Eina_Value json;
82 eina_value_setup(&json, EINA_VALUE_TYPE_STRING);
83 eina_value_set(&json, v);
84 Efl_Model_Load_Status status;
85 eo_do(model, status = efl_model_property_set(EJSON_MODEL_JSON_PROPERTY, &json));
86 eina_value_flush(&json);
87 return status;
88}
89
90static void
91_check_name_property_set(Efl_Model_Base *model, const char *v)
92{
93 Eina_Value name;
94 eina_value_setup(&name, EINA_VALUE_TYPE_STRING);
95 eina_value_set(&name, v);
96 Efl_Model_Load_Status status;
97 eo_do(model, status = efl_model_property_set(EJSON_MODEL_NAME_PROPERTY, &name));
98 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
99 eina_value_flush(&name);
100}
101
102static void
103_check_int_value_property_set(Efl_Model_Base *model, int64_t v)
104{
105 Eina_Value value;
106 eina_value_setup(&value, EINA_VALUE_TYPE_INT64);
107 eina_value_set(&value, v);
108
109 Efl_Model_Load_Status status;
110 eo_do(model, status = efl_model_property_set(EJSON_MODEL_VALUE_PROPERTY, &value));
111 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
112
113 char buf[64];
114 snprintf(buf, sizeof(buf), "%lld", (long long)v);
115
116 _check_json_string(model, buf);
117
118 eina_value_flush(&value);
119}
120
121static void
122_check_bool_value_property_set(Efl_Model_Base *model, bool v)
123{
124 Eina_Value value;
125 eina_value_setup(&value, EINA_VALUE_TYPE_INT);
126 eina_value_set(&value, (int)v);
127
128 Efl_Model_Load_Status status;
129 eo_do(model, status = efl_model_property_set(EJSON_MODEL_VALUE_PROPERTY, &value));
130 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
131
132 _check_json_string(model, v ? "true" : "false");
133
134 eina_value_flush(&value);
135}
136
137static void
138_check_string_value_property_set(Efl_Model_Base *model, const char *v)
139{
140 Eina_Value value;
141 eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
142 eina_value_set(&value, v);
143
144 Efl_Model_Load_Status status;
145 eo_do(model, status = efl_model_property_set(EJSON_MODEL_VALUE_PROPERTY, &value));
146 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
147
148 size_t len = 1 + strlen(v) + 1 + 1;
149 char buf[len];
150 snprintf(buf, len, "\"%s\"", v);
151
152 _check_json_string(model, buf);
153
154 eina_value_flush(&value);
155}
156
157static void
158_check_emodel_children_count_eq(Efl_Model_Base *model,
159 unsigned int expected_children_count)
160{
161 unsigned int actual_children_count = 0;
162 eo_do(model, efl_model_children_count_get(&actual_children_count));
163 ck_assert_int_eq(expected_children_count, actual_children_count);
164}
165
166static void
167_check_emodel_property_int_eq(Efl_Model_Base *emodel,
168 const char *property,
169 int64_t expected_value)
170{
171 const Eina_Value *value;
172 Efl_Model_Load_Status status;
173 eo_do(emodel, status = efl_model_property_get(property, &value));
174 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
175 ck_assert_ptr_ne(NULL, value);
176
177 const Eina_Value_Type *property_type = eina_value_type_get(value);
178 ck_assert_ptr_eq(EINA_VALUE_TYPE_INT64, property_type);
179
180 int64_t actual_value = 0;
181 eina_value_get(value, &actual_value);
182 ck_assert_int_eq(expected_value, actual_value);
183}
184
185static void
186_check_emodel_property_str_eq(Efl_Model_Base *emodel,
187 const char *property,
188 const char *expected_value)
189{
190 const Eina_Value *value;
191 Efl_Model_Load_Status status;
192 eo_do(emodel, status = efl_model_property_get(property, &value));
193 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
194 ck_assert_ptr_ne(NULL, value);
195
196 const Eina_Value_Type *property_type = eina_value_type_get(value);
197 fail_if(EINA_VALUE_TYPE_STRING != property_type && EINA_VALUE_TYPE_STRINGSHARE != property_type);
198
199 const char *actual_value = NULL;
200 eina_value_get(value, &actual_value);
201 ck_assert_str_eq(expected_value, actual_value);
202}
203
204static Efl_Model_Base *
205_emodel_nth_child_get(Efl_Model_Base *emodel, unsigned int n)
206{
207 Eina_Accessor *accessor;
208 Efl_Model_Load_Status status;
209 eo_do(emodel, status = efl_model_children_slice_get(n, 1, &accessor));
210 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
211 ck_assert_ptr_ne(NULL, accessor);
212 Efl_Model_Base *child = NULL;
213 Eina_Bool ret = eina_accessor_data_get(accessor, 0, (void**)&child);
214 eina_accessor_free(accessor);
215 ck_assert(ret);
216 ck_assert_ptr_ne(NULL, child);
217 return child;
218}
219
220static void
221_check_ejson_type(Efl_Model_Base *model, Ejson_Model_Type expected_type)
222{
223 Ejson_Model_Type actual_type;
224 eo_do(model, actual_type = ejson_model_type_get());
225 ck_assert_int_eq(expected_type, actual_type);
226}
227
228static void
229_check_emodel_load(Efl_Model_Base *model)
230{
231 eo_do(model, efl_model_load());
232 _wait_until_load_status(model, EFL_MODEL_LOAD_STATUS_LOADED);
233}
234
235static void
236_check_emodel_properties(Efl_Model_Base *model,
237 const char *expected_properties[])
238{
239 Eina_Array *properties = NULL;
240 Efl_Model_Load_Status status;
241 eo_do(model, status = efl_model_properties_get(&properties));
242 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
243 ck_assert_ptr_ne(NULL, properties);
244
245 unsigned int actual_properties_count = eina_array_count(properties);
246
247 unsigned int expected_properties_count = 0;
248 const char *expected_property = NULL;
249 while ((expected_property = *expected_properties++))
250 {
251 const char *actual_property = eina_array_data_get(properties,
252 expected_properties_count);
253 ck_assert_str_eq(expected_property, actual_property);
254 ++expected_properties_count;
255 ck_assert_int_le(expected_properties_count, actual_properties_count);
256 }
257
258 ck_assert_int_eq(expected_properties_count, actual_properties_count);
259}
260
261static void
262_check_properties_count_eq(Efl_Model_Base *model,
263 unsigned int expected_properties_count)
264{
265 Eina_Array *properties = NULL;
266 Efl_Model_Load_Status status;
267 eo_do(model, status = efl_model_properties_get(&properties));
268 ck_assert_int_ne(EFL_MODEL_LOAD_STATUS_ERROR, status);
269 if (!expected_properties_count && !properties)
270 return;
271
272 ck_assert_ptr_ne(NULL, properties);
273
274 unsigned int actual_properties_count = eina_array_count(properties);
275 ck_assert_int_eq(expected_properties_count, actual_properties_count);
276}
277
278START_TEST(smoke)
279{
280 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
281 NULL,
282 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
283 ck_assert_ptr_ne(NULL, json);
284 eo_unref(json);
285}
286END_TEST
287
288START_TEST(load_object)
289{
290 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
291 NULL,
292 ejson_model_constructor(EJSON_MODEL_TYPE_OBJECT));
293 ck_assert_ptr_ne(NULL, json);
294
295 _check_emodel_load(json);
296
297 eo_unref(json);
298}
299END_TEST
300
301START_TEST(object_property_set)
302{
303 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
304 NULL,
305 ejson_model_constructor(EJSON_MODEL_TYPE_OBJECT));
306 ck_assert_ptr_ne(NULL, json);
307
308 _check_emodel_load(json);
309
310 _check_json_string(json, "{ }");
311
312 Efl_Model_Base *child = eo_do_ret(json, child, efl_model_child_add());
313 ck_assert_ptr_ne(NULL, child);
314
315 _check_json_string(json, "{ }");
316
317 Ejson_Model_Type type = eo_do_ret(child, type, ejson_model_type_get());
318 ck_assert_int_eq(EJSON_MODEL_TYPE_NULL, type);
319 eo_do(child, ejson_model_type_set(EJSON_MODEL_TYPE_INT));
320 eo_do(child, type = ejson_model_type_get());
321 ck_assert_int_eq(EJSON_MODEL_TYPE_INT, type);
322
323 _check_emodel_load(child);
324
325 _check_json_string(child, "null");
326 _check_json_string(json, "{ }");
327
328 // set member name
329 _check_name_property_set(child, "a");
330 _check_json_string(child, "null");
331 _check_json_string(json, "{ \"a\": null }");
332
333 // set member value
334 _check_int_value_property_set(child, 1234);
335 _check_json_string(json, "{ \"a\": 1234 }");
336
337 // change member name
338 _check_name_property_set(child, "b");
339 _check_json_string(json, "{ \"b\": 1234 }");
340
341 eo_unref(json);
342}
343END_TEST
344
345START_TEST(array_object_property_set)
346{
347 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
348 NULL,
349 ejson_model_constructor(EJSON_MODEL_TYPE_ARRAY));
350 ck_assert_ptr_ne(NULL, json);
351
352 _check_emodel_load(json);
353
354 _check_json_string(json, "[ ]");
355
356 Efl_Model_Base *child = eo_do_ret(json, child, efl_model_child_add());
357 ck_assert_ptr_ne(NULL, child);
358
359 _check_json_string(json, "[ ]");
360
361 Ejson_Model_Type type = eo_do_ret(child, type, ejson_model_type_get());
362 ck_assert_int_eq(EJSON_MODEL_TYPE_NULL, type);
363 eo_do(child, ejson_model_type_set(EJSON_MODEL_TYPE_INT));
364 eo_do(child, type = ejson_model_type_get());
365 ck_assert_int_eq(EJSON_MODEL_TYPE_INT, type);
366
367 _check_emodel_load(child);
368
369 _check_json_string(child, "null");
370 _check_json_string(json, "[ ]");
371
372 _check_int_value_property_set(child, 1234);
373
374 _check_json_string(json, "[ 1234 ]");
375
376 eo_unref(json);
377}
378END_TEST
379
380START_TEST(int_property_set)
381{
382 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
383 NULL,
384 ejson_model_constructor(EJSON_MODEL_TYPE_INT));
385 ck_assert_ptr_ne(NULL, json);
386
387 _check_emodel_load(json);
388
389 _check_json_string(json, "null");
390
391 _check_int_value_property_set(json, 1234);
392
393 _check_value_type_cannot_have_children(json);
394
395 eo_unref(json);
396}
397END_TEST
398
399START_TEST(boolean_property_set)
400{
401 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
402 NULL,
403 ejson_model_constructor(EJSON_MODEL_TYPE_BOOLEAN));
404 ck_assert_ptr_ne(NULL, json);
405
406 _check_emodel_load(json);
407
408 _check_json_string(json, "null");
409
410 _check_bool_value_property_set(json, true);
411 _check_bool_value_property_set(json, false);
412
413 _check_value_type_cannot_have_children(json);
414
415 eo_unref(json);
416}
417END_TEST
418
419START_TEST(string_property_set)
420{
421 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
422 NULL,
423 ejson_model_constructor(EJSON_MODEL_TYPE_STRING));
424 ck_assert_ptr_ne(NULL, json);
425
426 _check_emodel_load(json);
427
428 _check_json_string(json, "null");
429
430 _check_string_value_property_set(json, "Hello world!");
431
432 _check_value_type_cannot_have_children(json);
433
434 eo_unref(json);
435}
436END_TEST
437
438START_TEST(json_object_property_set)
439{
440 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
441 NULL,
442 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
443 ck_assert_ptr_ne(NULL, json);
444
445 _json_property_set(json, "{ \"a\": 1, \"b\": \"Hello\" }");
446
447 _check_emodel_load(json);
448
449 _check_json_string(json, "{ \"a\": 1, \"b\": \"Hello\" }");
450
451 _check_emodel_children_count_eq(json, 2);
452
453 Efl_Model_Base *child1 = _emodel_nth_child_get(json, 1);
454 Efl_Model_Base *child2 = _emodel_nth_child_get(json, 2);
455
456 _check_ejson_type(child1, EJSON_MODEL_TYPE_INT);
457 _check_ejson_type(child2, EJSON_MODEL_TYPE_STRING);
458
459 _check_emodel_load(child1);
460
461 _check_emodel_property_int_eq(child1, EJSON_MODEL_VALUE_PROPERTY, 1);
462 _check_emodel_property_str_eq(child1, EJSON_MODEL_NAME_PROPERTY, "a");
463
464 _check_emodel_load(child2);
465
466 _check_emodel_property_str_eq(child2, EJSON_MODEL_VALUE_PROPERTY, "Hello");
467 _check_emodel_property_str_eq(child2, EJSON_MODEL_NAME_PROPERTY, "b");
468
469 _json_property_set(child2, "{ \"c\": 2, \"d\": \"World\" }");
470
471 _check_json_string(json, "{ \"a\": 1, \"b\": { \"c\": 2, \"d\": \"World\" } }");
472
473 eo_unref(json);
474}
475END_TEST
476
477START_TEST(json_array_property_set)
478{
479 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
480 NULL,
481 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
482 ck_assert_ptr_ne(NULL, json);
483
484 _json_property_set(json, "[ 1, \"Hello\" ]");
485
486 _check_emodel_load(json);
487
488 _check_json_string(json, "[ 1, \"Hello\" ]");
489
490 _check_emodel_children_count_eq(json, 2);
491
492 Efl_Model_Base *child1 = _emodel_nth_child_get(json, 1);
493 Efl_Model_Base *child2 = _emodel_nth_child_get(json, 2);
494
495 _check_ejson_type(child1, EJSON_MODEL_TYPE_INT);
496 _check_ejson_type(child2, EJSON_MODEL_TYPE_STRING);
497
498 _check_emodel_load(child1);
499
500 _check_emodel_property_int_eq(child1, EJSON_MODEL_VALUE_PROPERTY, 1);
501
502 _check_emodel_load(child2);
503
504 _check_emodel_property_str_eq(child2, EJSON_MODEL_VALUE_PROPERTY, "Hello");
505
506 _json_property_set(child2, "[ 2, \"World\" ]");
507
508 _check_json_string(json, "[ 1, [ 2, \"World\" ] ]");
509
510 eo_unref(json);
511}
512END_TEST
513
514START_TEST(load_status_get)
515{
516 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
517 NULL,
518 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
519 ck_assert_ptr_ne(NULL, json);
520
521 Efl_Model_Load_Status status;
522 eo_do(json, status = efl_model_load_status_get());
523 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
524
525 _check_emodel_load(json);
526
527 eo_do(json, status = efl_model_load_status_get());
528 ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
529
530 eo_unref(json);
531}
532END_TEST
533
534static const char *_all_json_types_object_string =
535 "{ \"i\": 1, "
536 "\"s\": \"Hello World!\", "
537 "\"b\": true, "
538 "\"d\": 1.234, "
539 "\"n\": null, "
540 "\"o\": { }, "
541 "\"a\": [ ] "
542 "}";
543
544static Efl_Model_Base *
545_create_model_with_all_json_types()
546{
547 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
548 NULL,
549 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
550 ck_assert_ptr_ne(NULL, json);
551
552 _check_emodel_load(json);
553
554 _json_property_set(json, _all_json_types_object_string);
555 _check_json_string(json, _all_json_types_object_string);
556
557 _check_emodel_children_count_eq(json, 7);
558 return json;
559}
560
561START_TEST(properties_get)
562{
563 Efl_Model_Base *json = _create_model_with_all_json_types();
564
565 _check_emodel_properties(json, (const char*[]){"json", NULL});
566
567 Efl_Model_Base *child_i = _emodel_nth_child_get(json, 1);
568 Efl_Model_Base *child_s = _emodel_nth_child_get(json, 2);
569 Efl_Model_Base *child_b = _emodel_nth_child_get(json, 3);
570 Efl_Model_Base *child_d = _emodel_nth_child_get(json, 4);
571 Efl_Model_Base *child_n = _emodel_nth_child_get(json, 5);
572 Efl_Model_Base *child_o = _emodel_nth_child_get(json, 6);
573 Efl_Model_Base *child_a = _emodel_nth_child_get(json, 7);
574
575 _check_emodel_load(child_i);
576 _check_emodel_load(child_s);
577 _check_emodel_load(child_b);
578 _check_emodel_load(child_d);
579 _check_emodel_load(child_n);
580 _check_emodel_load(child_o);
581 _check_emodel_load(child_a);
582
583 _check_ejson_type(child_i, EJSON_MODEL_TYPE_INT);
584 _check_ejson_type(child_s, EJSON_MODEL_TYPE_STRING);
585 _check_ejson_type(child_b, EJSON_MODEL_TYPE_BOOLEAN);
586 _check_ejson_type(child_d, EJSON_MODEL_TYPE_DOUBLE);
587 _check_ejson_type(child_n, EJSON_MODEL_TYPE_NULL);
588 _check_ejson_type(child_o, EJSON_MODEL_TYPE_OBJECT);
589 _check_ejson_type(child_a, EJSON_MODEL_TYPE_ARRAY);
590
591 _check_emodel_properties(child_i, (const char*[]){"json", "value", "name", NULL});
592 _check_emodel_properties(child_s, (const char*[]){"json", "value", "name", NULL});
593 _check_emodel_properties(child_b, (const char*[]){"json", "value", "name", NULL});
594 _check_emodel_properties(child_d, (const char*[]){"json", "value", "name", NULL});
595 _check_emodel_properties(child_n, (const char*[]){"json", "name", NULL});
596 _check_emodel_properties(child_o, (const char*[]){"json", "name", NULL});
597 _check_emodel_properties(child_a, (const char*[]){"json", "name", NULL});
598
599 eo_unref(json);
600}
601END_TEST
602
603START_TEST(unload)
604{
605 Efl_Model_Base *json = _create_model_with_all_json_types();
606
607 eo_do(json, efl_model_unload());
608 _wait_until_load_status(json, EFL_MODEL_LOAD_STATUS_UNLOADED);
609
610 // reload
611 _check_emodel_load(json);
612 _check_json_string(json, "{ }");
613
614 _json_property_set(json, _all_json_types_object_string);
615 _check_json_string(json, _all_json_types_object_string);
616
617 eo_unref(json);
618}
619END_TEST
620
621START_TEST(properties_load)
622{
623 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
624 NULL,
625 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
626 ck_assert_ptr_ne(NULL, json);
627
628 _json_property_set(json, _all_json_types_object_string);
629
630 eo_do(json, efl_model_properties_load());
631 _wait_until_load_status(json, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
632
633 _check_emodel_children_count_eq(json, 0);
634
635 _check_json_string(json, _all_json_types_object_string);
636
637 eo_unref(json);
638}
639END_TEST
640
641START_TEST(children_load)
642{
643 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS,
644 NULL,
645 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
646 ck_assert_ptr_ne(NULL, json);
647
648 _json_property_set(json, _all_json_types_object_string);
649
650 eo_do(json, efl_model_children_load());
651 _wait_until_load_status(json, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
652
653 _check_emodel_children_count_eq(json, 7);
654
655 _check_properties_count_eq(json, 0);
656
657 eo_unref(json);
658}
659END_TEST
660
661
662START_TEST(object_child_del)
663{
664 Efl_Model_Base *json = _create_model_with_all_json_types();
665
666 Efl_Model_Base *child_i = _emodel_nth_child_get(json, 1);
667 Efl_Model_Base *child_s = _emodel_nth_child_get(json, 2);
668 Efl_Model_Base *child_b = _emodel_nth_child_get(json, 3);
669 Efl_Model_Base *child_d = _emodel_nth_child_get(json, 4);
670 Efl_Model_Base *child_n = _emodel_nth_child_get(json, 5);
671 Efl_Model_Base *child_o = _emodel_nth_child_get(json, 6);
672 Efl_Model_Base *child_a = _emodel_nth_child_get(json, 7);
673
674 eo_do(json, efl_model_child_del(child_s));
675 _check_emodel_children_count_eq(json, 6);
676 _check_json_string(json, "{ \"i\": 1, \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { }, \"a\": [ ] }");
677
678 eo_do(json, efl_model_child_del(child_i));
679 _check_emodel_children_count_eq(json, 5);
680 _check_json_string(json, "{ \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { }, \"a\": [ ] }");
681
682 eo_do(json, efl_model_child_del(child_a));
683 _check_emodel_children_count_eq(json, 4);
684 _check_json_string(json, "{ \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { } }");
685
686 eo_do(json, efl_model_child_del(child_d));
687 _check_emodel_children_count_eq(json, 3);
688 _check_json_string(json, "{ \"b\": true, \"n\": null, \"o\": { } }");
689
690 eo_do(json, efl_model_child_del(child_b));
691 _check_emodel_children_count_eq(json, 2);
692 _check_json_string(json, "{ \"n\": null, \"o\": { } }");
693
694 eo_do(json, efl_model_child_del(child_o));
695 _check_emodel_children_count_eq(json, 1);
696 _check_json_string(json, "{ \"n\": null }");
697
698 eo_do(json, efl_model_child_del(child_n));
699 _check_emodel_children_count_eq(json, 0);
700 _check_json_string(json, "{ }");
701
702 eo_unref(json);
703}
704END_TEST
705
706START_TEST(array_child_del)
707{
708 const char *_all_json_types_array_string =
709 "[ 1, \"Hello World!\", true, 1.234, null, { }, [ ] ]";
710
711 Efl_Model_Base *json = eo_add(EJSON_MODEL_CLASS, NULL,
712 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
713 ck_assert_ptr_ne(NULL, json);
714
715 _check_emodel_load(json);
716
717 _json_property_set(json, _all_json_types_array_string);
718 _check_json_string(json, _all_json_types_array_string);
719
720 _check_emodel_children_count_eq(json, 7);
721
722 Efl_Model_Base *child_i = _emodel_nth_child_get(json, 1);
723 Efl_Model_Base *child_s = _emodel_nth_child_get(json, 2);
724 Efl_Model_Base *child_b = _emodel_nth_child_get(json, 3);
725 Efl_Model_Base *child_d = _emodel_nth_child_get(json, 4);
726 Efl_Model_Base *child_n = _emodel_nth_child_get(json, 5);
727 Efl_Model_Base *child_o = _emodel_nth_child_get(json, 6);
728 Efl_Model_Base *child_a = _emodel_nth_child_get(json, 7);
729
730 eo_do(json, efl_model_child_del(child_s));
731 _check_emodel_children_count_eq(json, 6);
732 _check_json_string(json, "[ 1, true, 1.234, null, { }, [ ] ]");
733
734 eo_do(json, efl_model_child_del(child_i));
735 _check_emodel_children_count_eq(json, 5);
736 _check_json_string(json, "[ true, 1.234, null, { }, [ ] ]");
737
738 eo_do(json, efl_model_child_del(child_a));
739 _check_emodel_children_count_eq(json, 4);
740 _check_json_string(json, "[ true, 1.234, null, { } ]");
741
742 eo_do(json, efl_model_child_del(child_d));
743 _check_emodel_children_count_eq(json, 3);
744 _check_json_string(json, "[ true, null, { } ]");
745
746 eo_do(json, efl_model_child_del(child_b));
747 _check_emodel_children_count_eq(json, 2);
748 _check_json_string(json, "[ null, { } ]");
749
750 eo_do(json, efl_model_child_del(child_o));
751 _check_emodel_children_count_eq(json, 1);
752 _check_json_string(json, "[ null ]");
753
754 eo_do(json, efl_model_child_del(child_n));
755 _check_emodel_children_count_eq(json, 0);
756 _check_json_string(json, "[ ]");
757
758 eo_unref(json);
759}
760END_TEST
761
762void
763ejson_test_ejson_model(TCase *tc)
764{
765 tcase_add_checked_fixture(tc, _setup, _teardown);
766 tcase_add_test(tc, smoke);
767 tcase_add_test(tc, load_object);
768 tcase_add_test(tc, object_property_set);
769 tcase_add_test(tc, array_object_property_set);
770 tcase_add_test(tc, int_property_set);
771 tcase_add_test(tc, boolean_property_set);
772 tcase_add_test(tc, string_property_set);
773 tcase_add_test(tc, json_object_property_set);
774 tcase_add_test(tc, json_array_property_set);
775 tcase_add_test(tc, load_status_get);
776 tcase_add_test(tc, properties_get);
777 tcase_add_test(tc, unload);
778 tcase_add_test(tc, properties_load);
779 tcase_add_test(tc, children_load);
780 tcase_add_test(tc, object_child_del);
781 tcase_add_test(tc, array_child_del);
782}
diff --git a/src/tests/ejson/ejson_test_ejson_model.h b/src/tests/ejson/ejson_test_ejson_model.h
new file mode 100644
index 0000000000..ea5c939761
--- /dev/null
+++ b/src/tests/ejson/ejson_test_ejson_model.h
@@ -0,0 +1,6 @@
1#ifndef _EJSON_TEST_EJSON_MODEL_H
2#define _EJSON_TEST_EJSON_MODEL_H
3
4#include <Ejson.h>
5
6#endif