From 1513705c9b2b1e4910a360e540520510d62129bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 26 Oct 2012 18:19:52 +0000 Subject: [PATCH] edbus: Parse Eina_Value to edbus_message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by: José Roberto de Souza SVN revision: 78548 --- legacy/edbus/Makefile.am | 3 +- legacy/edbus/src/examples/complex_types.c | 14 + .../edbus/src/examples/complex_types_server.c | 11 +- legacy/edbus/src/lib/EDBus.h | 1 + .../src/lib/edbus_message_from_eina_value.c | 371 ++++++++++++++++++ .../src/lib/edbus_message_from_eina_value.h | 1 + .../src/lib/edbus_message_to_eina_value.c | 148 +++---- .../src/lib/edbus_message_to_eina_value.h | 2 - legacy/edbus/src/lib/edbus_proxy.c | 6 +- 9 files changed, 451 insertions(+), 106 deletions(-) create mode 100644 legacy/edbus/src/lib/edbus_message_from_eina_value.c create mode 100644 legacy/edbus/src/lib/edbus_message_from_eina_value.h diff --git a/legacy/edbus/Makefile.am b/legacy/edbus/Makefile.am index ce14f775e5..fef3d1e45e 100644 --- a/legacy/edbus/Makefile.am +++ b/legacy/edbus/Makefile.am @@ -80,7 +80,8 @@ libedbus2_la_SOURCES = \ src/lib/edbus_service.c \ src/lib/edbus_signal_handler.c \ src/lib/edbus_message_helper.c \ - src/lib/edbus_message_to_eina_value.c + src/lib/edbus_message_to_eina_value.c \ + src/lib/edbus_message_from_eina_value.c if EFL_BUILD_EXAMPLES noinst_PROGRAMS = \ diff --git a/legacy/edbus/src/examples/complex_types.c b/legacy/edbus/src/examples/complex_types.c index 43e168285b..f90daec074 100644 --- a/legacy/edbus/src/examples/complex_types.c +++ b/legacy/edbus/src/examples/complex_types.c @@ -28,6 +28,12 @@ _read_cache(void *data) printf("Read cache: %s | %d\n", txt, num); + v = edbus_proxy_property_local_get(proxy, "st"); + eina_value_struct_get(v, "arg0", &txt); + printf("Read cache: [st] %s | ", txt); + eina_value_struct_get(v, "arg1", &txt); + printf("%s\n", txt); + return EINA_FALSE; } @@ -218,6 +224,14 @@ _property_changed(void *data, EDBus_Proxy *proxy, void *event_info) eina_value_get(value, &num); printf("[%s] = %d\n", name, num); } + else if (!strcmp(name, "st")) + { + const char *txt; + eina_value_struct_get(value, "arg0", &txt); + printf("[%s] %s | ", name, txt); + eina_value_struct_get(value, "arg1", &txt); + printf("%s\n", txt); + } } int diff --git a/legacy/edbus/src/examples/complex_types_server.c b/legacy/edbus/src/examples/complex_types_server.c index 451c7c2a71..57ebc13a27 100644 --- a/legacy/edbus/src/examples/complex_types_server.c +++ b/legacy/edbus/src/examples/complex_types_server.c @@ -348,7 +348,7 @@ static Eina_Bool _emmit_changed(void *data) { EDBus_Service_Interface *iface = data; EDBus_Message *sig = edbus_service_signal_new(iface, 0); - EDBus_Message_Iter *main_iter, *array, *entry, *var, *invalidate; + EDBus_Message_Iter *main_iter, *array, *entry, *var, *invalidate, *st; main_iter = edbus_message_iter_get(sig); if (!edbus_message_iter_arguments_set(main_iter, "sa{sv}", IFACE, &array)) @@ -371,6 +371,15 @@ static Eina_Bool _emmit_changed(void *data) edbus_message_iter_container_close(entry, var); edbus_message_iter_container_close(array, entry); + edbus_message_iter_arguments_set(array, "{sv}", &entry); + edbus_message_iter_arguments_set(entry, "s", "st"); + var = edbus_message_iter_container_new(entry, 'v', "(ss)"); + edbus_message_iter_arguments_set(var, "(ss)", &st); + edbus_message_iter_arguments_set(st, "ss", "string1", "string2"); + edbus_message_iter_container_close(var, st); + edbus_message_iter_container_close(entry, var); + edbus_message_iter_container_close(array, entry); + edbus_message_iter_container_close(main_iter, array); edbus_message_iter_arguments_set(main_iter, "as", &invalidate); diff --git a/legacy/edbus/src/lib/EDBus.h b/legacy/edbus/src/lib/EDBus.h index 4adfc623d7..1be2e34809 100644 --- a/legacy/edbus/src/lib/EDBus.h +++ b/legacy/edbus/src/lib/EDBus.h @@ -135,6 +135,7 @@ typedef void (*EDBus_Signal_Cb)(void *data, const EDBus_Message *msg); #include "edbus_service.h" #include "edbus_message_helper.h" #include "edbus_message_to_eina_value.h" +#include "edbus_message_from_eina_value.h" #ifdef __cplusplus } diff --git a/legacy/edbus/src/lib/edbus_message_from_eina_value.c b/legacy/edbus/src/lib/edbus_message_from_eina_value.c new file mode 100644 index 0000000000..095c6320f7 --- /dev/null +++ b/legacy/edbus/src/lib/edbus_message_from_eina_value.c @@ -0,0 +1,371 @@ +#include "edbus_private.h" +#include "edbus_private_types.h" + +static Eina_Bool _message_iter_from_eina_value_struct(const char *signature, EDBus_Message_Iter *iter, const Eina_Value *value); + +static Eina_Bool +_compatible_type(int dbus_type, const Eina_Value_Type *value_type) +{ + switch (dbus_type) + { + case 'i': + case 'h': + return value_type == EINA_VALUE_TYPE_INT; + case 's': + case 'o': + case 'g': + return value_type == EINA_VALUE_TYPE_STRING; + case 'b': + case 'y': + return value_type == EINA_VALUE_TYPE_UCHAR; + case 'n': + return value_type == EINA_VALUE_TYPE_SHORT; + case 'q': + return value_type == EINA_VALUE_TYPE_USHORT; + case 'u': + return value_type == EINA_VALUE_TYPE_UINT; + case 'x': + return value_type == EINA_VALUE_TYPE_INT64; + case 't': + return value_type == EINA_VALUE_TYPE_UINT64; + case 'd': + return value_type == EINA_VALUE_TYPE_DOUBLE; + case 'a': + return value_type == EINA_VALUE_TYPE_ARRAY; + case '(': + case '{': + case 'e': + case 'r': + return value_type == EINA_VALUE_TYPE_STRUCT; + default: + ERR("Unknown type %c", dbus_type); + return EINA_FALSE; + } +} + +static Eina_Bool +_array_append(const char *type, const Eina_Value *value_array, EDBus_Message_Iter *iter) +{ + EDBus_Message_Iter *array; + + EINA_SAFETY_ON_FALSE_RETURN_VAL( + edbus_message_iter_arguments_set(iter, type, &array), EINA_FALSE); + DBG("array of type %c", type[1]); + switch (type[1]) + { + case '{': + case '(': + { + unsigned i = strlen(type+2);//remove 'a()' of len a(sv) + char *entry_sig = malloc(sizeof(char) * i); + memcpy(entry_sig, type+2, i); + entry_sig[i-1] = 0; + + for (i = 0; i < eina_value_array_count(value_array); i++) + { + Eina_Value st; + EDBus_Message_Iter *entry; + eina_value_array_value_get(value_array, i, &st); + edbus_message_iter_arguments_set(array, type+1, &entry); + _message_iter_from_eina_value_struct(entry_sig, entry, &st); + edbus_message_iter_container_close(array, entry); + eina_value_flush(&st); + } + free(entry_sig); + break; + } + case 'a': + { + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + Eina_Value inner_array; + EDBus_Message_Iter *sub_array; + eina_value_array_value_get(value_array, i, &inner_array); + edbus_message_iter_arguments_set(array, type+1, &sub_array); + _array_append(type+1, &inner_array, sub_array); + edbus_message_iter_container_close(array, sub_array); + eina_value_flush(&inner_array); + } + } + case 'v': + { + ERR("Variant not supported."); + return EINA_FALSE; + } + case 'i': + case 'h'://fd + { + int32_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 's': + case 'o'://object path + case 'g'://signature + { + const char *txt; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &txt); + edbus_message_iter_basic_append(array, type[1], txt); + } + break; + } + case 'b'://boolean + case 'y'://byte + { + unsigned char z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 'n'://int16 + { + int16_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 'q'://uint16 + { + uint16_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 'u'://uint32 + { + uint32_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 'x'://int64 + { + int64_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 't'://uint64 + { + uint64_t z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + case 'd'://double + { + double z; + unsigned i; + for (i = 0; i < eina_value_array_count(value_array); i++) + { + eina_value_array_get(value_array, i, &z); + edbus_message_iter_basic_append(array, type[1], z); + } + break; + } + default: + { + ERR("Unknown type %c", type[1]); + return EINA_FALSE; + } + } + edbus_message_iter_container_close(iter, array); + return EINA_TRUE; +} + +static Eina_Bool +_basic_append(char type, const Eina_Value *value, const Eina_Value_Struct_Desc *desc, unsigned idx, EDBus_Message_Iter *iter) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL( + _compatible_type(type, desc->members[idx].type), EINA_FALSE); + switch (type) + { + case 'i'://int + case 'h'://fd + { + int32_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 's': + case 'o'://object path + case 'g'://signature + { + const char *txt; + eina_value_struct_get(value, desc->members[idx].name, &txt); + edbus_message_iter_basic_append(iter, type, txt); + break; + } + case 'b'://boolean + case 'y'://byte + { + unsigned char byte; + eina_value_struct_get(value, desc->members[idx].name, &byte); + edbus_message_iter_basic_append(iter, type, byte); + break; + } + case 'n'://int16 + { + int16_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 'q'://uint16 + { + uint16_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 'u'://uint32 + { + uint32_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 'x'://int64 + { + int64_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 't'://uint64 + { + uint64_t i; + eina_value_struct_get(value, desc->members[idx].name, &i); + edbus_message_iter_basic_append(iter, type, i); + break; + } + case 'd'://double + { + double d; + eina_value_struct_get(value, desc->members[idx].name, &d); + edbus_message_iter_basic_append(iter, type, d); + break; + } + default: + ERR("Unexpected type %c", type); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_message_iter_from_eina_value_struct(const char *signature, EDBus_Message_Iter *iter, const Eina_Value *value) +{ + unsigned i; + DBusSignatureIter signature_iter; + Eina_Bool r = EINA_TRUE; + char *type; + Eina_Value_Struct st; + + EINA_SAFETY_ON_FALSE_RETURN_VAL( + eina_value_type_get(value) == EINA_VALUE_TYPE_STRUCT, EINA_FALSE); + eina_value_pget(value, &st); + + dbus_signature_iter_init(&signature_iter, signature); + i = 0; + while ((type = dbus_signature_iter_get_signature(&signature_iter))) + { + DBG("type: %s", type); + if (type[0] != 'v' && !type[1]) + r = _basic_append(type[0], value, st.desc, i, iter); + else if (type[0] == 'a') + { + Eina_Value value_array; + + EINA_SAFETY_ON_FALSE_RETURN_VAL( + _compatible_type(type[0], st.desc->members[i].type), + EINA_FALSE); + eina_value_struct_value_get(value, st.desc->members[i].name, + &value_array); + r = _array_append(type, &value_array, iter); + eina_value_flush(&value_array); + } + else if (type[0] == '(') + { + Eina_Value inner_st; + EDBus_Message_Iter *sub_iter; + char *sub_sig; + unsigned len = strlen(type+1) -1; + sub_sig = malloc(sizeof(char) * len); + memcpy(sub_sig, type+1, len); + sub_sig[len-1] = 0; + EINA_SAFETY_ON_FALSE_RETURN_VAL( + _compatible_type(type[0], st.desc->members[i].type), + EINA_FALSE); + eina_value_struct_value_get(value, st.desc->members[i].name, &inner_st); + edbus_message_iter_arguments_set(iter, type, &sub_iter); + r = _message_iter_from_eina_value_struct(sub_sig, sub_iter, + &inner_st); + edbus_message_iter_container_close(iter, sub_iter); + free(sub_sig); + } + else if (type[0] == 'v') + { + ERR("Variant not supported"); + r = EINA_FALSE; + } + else + { + ERR("Unknown type %c", type[0]); + r = EINA_FALSE; + } + i++; + dbus_free(type); + if (!r || !dbus_signature_iter_next(&signature_iter)) break; + } + return r; +} + +EAPI Eina_Bool +edbus_message_from_eina_value(const char *signature, EDBus_Message *msg, const Eina_Value *value) +{ + EDBus_Message_Iter *iter; + EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + + iter = edbus_message_iter_get(msg); + EINA_SAFETY_ON_NULL_RETURN_VAL(iter, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE); + + return _message_iter_from_eina_value_struct(signature, iter, value); +} diff --git a/legacy/edbus/src/lib/edbus_message_from_eina_value.h b/legacy/edbus/src/lib/edbus_message_from_eina_value.h new file mode 100644 index 0000000000..11707fd76b --- /dev/null +++ b/legacy/edbus/src/lib/edbus_message_from_eina_value.h @@ -0,0 +1 @@ +EAPI Eina_Bool edbus_message_from_eina_value(const char *signature, EDBus_Message *msg, const Eina_Value *value); diff --git a/legacy/edbus/src/lib/edbus_message_to_eina_value.c b/legacy/edbus/src/lib/edbus_message_to_eina_value.c index d3d0663a3d..5efbe427b0 100644 --- a/legacy/edbus/src/lib/edbus_message_to_eina_value.c +++ b/legacy/edbus/src/lib/edbus_message_to_eina_value.c @@ -2,7 +2,6 @@ #include "edbus_private_types.h" static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Message_Iter *iter); -static void _eina_value_struct_free(Eina_Value *value, Eina_Array *array); static const Eina_Value_Type * _dbus_type_to_eina_value_type(char type) @@ -216,6 +215,48 @@ _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Mess #define ARG "arg%d" +typedef struct _EDBus_Struct_Desc +{ + Eina_Value_Struct_Desc base; + int refcount; +} EDBus_Struct_Desc; + +static void * +_ops_malloc(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc) +{ + EDBus_Struct_Desc *edesc = (EDBus_Struct_Desc*)desc; + edesc->refcount++; + DBG("%p refcount=%d", edesc, edesc->refcount); + return malloc(desc->size); +} + +static void +_ops_free(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, void *memory) +{ + EDBus_Struct_Desc *edesc = (EDBus_Struct_Desc*) desc; + edesc->refcount--; + free(memory); + DBG("%p refcount=%d", edesc, edesc->refcount); + if (edesc->refcount <= 0) + { + unsigned i; + for (i = 0; i < edesc->base.member_count; i++) + free((char *)edesc->base.members[i].name); + free((Eina_Value_Struct_Member *)edesc->base.members); + free(edesc); + } +} + +static Eina_Value_Struct_Operations operations = +{ + EINA_VALUE_STRUCT_OPERATIONS_VERSION, + _ops_malloc, + _ops_free, + NULL, + NULL, + NULL +}; + Eina_Value * _message_iter_struct_to_eina_value(EDBus_Message_Iter *iter) { @@ -225,13 +266,13 @@ _message_iter_struct_to_eina_value(EDBus_Message_Iter *iter) unsigned int offset = 0, z; static char name[7];//arg000 + \0 Eina_Value_Struct_Member *members; - Eina_Value_Struct_Desc *st_desc; + EDBus_Struct_Desc *st_desc; Eina_Array *st_values = eina_array_new(1); DBG("begin struct"); - st_desc = calloc(1, sizeof(Eina_Value_Struct_Desc)); - st_desc->version = EINA_VALUE_STRUCT_DESC_VERSION; - st_desc->ops = NULL; + st_desc = calloc(1, sizeof(EDBus_Struct_Desc)); + st_desc->base.version = EINA_VALUE_STRUCT_DESC_VERSION; + st_desc->base.ops = &operations; //create member list z = 0; @@ -364,10 +405,10 @@ _message_iter_struct_to_eina_value(EDBus_Message_Iter *iter) } //setup - st_desc->members = members; - st_desc->member_count = eina_array_count(st_members); - st_desc->size = offset; - value_st = eina_value_struct_new(st_desc); + st_desc->base.members = members; + st_desc->base.member_count = eina_array_count(st_members); + st_desc->base.size = offset; + value_st = eina_value_struct_new((Eina_Value_Struct_Desc *)st_desc); eina_array_free(st_members); //filling with data @@ -392,92 +433,3 @@ edbus_message_to_eina_value(const EDBus_Message *msg) EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL); return _message_iter_struct_to_eina_value(iter); } - -static void -_eina_value_array_free(Eina_Value *value, Eina_Array *array) -{ - Eina_Value_Array value_array; - unsigned i; - - eina_value_pget(value, &value_array); - if (value_array.subtype == EINA_VALUE_TYPE_STRUCT) - { - for (i = 0; i < eina_value_array_count(value); i++) - { - Eina_Value st; - eina_value_array_value_get(value, i, &st); - _eina_value_struct_free(&st, array); - eina_value_flush(&st); - } - } - else if (value_array.subtype == EINA_VALUE_TYPE_ARRAY) - { - for (i = 0; i < eina_value_array_count(value); i++) - { - Eina_Value inner_array; - eina_value_array_value_get(value, i, &inner_array); - _eina_value_array_free(&inner_array, array); - eina_value_flush(&inner_array); - } - } -} -static void -_eina_value_struct_free(Eina_Value *value, Eina_Array *array) -{ - Eina_Value_Struct st; - unsigned i; - static char name[7]; - - DBG("value %p", value); - EINA_SAFETY_ON_FALSE_RETURN(eina_value_pget(value, &st)); - - for (i = 0; i < st.desc->member_count; i++) - { - DBG("arg%d of %p", i, value); - if (st.desc->members[i].type == EINA_VALUE_TYPE_STRUCT) - { - Eina_Value sub; - sprintf(name, ARG, i); - eina_value_struct_value_get(value, name, &sub); - _eina_value_struct_free(&sub, array); - eina_value_flush(&sub); - } - else if (st.desc->members[i].type == EINA_VALUE_TYPE_ARRAY) - { - Eina_Value sub; - sprintf(name, ARG, i); - eina_value_struct_value_get(value, name, &sub); - _eina_value_array_free(&sub, array); - eina_value_flush(&sub); - } - } - eina_array_push(array, st.desc); - DBG("end value %p", value); -} - -EAPI void -edbus_message_to_eina_value_free(Eina_Value *value) -{ - Eina_Array *descriptions; - Eina_Value_Struct_Desc *st_desc; - - EINA_SAFETY_ON_NULL_RETURN(value); - EINA_SAFETY_ON_FALSE_RETURN(eina_value_type_get(value) == EINA_VALUE_TYPE_STRUCT); - - descriptions = eina_array_new(1); - _eina_value_struct_free(value, descriptions); - eina_value_free(value); - - while ((st_desc = eina_array_pop(descriptions))) - { - unsigned i; - for (i = 0; i < st_desc->member_count; i++) - { - char *name = (char *)st_desc->members[i].name; - free(name); - } - free((Eina_Value_Struct_Member *)st_desc->members); - free(st_desc); - } - eina_array_free(descriptions); -} diff --git a/legacy/edbus/src/lib/edbus_message_to_eina_value.h b/legacy/edbus/src/lib/edbus_message_to_eina_value.h index b2e871d8f3..96044adc7d 100644 --- a/legacy/edbus/src/lib/edbus_message_to_eina_value.h +++ b/legacy/edbus/src/lib/edbus_message_to_eina_value.h @@ -1,3 +1 @@ -EAPI void edbus_message_to_eina_value_free(Eina_Value *value); - EAPI Eina_Value *edbus_message_to_eina_value(const EDBus_Message *msg); diff --git a/legacy/edbus/src/lib/edbus_proxy.c b/legacy/edbus/src/lib/edbus_proxy.c index 9142286160..2586b99907 100644 --- a/legacy/edbus/src/lib/edbus_proxy.c +++ b/legacy/edbus/src/lib/edbus_proxy.c @@ -303,9 +303,7 @@ _property_changed_iter(void *data, const void *key, EDBus_Message_Iter *var) event.value = value; _edbus_proxy_event_callback_call(proxy, EDBUS_PROXY_EVENT_PROPERTY_CHANGED, &event); - - edbus_message_to_eina_value_free(st_value); - //TODO if value have any STRUCT at this point it will not be accessible + eina_value_free(st_value); eina_value_flush(&stack_value); } @@ -707,7 +705,7 @@ _property_iter(void *data, const void *key, EDBus_Message_Iter *var) eina_hash_add(proxy->props, skey, value); } - edbus_message_to_eina_value_free(st_value); + eina_value_free(st_value); eina_value_flush(&stack_value); }