summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2016-06-03 12:30:50 -0300
committerLauro Moura <lauromoura@expertisesolutions.com.br>2016-06-03 20:29:13 -0300
commitb4637e2327847a1ce833952a65a99bcea4e5cad3 (patch)
treed2074bdf66f98b255e630d27411ba4ed7e3ce4d5
parent4afb32573aa0dd44c9471445fe2a80fdd4d5d1f4 (diff)
downloadefl-b4637e2327847a1ce833952a65a99bcea4e5cad3.tar.gz
ejson: Add ejson model.
Eo-based model using the eina json parser. Original authors: - Larry Jr <larry.olj@gmail.com> - Guilherme Lepsch <lepsch@expertisesolutions.com.br> @feature
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac34
-rw-r--r--pc/ejson.pc.in18
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile_Ejson.am35
-rw-r--r--src/lib/ejson/Ejson.h63
-rw-r--r--src/lib/ejson/ejson_core.c67
-rw-r--r--src/lib/ejson/ejson_model.c526
-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.h16
11 files changed, 843 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index e6ef14962b..146e5bbcb9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -155,7 +155,8 @@ pc/emotion.pc \
pc/ethumb.pc \
pc/ethumb_client.pc \
pc/elocation.pc \
-pc/elementary.pc
+pc/elementary.pc \
+pc/ejson.pc
if HAVE_CXX11
pkgconfig_DATA += \
diff --git a/configure.ac b/configure.ac
index a1d1f883da..a247b0e4b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5624,6 +5624,38 @@ AC_ARG_ENABLE([cancel-ok],
],[])
AC_SUBST(ELM_EDJE_DEFINES)
+#### Ejson
+EFL_LIB_START([Ejson])
+
+### Additional options to configure
+
+### Default values
+
+### Checks for programs
+
+## Compatibility layers
+
+### Checks for Libraries
+EFL_INTERNAL_DEPEND_PKG([EJSON], [eina])
+EFL_INTERNAL_DEPEND_PKG([EJSON], [ecore])
+EFL_INTERNAL_DEPEND_PKG([EJSON], [eo])
+EFL_INTERNAL_DEPEND_PKG([EJSON], [efl])
+
+### Checks for header files
+
+### Checks for types
+
+### Checks for structures
+
+### Checks for compiler characteristics
+
+### Checks for linker characteristics
+
+### Checks for library functions
+
+EFL_LIB_END([Ejson])
+#### End of Ejson
+
## Disable warning for OS that have a specifc configuration
case "$host_os" in
@@ -5764,6 +5796,7 @@ pc/elementary.pc
pc/elementary-cxx.pc
pc/elput.pc
pc/ecore-drm2.pc
+pc/ejson.pc
dbus-services/org.enlightenment.Ethumb.service
systemd-services/ethumb.service
$po_makefile_in
@@ -5944,6 +5977,7 @@ echo "Ethumb..........: yes"
echo "Ethumb_Client...: yes"
echo "Elua............: $have_elua"
echo "Elementary......: yes (${features_elementary})"
+echo "Ejson...........: yes"
echo
echo
diff --git a/pc/ejson.pc.in b/pc/ejson.pc.in
new file mode 100644
index 0000000000..ff6b0fe488
--- /dev/null
+++ b/pc/ejson.pc.in
@@ -0,0 +1,18 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+modules=@libdir@/ejson
+module_arch=@MODULE_ARCH@
+datarootdir=@datarootdir@
+datadir=@datadir@
+eoincludedir=@datadir@/eolian/include
+eolian_flags=-I${pc_sysrootdir}${eoincludedir}/ejson-@VMAJ@
+
+Name: ejson
+Description: Ejson model class
+Requires.private: @requirements_pc_ejson@
+Version: @VERSION@
+Libs: -L${libdir} -lejson -lefl -leo -leina -ecore
+Libs.private: @requirements_libs_ejson@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/ecore-@VMAJ@ -I${includedir}/ejson-@VMAJ@
diff --git a/src/Makefile.am b/src/Makefile.am
index 50839cb746..cce33e825c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,6 +62,7 @@ include Makefile_Ecore_Audio.am
include Makefile_Ecore_Avahi.am
include Makefile_Embryo.am
include Makefile_Eio.am
+include Makefile_Ejson.am
include Makefile_Efreet.am
include Makefile_Ecore_Buffer.am
include Makefile_EPhysics.am
diff --git a/src/Makefile_Ejson.am b/src/Makefile_Ejson.am
new file mode 100644
index 0000000000..852bb2a628
--- /dev/null
+++ b/src/Makefile_Ejson.am
@@ -0,0 +1,35 @@
+### Library
+
+ejson_eolian_files = \
+ lib/ejson/ejson_model.eo
+
+ejson_eolian_h = $(ejson_eolian_files:%.eo=%.eo.h)
+ejson_eolian_c = $(ejson_eolian_files:%.eo=%.eo.c)
+
+BUILT_SOURCES += $(ejson_eolian_c) $(ejson_eolian_h)
+
+ejsoneolianfilesdir = $(datadir)/eolian/include/ejson-@VMAJ@
+ejsoneolianfiles_DATA = $(ejson_eolian_files)
+
+lib_LTLIBRARIES += lib/ejson/libejson.la
+EXTRA_DIST += \
+$(ejsoneolianfiles_DATA) \
+lib/ejson/Makefile.am \
+lib/ejson/Makefile.in
+
+installed_ejsonmainheadersdir = $(includedir)/ejson-@VMAJ@
+
+dist_installed_ejsonmainheaders_DATA = \
+lib/ejson/Ejson.h
+nodist_installed_ejsonmainheaders_DATA = $(ejson_eolian_h)
+
+lib_ejson_libejson_la_SOURCES = \
+lib/ejson/ejson_core.c \
+lib/ejson/ejson_model.c \
+lib/ejson/ejson_model_private.h \
+lib/ejson/ejson_private.h
+
+lib_ejson_libejson_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EJSON_CFLAGS@ @EFL_CFLAGS@
+lib_ejson_libejson_la_LIBADD = @EJSON_LIBS@ @EFL_LIBS@
+lib_ejson_libejson_la_DEPENDENCIES = @EJSON_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
+lib_ejson_libejson_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
diff --git a/src/lib/ejson/Ejson.h b/src/lib/ejson/Ejson.h
new file mode 100644
index 0000000000..c2b50107be
--- /dev/null
+++ b/src/lib/ejson/Ejson.h
@@ -0,0 +1,63 @@
+#ifndef EJSON_H
+#define EJSON_H
+
+#include <Ecore.h>
+#include <Efl.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EIO_BUILD
+# ifdef DLL_EXPORT
+# define EAPI __declspec(dllexport)
+# else
+# define EAPI
+# endif /* ! DLL_EXPORT */
+# else
+# define EAPI __declspec(dllimport)
+# endif /* ! EFL_EIO_BUILD */
+#else
+# ifdef __GNUC__
+# if __GNUC__ >= 4
+# define EAPI __attribute__ ((visibility("default")))
+# else
+# define EAPI
+# endif
+# else
+# define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EJSON_MODEL_NAME_PROPERTY "name"
+#define EJSON_MODEL_VALUE_PROPERTY "value"
+
+/**
+ * @brief Initialize ejson.
+ *
+ * @return 1 or greater on success, 0 otherwise
+ */
+EAPI int ejson_init(void);
+
+/**
+ * @brief Shutdown ejson.
+ *
+ * @return 0 if e_dbus shuts down, greater than 0 otherwise.
+ */
+EAPI int ejson_shutdown(void);
+
+#include <ejson_model.eo.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef EAPI
+#define EAPI
+
+#endif
diff --git a/src/lib/ejson/ejson_core.c b/src/lib/ejson/ejson_core.c
new file mode 100644
index 0000000000..643d2518b8
--- /dev/null
+++ b/src/lib/ejson/ejson_core.c
@@ -0,0 +1,67 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "Ejson.h"
+#include "ejson_private.h"
+
+static int _ejson_init_count = 0;
+int _ejson_log_dom = -1;
+
+EAPI int
+ejson_init(void)
+{
+ if (_ejson_init_count++ > 0)
+ return _ejson_init_count;
+
+ if (!eina_init())
+ {
+ fputs("Ejson: Unable to initialize eina\n", stderr);
+ return 0;
+ }
+
+ _ejson_log_dom = eina_log_domain_register("ejson_model", EINA_COLOR_CYAN);
+ if (_ejson_log_dom < 0)
+ {
+ EINA_LOG_ERR("Unable to create an 'ejson_model' log domain");
+ _ejson_log_dom = -1;
+ eina_shutdown();
+ return 0;
+ }
+
+ ecore_app_no_system_modules();
+ if (!ecore_init())
+ {
+ ERR("Unable to initialize ecore");
+ eina_log_domain_unregister(_ejson_log_dom);
+ _ejson_log_dom = -1;
+ eina_shutdown();
+ return 0;
+ }
+
+ // ...
+
+ return _ejson_init_count;
+}
+
+EAPI int
+ejson_shutdown(void)
+{
+ if (_ejson_init_count <= 0)
+ {
+ ERR("Init count not greater than 0 in shutdown.");
+ _ejson_init_count = 0;
+ return 0;
+ }
+
+ if (--_ejson_init_count)
+ return _ejson_init_count;
+
+ // ...
+
+ ecore_shutdown();
+ eina_log_domain_unregister(_ejson_log_dom);
+ _ejson_log_dom = -1;
+ eina_shutdown();
+ return 0;
+}
diff --git a/src/lib/ejson/ejson_model.c b/src/lib/ejson/ejson_model.c
new file mode 100644
index 0000000000..9ece47ea13
--- /dev/null
+++ b/src/lib/ejson/ejson_model.c
@@ -0,0 +1,526 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ejson.h"
+#include "ejson_model_private.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define MY_CLASS EJSON_MODEL_CLASS
+#define MY_CLASS_NAME "Ejson_Model"
+
+typedef struct _Ejson_Model_Child_Data
+{
+ Ejson_Model_Data *pd;
+ Eo *parent;
+} Ejson_Model_Child_Data;
+
+
+static void _ejson_model_clear(Ejson_Model_Data *);
+static bool _ejson_model_name_property_set(Ejson_Model_Data *, const Eina_Value *, Eina_Promise_Owner *promise);
+static bool _ejson_model_value_property_set(Ejson_Model_Data *, const Eina_Value *, Eina_Promise_Owner *promise);
+static bool _ejson_model_stream_load(Ejson_Model_Data *, const char*, unsigned);
+static Eina_Bool _ejson_model_eina_value_as(const Eina_Value *, const Eina_Value_Type *, void *);
+typedef Ejson_Model_Child_Data *(*Ejson_Model_Child_Data_New)(void *);
+
+static Eina_Bool _parse_simple_obj_cb(void *data, Eina_Simple_JSON_Value_Type type, const char *key, const char *content, unsigned length);
+
+static void _ejson_model_type_set(Eo *obj, Ejson_Model_Data *pd, Ejson_Model_Type type);
+
+void
+_accessor_free(void *data)
+{
+ Eina_Accessor *ac = data;
+ if (!ac)
+ return;
+ Eina_List *list = eina_accessor_container_get(ac);
+ eina_accessor_free(ac);
+ eina_list_free(list);
+}
+
+static Eo_Base*
+_ejson_model_eo_base_constructor(Eo *obj, Ejson_Model_Data *pd)
+{
+ obj = eo_constructor(eo_super(obj, MY_CLASS));
+
+ pd->obj = obj;
+ pd->properties_array = eina_array_new(1);
+ pd->value = NULL;
+ pd->name = NULL;
+ pd->children_list = NULL;
+ pd->json_property_valid = false;
+
+ _ejson_model_type_set(obj, pd, EJSON_MODEL_TYPE_NULL);
+
+ return obj;
+}
+
+static void
+_ejson_model_string_set(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd,
+ const char* stream)
+{
+ _ejson_model_stream_load(pd, stream, strlen(stream));
+}
+
+static void
+_ejson_model_eo_base_destructor(Eo *obj, Ejson_Model_Data *pd)
+{
+ _ejson_model_clear(pd);
+
+ eo_destructor(eo_super(obj, MY_CLASS));
+}
+
+static void
+_fill_default_value(Ejson_Model_Data *pd)
+{
+ pd->value = eina_value_optional_empty_new();
+}
+
+static Eina_Array const *
+_ejson_model_efl_model_properties_get(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, NULL);
+
+ return pd->properties_array;
+}
+
+static void
+_ejson_model_efl_model_property_set(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd,
+ const char *property,
+ const Eina_Value *value,
+ Eina_Promise_Owner *promise)
+{
+ Efl_Model_Property_Event evt;
+ if (strcmp(EJSON_MODEL_NAME_PROPERTY, property) == 0)
+ {
+ if (!_ejson_model_name_property_set(pd, value, promise))
+ return;
+
+ evt.changed_properties = eina_array_new(1);
+ eina_array_push(evt.changed_properties, EJSON_MODEL_NAME_PROPERTY);
+ }
+ else if (strcmp(EJSON_MODEL_VALUE_PROPERTY, property) == 0)
+ {
+ if (!_ejson_model_value_property_set(pd, value, promise))
+ return;
+
+ evt.changed_properties = eina_array_new(1);
+ eina_array_push(evt.changed_properties, EJSON_MODEL_VALUE_PROPERTY);
+ }
+ else
+ {
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+ return;
+ }
+
+ if (eina_array_count(evt.changed_properties))
+ {
+ pd->json_property_valid = false;
+ eo_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt);
+ }
+
+ eina_array_free(evt.changed_properties);
+}
+
+static bool
+_ejson_model_name_property_set(Ejson_Model_Data *pd, const Eina_Value *value,
+ Eina_Promise_Owner *promise)
+{
+ const char *name = NULL;
+
+ if (!value || !(name = eina_value_to_string(value)))
+ {
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
+ return false;
+ }
+
+ if (!pd->name)
+ eina_array_push(pd->properties_array, "name");
+
+ free((char*)pd->name);
+ pd->name = name;
+
+ eina_promise_owner_value_set(promise, value, NULL);
+
+ return true;
+}
+
+static bool
+_ejson_model_value_property_set(Ejson_Model_Data *pd, const Eina_Value *value,
+ Eina_Promise_Owner *promise)
+{
+ const Eina_Value_Type * const value_type = eina_value_type_get(value);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
+
+
+ /* json_object *json = NULL; */
+ switch (pd->type)
+ {
+ case EJSON_MODEL_TYPE_BOOLEAN:
+ {
+ int v;
+ Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_INT, &v);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
+
+ break;
+ }
+ case EJSON_MODEL_TYPE_DOUBLE:
+ {
+ double v;
+ Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_DOUBLE, &v);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
+
+ break;
+ }
+ case EJSON_MODEL_TYPE_INT:
+ {
+ long int v;
+ eina_value_get(value, &v);
+ Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_INT64, &v);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
+ eina_value_get(value, &v);
+
+ break;
+ }
+ case EJSON_MODEL_TYPE_STRING:
+ {
+ const char *v;
+ Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_STRING, &v);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
+
+ break;
+ }
+ case EJSON_MODEL_TYPE_NULL:
+ case EJSON_MODEL_TYPE_OBJECT:
+ case EJSON_MODEL_TYPE_ARRAY:
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
+ return false;
+ }
+
+ // Copy takes care of flushing the previous values in pd->value.
+ if (!pd->value)
+ {
+ eina_array_push(pd->properties_array, "value");
+ _fill_default_value(pd);
+ }
+ Eina_Bool ret = eina_value_copy(value, pd->value);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+ eina_promise_owner_value_set(promise, value, NULL);
+
+ return true;
+
+on_error:
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_UNKNOWN);
+ return false;
+}
+
+static void
+_ejson_model_efl_model_property_get(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd,
+ const char *property,
+ Eina_Promise_Owner *promise)
+{
+ if (property == NULL && pd->value == NULL)
+ {
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
+ return;
+ }
+
+ if (strcmp(EJSON_MODEL_NAME_PROPERTY, property) == 0)
+ {
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, pd->name);
+
+ eina_promise_owner_value_set(promise, &value, (Eina_Promise_Free_Cb)eina_value_flush);
+ }
+ else if(strcmp(EJSON_MODEL_VALUE_PROPERTY, property) == 0)
+ {
+ if (!pd->value)
+ {
+ eina_array_push(pd->properties_array, "value");
+ _fill_default_value(pd);
+ }
+ eina_promise_owner_value_set(promise, pd->value, NULL);
+ }
+ else
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+}
+
+Eo *
+_ejson_model_efl_model_child_add(Eo *obj, Ejson_Model_Data *pd)
+{
+ switch (pd->type)
+ {
+ case EJSON_MODEL_TYPE_ARRAY:
+ case EJSON_MODEL_TYPE_OBJECT:
+ break;
+ default:
+ WRN("Value types cannot have children: %d", pd->type);
+ return NULL;
+ }
+
+ Eo *child = eo_add(EJSON_MODEL_CLASS, obj,
+ ejson_model_type_set(eo_self, EJSON_MODEL_TYPE_NULL));
+
+ pd->children_list = eina_list_append(pd->children_list, child);
+
+ return child;
+}
+
+static void
+_ejson_model_efl_model_child_del(Eo *obj,
+ Ejson_Model_Data *pd,
+ Eo *child)
+{
+ EINA_SAFETY_ON_NULL_RETURN(child);
+
+ int idx = eina_list_data_idx(pd->children_list, child);
+
+ if(idx >= 0)
+ {
+ pd->children_list = eina_list_remove(pd->children_list, child);
+ unsigned int count = eina_list_count(pd->children_list);
+
+ Efl_Model_Children_Event cevt = {.child = child, .index = idx};
+ eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_REMOVED, &cevt);
+ eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &count);
+ eo_parent_set(child, NULL);
+ eo_unref(child);
+ }
+}
+
+static void
+_ejson_model_efl_model_children_slice_get(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd,
+ unsigned start,
+ unsigned count,
+ Eina_Promise_Owner *promise)
+{
+
+ Eina_Accessor *children_accessor = efl_model_list_slice(pd->children_list, start, count);
+ if (children_accessor)
+ eina_promise_owner_value_set(promise, children_accessor, &_accessor_free);
+ else
+ eina_promise_owner_error_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+}
+
+static void
+_ejson_model_efl_model_children_count_get(Eo *obj EINA_UNUSED,
+ Ejson_Model_Data *pd,
+ Eina_Promise_Owner *promise)
+{
+ unsigned int children_count = eina_list_count(pd->children_list);
+ eina_promise_owner_value_set(promise, &children_count, NULL);
+}
+
+
+
+static Ejson_Model_Type
+_ejson_model_type_get(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
+{
+ return pd->type;
+}
+
+static void
+_ejson_model_type_set(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd, const Ejson_Model_Type type)
+{
+ EINA_SAFETY_ON_FALSE_RETURN(type >= 0 && type <= EJSON_MODEL_TYPE_ARRAY);
+ pd->type = type;
+}
+
+static void
+_ejson_model_clear(Ejson_Model_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ // No need to free each child as they were added through eo_add
+ eina_list_free(pd->children_list);
+
+ if (pd->properties_array)
+ {
+ eina_array_free(pd->properties_array);
+ pd->properties_array = NULL;
+ }
+
+ pd->json_property_valid = false;
+
+ free((char*)pd->name);
+ pd->name = NULL;
+
+ eina_value_free(pd->value);
+}
+
+/* JSON SIMPLE PARSE INIT */
+
+static Eina_Bool
+_parse_simple_child_setup(Ejson_Model *obj, Eina_Simple_JSON_Value_Type type, const char *content, unsigned length)
+{
+ Ejson_Model_Type mtype;
+ Eina_Value value;
+ Eina_Promise *promise = NULL;
+
+ switch(type)
+ {
+ case EINA_SIMPLE_JSON_VALUE_OBJECT:
+ {
+ ejson_model_type_set(obj, EJSON_MODEL_TYPE_OBJECT);
+ return eina_simple_json_object_parse(content, length, _parse_simple_obj_cb, obj);
+ }
+ case EINA_SIMPLE_JSON_VALUE_ARRAY:
+ {
+ ejson_model_type_set(obj, EJSON_MODEL_TYPE_ARRAY);
+ return eina_simple_json_object_parse(content, length, _parse_simple_obj_cb, obj);
+ }
+ case EINA_SIMPLE_JSON_VALUE_STRING:
+ {
+ char buf[length+1];
+ mtype = EJSON_MODEL_TYPE_STRING;
+ memcpy(&buf, content, length);
+ buf[length] = '\0';
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, buf);
+ break;
+ }
+ case EINA_SIMPLE_JSON_VALUE_BOOLEAN:
+ {
+ unsigned int b = !strncmp(content, "true", sizeof("true")-1);
+ mtype = EJSON_MODEL_TYPE_BOOLEAN;
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&value, b);
+ break;
+ }
+ case EINA_SIMPLE_JSON_VALUE_INT:
+ {
+ char v[length+1];
+ mtype = EJSON_MODEL_TYPE_INT;
+
+ memcpy(&v, content, length);
+ v[length] = '\0';
+ int64_t n = atoi(v);
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT64);
+ eina_value_set(&value, n);
+ break;
+ }
+ case EINA_SIMPLE_JSON_VALUE_DOUBLE:
+ {
+ char v[length+1];
+ mtype = EJSON_MODEL_TYPE_DOUBLE;
+
+ memcpy(&v, content, length);
+ v[length] = '\0';
+ double n = atof(v);
+ eina_value_setup(&value, EINA_VALUE_TYPE_DOUBLE);
+ eina_value_set(&value, &n);
+ break;
+ }
+ case EINA_SIMPLE_JSON_VALUE_NULL:
+ default:
+ {
+ mtype = EJSON_MODEL_TYPE_NULL;
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, NULL);
+ }
+ }
+
+
+ ejson_model_type_set(obj, mtype);
+ efl_model_property_set(obj, EJSON_MODEL_VALUE_PROPERTY, &value, &promise);
+ eina_value_flush(&value);
+ eina_promise_unref(promise);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_parse_simple_array_cb(void *data, Eina_Simple_JSON_Value_Type type, const char *content, unsigned length)
+{
+ Ejson_Model *parent = data;
+ Eo* child;
+ child = efl_model_child_add(parent);
+
+ return _parse_simple_child_setup(child, type, content, length);
+}
+
+static Eina_Bool
+_parse_simple_obj_cb(void *data, Eina_Simple_JSON_Value_Type type, const char *key, const char *content, unsigned length)
+{
+ Ejson_Model *parent = data;
+ Eo* child;
+ Eina_Promise *promise = NULL;
+ child = efl_model_child_add(parent);
+
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, key);
+ efl_model_property_set(child, EJSON_MODEL_NAME_PROPERTY, &value, &promise);
+ eina_value_flush(&value);
+
+ if (eina_promise_error_get(promise))
+ {
+ eina_promise_unref(promise);
+ return EINA_FALSE;
+ }
+
+ eina_promise_unref(promise);
+
+ return _parse_simple_child_setup(child, type, content, length);
+}
+
+static Eina_Bool
+_parse_simple_load_cb(void *data, Eina_Simple_JSON_Type type, const char *content, unsigned length)
+{
+ Ejson_Model_Data *pd = data;
+
+ if (type == EINA_SIMPLE_JSON_OBJECT)
+ {
+ pd->type = EJSON_MODEL_TYPE_OBJECT;
+ return eina_simple_json_object_parse(content, length, _parse_simple_obj_cb, pd->obj);
+ }
+ else if (type == EINA_SIMPLE_JSON_ARRAY)
+ {
+ pd->type = EJSON_MODEL_TYPE_ARRAY;
+ return eina_simple_json_array_parse(content, length, _parse_simple_array_cb, pd->obj);
+ }
+
+ return EINA_FALSE;
+}
+
+static bool
+_ejson_model_stream_load(Ejson_Model_Data *pd, const char* stream, unsigned slen)
+{
+ if (!stream || !eina_simple_json_parse(stream, slen, _parse_simple_load_cb, pd))
+ return false;
+
+ pd->json_property_valid = true;
+ return true;
+}
+/* JSON SIMPLE PARSE END */
+
+static Eina_Bool
+_ejson_model_eina_value_as(const Eina_Value *value, const Eina_Value_Type *type, void *mem)
+{
+ const Eina_Value_Type * const value_type = eina_value_type_get(value);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
+
+ if (value_type == type)
+ return eina_value_get(value, mem);
+
+ Eina_Value convert;
+ Eina_Bool ret = eina_value_setup(&convert, type)
+ && eina_value_convert(value, &convert)
+ && eina_value_get(&convert, mem);
+ eina_value_flush(&convert);
+
+ return ret;
+}
+
+
+#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..cb266b088c
--- /dev/null
+++ b/src/lib/ejson/ejson_model.eo
@@ -0,0 +1,50 @@
+
+enum Ejson.Model.Type {
+ null,
+ boolean,
+ double,
+ int,
+ string,
+ object,
+ array
+}
+
+class Ejson.Model (Eo.Base, Efl.Model) {
+ [[Ejson model class]]
+
+ data: Ejson_Model_Data;
+ methods {
+ string_set {
+ [[Custom Ejson_Model constructor by stream.
+
+ ejson_model_constructor
+ @since 1.17]]
+ params {
+ @in stream: const(char)*; [[Json object type]]
+ }
+ }
+
+ @property type {
+ get { }
+ set { }
+ values {
+ type: Ejson.Model.Type;
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.properties.get;
+ Efl.Model.property_set;
+ Efl.Model.property_get;
+ Efl.Model.child_add;
+ Efl.Model.child_del;
+ Efl.Model.children_slice_get;
+ Efl.Model.children_count_get;
+ }
+ constructors {
+ .type;
+ .string_set;
+ }
+}
diff --git a/src/lib/ejson/ejson_model_private.h b/src/lib/ejson/ejson_model_private.h
new file mode 100644
index 0000000000..09c1307b26
--- /dev/null
+++ b/src/lib/ejson/ejson_model_private.h
@@ -0,0 +1,31 @@
+#ifndef _EJSON_MODEL_PRIVATE_H
+#define _EJSON_MODEL_PRIVATE_H
+
+#include "ejson_private.h"
+
+#include <Eo.h>
+#include <Efl.h>
+
+#include <stdbool.h>
+
+#include "Ejson.h"
+
+
+typedef struct _Ejson_Model_Data Ejson_Model_Data;
+
+/**
+ * ejson_model
+ */
+struct _Ejson_Model_Data
+{
+ Eo *obj;
+ Eina_Array *properties_array;
+ Eina_List *children_list;
+ Ejson_Model_Type type;
+ bool json_property_valid;
+ const char *name;
+ Eina_Value *value;
+};
+
+#endif
+
diff --git a/src/lib/ejson/ejson_private.h b/src/lib/ejson/ejson_private.h
new file mode 100644
index 0000000000..f394dfa4de
--- /dev/null
+++ b/src/lib/ejson/ejson_private.h
@@ -0,0 +1,16 @@
+#ifndef _EJSON_PRIVATE_H
+#define _EJSON_PRIVATE_H
+
+#include <Eo.h>
+#include <Efl.h>
+
+/* logging support */
+extern int _ejson_log_dom;
+
+#define CRI(...) EINA_LOG_DOM_CRIT(_ejson_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_ejson_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_ejson_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_ejson_log_dom, __VA_ARGS__)
+#define DBG(...) EINA_LOG_DOM_DBG(_ejson_log_dom, __VA_ARGS__)
+
+#endif