diff options
author | Lauro Moura <lauromoura@expertisesolutions.com.br> | 2016-06-03 12:30:50 -0300 |
---|---|---|
committer | Lauro Moura <lauromoura@expertisesolutions.com.br> | 2016-06-03 20:29:13 -0300 |
commit | b4637e2327847a1ce833952a65a99bcea4e5cad3 (patch) | |
tree | d2074bdf66f98b255e630d27411ba4ed7e3ce4d5 | |
parent | 4afb32573aa0dd44c9471445fe2a80fdd4d5d1f4 (diff) | |
download | efl-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.am | 3 | ||||
-rw-r--r-- | configure.ac | 34 | ||||
-rw-r--r-- | pc/ejson.pc.in | 18 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/Makefile_Ejson.am | 35 | ||||
-rw-r--r-- | src/lib/ejson/Ejson.h | 63 | ||||
-rw-r--r-- | src/lib/ejson/ejson_core.c | 67 | ||||
-rw-r--r-- | src/lib/ejson/ejson_model.c | 526 | ||||
-rw-r--r-- | src/lib/ejson/ejson_model.eo | 50 | ||||
-rw-r--r-- | src/lib/ejson/ejson_model_private.h | 31 | ||||
-rw-r--r-- | src/lib/ejson/ejson_private.h | 16 |
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 |