#include "edbus_private.h" #include "edbus_private_types.h" static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Message_Iter *iter); static const Eina_Value_Type * _dbus_type_to_eina_value_type(char type) { switch (type) { case 'i': case 'h': return EINA_VALUE_TYPE_INT; case 's': case 'o': case 'g': return EINA_VALUE_TYPE_STRING; case 'b': case 'y': return EINA_VALUE_TYPE_UCHAR; case 'n': return EINA_VALUE_TYPE_SHORT; case 'q': return EINA_VALUE_TYPE_USHORT; case 'u': return EINA_VALUE_TYPE_UINT; case 'x': return EINA_VALUE_TYPE_INT64; case 't': return EINA_VALUE_TYPE_UINT64; case 'd': return EINA_VALUE_TYPE_DOUBLE; case 'a': return EINA_VALUE_TYPE_ARRAY; case '(': case '{': case 'e': case 'r': case 'v': return EINA_VALUE_TYPE_STRUCT; default: ERR("Unknown type %c", type); return NULL; } } static unsigned int _type_size(char type) { switch (type) { case 'i': case 'h': case 'u': return(sizeof(int32_t)); case 's': case 'o': case 'g': return(sizeof(char *)); case 'b': case 'y': return(sizeof(unsigned char)); case 'n': case 'q': return(sizeof(int16_t)); case 'x': case 't': return(sizeof(int64_t)); case 'd': return(sizeof(double)); case 'a': return(sizeof(Eina_Value_Array)); case '(': case '{': case 'e': case 'r': case 'v': return(sizeof(Eina_Value_Struct)); default: ERR("Unknown type %c", type); return 0; } } static unsigned int _type_offset(char type, unsigned base) { unsigned size, padding; size = _type_size(type); if (!(base % size)) return base; padding = abs(base - size); return base + padding; } static Eina_Value * _message_iter_array_to_eina_value(EDBus_Message_Iter *iter) { Eina_Value *array_value; char *sig; sig = edbus_message_iter_signature_get(iter); DBG("array of %s", sig); array_value = eina_value_array_new(_dbus_type_to_eina_value_type(sig[0]), 0); if (sig[0] == '(' || sig[0] == '{' || sig[0] == 'v') { EDBus_Message_Iter *entry; if (sig[0] == '{') sig[0] = 'e'; else if (sig[0] == '(') sig[0] = 'r'; while (edbus_message_iter_get_and_next(iter, sig[0], &entry)) { Eina_Value *data = _message_iter_struct_to_eina_value(entry); Eina_Value_Struct st; eina_value_get(data, &st); eina_value_array_append(array_value, st); } } else if (sig[0] == 'a') { EDBus_Message_Iter *entry; while (edbus_message_iter_get_and_next(iter, sig[0], &entry)) { Eina_Value *data = _message_iter_array_to_eina_value(entry); Eina_Value_Array inner_array; eina_value_get(data, &inner_array); eina_value_array_append(array_value, inner_array); } } else _message_iter_basic_array_to_eina_value(sig[0], array_value, iter); DBG("return array of %s", sig); free(sig); return array_value; } static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Message_Iter *iter) { switch (type) { case 'i': case 'h'://fd { int32_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 's': case 'o'://object path case 'g'://signature { const char *txt; while (edbus_message_iter_get_and_next(iter, type, &txt)) eina_value_array_append(value, txt); break; } case 'b'://boolean case 'y'://byte { unsigned char byte; while (edbus_message_iter_get_and_next(iter, type, &byte)) eina_value_array_append(value, byte); break; } case 'n'://int16 { int16_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 'q'://uint16 { uint16_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 'u'://uint32 { uint32_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 'x'://int64 { int64_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 't'://uint64 { uint64_t i; while (edbus_message_iter_get_and_next(iter, type, &i)) eina_value_array_append(value, i); break; } case 'd'://double { double d; while (edbus_message_iter_get_and_next(iter, type, &d)) eina_value_array_append(value, d); break; } } } #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) { int type; Eina_Value *value_st = NULL; Eina_Array *st_members = eina_array_new(1); unsigned int offset = 0, z; char name[7];//arg000 + \0 Eina_Value_Struct_Member *members; EDBus_Struct_Desc *st_desc; Eina_Array *st_values = eina_array_new(1); DBG("begin struct"); 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; while ((type = dbus_message_iter_get_arg_type(&iter->dbus_iterator)) != DBUS_TYPE_INVALID) { Eina_Value_Struct_Member *m; Eina_Value *v; m = calloc(1, sizeof(Eina_Value_Struct_Member)); sprintf(name, ARG, z); m->name = strdup(name); offset = _type_offset(type, offset); m->offset = offset; offset += _type_size(type); m->type = _dbus_type_to_eina_value_type(type); eina_array_push(st_members, m); DBG("type = %c", type); switch (type) { case 'i'://int case 'h'://fd { int32_t i; v = eina_value_new(EINA_VALUE_TYPE_INT); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 's': case 'o'://object path case 'g'://signature { const char *txt; v = eina_value_new(EINA_VALUE_TYPE_STRING); edbus_message_iter_basic_get(iter, &txt); eina_value_set(v, txt); break; } case 'b'://boolean case 'y'://byte { unsigned char byte; v = eina_value_new(EINA_VALUE_TYPE_UCHAR); edbus_message_iter_basic_get(iter, &byte); eina_value_set(v, byte); break; } case 'n'://int16 { int16_t i; v = eina_value_new(EINA_VALUE_TYPE_SHORT); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 'q'://uint16 { uint16_t i; v = eina_value_new(EINA_VALUE_TYPE_USHORT); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 'u'://uint32 { uint32_t i; v = eina_value_new(EINA_VALUE_TYPE_UINT); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 'x'://int64 { int64_t i; v = eina_value_new(EINA_VALUE_TYPE_INT64); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 't'://uint64 { uint64_t i; v = eina_value_new(EINA_VALUE_TYPE_UINT64); edbus_message_iter_basic_get(iter, &i); eina_value_set(v, i); break; } case 'd'://double { double d; v = eina_value_new(EINA_VALUE_TYPE_DOUBLE); edbus_message_iter_basic_get(iter, &d); eina_value_set(v, d); break; } case 'a'://array { EDBus_Message_Iter *dbus_array; dbus_array = edbus_message_iter_sub_iter_get(iter); v = _message_iter_array_to_eina_value(dbus_array); break; } case '('://struct case 'r'://struct case 'v'://variant { EDBus_Message_Iter *dbus_st; dbus_st = edbus_message_iter_sub_iter_get(iter); v = _message_iter_struct_to_eina_value(dbus_st); break; } default: ERR("Unexpected type %c", type); v = NULL; } eina_array_push(st_values, v); edbus_message_iter_next(iter); z++; } if (!z) { free(st_desc); goto end; } members = malloc(eina_array_count(st_members) * sizeof(Eina_Value_Struct_Member)); for (z = 0; z < eina_array_count(st_members); z++) { Eina_Value_Struct_Member *m = eina_array_data_get(st_members, z); members[z].name = m->name; members[z].offset = m->offset; members[z].type = m->type; free(m); } //setup 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); //filling with data for (z = 0; z < eina_array_count(st_values); z++) { Eina_Value *v = eina_array_data_get(st_values, z); sprintf(name, ARG, z); eina_value_struct_value_set(value_st, name, v); eina_value_free(v); } end: eina_array_free(st_members); eina_array_free(st_values); DBG("end struct"); return value_st; } EAPI Eina_Value * edbus_message_to_eina_value(const EDBus_Message *msg) { EDBus_Message_Iter *iter; EINA_SAFETY_ON_FALSE_RETURN_VAL(msg, NULL); iter = edbus_message_iter_get(msg); EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL); return _message_iter_struct_to_eina_value(iter); } EAPI Eina_Value * edbus_message_iter_struct_like_to_eina_value(const EDBus_Message_Iter *iter) { EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL); return _message_iter_struct_to_eina_value((EDBus_Message_Iter *)iter); }