--- /dev/null
+#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);
+}
#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)
#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)
{
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;
}
//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
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);
-}