forked from enlightenment/efl
edbus: Parse EDBus_Message to Eina_Value
Patch by: José Roberto de Souza <zehortigoza@profusion.mobi> SVN revision: 78543
This commit is contained in:
parent
6fb7d45936
commit
45a5f7e5d5
|
@ -64,7 +64,8 @@ include_HEADERS = \
|
|||
src/lib/edbus_proxy.h \
|
||||
src/lib/edbus_service.h \
|
||||
src/lib/edbus_signal_handler.h \
|
||||
src/lib/edbus_message_helper.h
|
||||
src/lib/edbus_message_helper.h \
|
||||
src/lib/edbus_message_to_eina_value.h
|
||||
|
||||
libedbus2_la_LIBADD = @ECORE_LIBS@ @DBUS_LIBS@
|
||||
libedbus2_la_SOURCES = \
|
||||
|
@ -78,7 +79,8 @@ libedbus2_la_SOURCES = \
|
|||
src/lib/edbus_freedesktop.c \
|
||||
src/lib/edbus_service.c \
|
||||
src/lib/edbus_signal_handler.c \
|
||||
src/lib/edbus_message_helper.c
|
||||
src/lib/edbus_message_helper.c \
|
||||
src/lib/edbus_message_to_eina_value.c
|
||||
|
||||
if EFL_BUILD_EXAMPLES
|
||||
noinst_PROGRAMS = \
|
||||
|
|
|
@ -134,6 +134,7 @@ typedef void (*EDBus_Signal_Cb)(void *data, const EDBus_Message *msg);
|
|||
#include "edbus_freedesktop.h"
|
||||
#include "edbus_service.h"
|
||||
#include "edbus_message_helper.h"
|
||||
#include "edbus_message_to_eina_value.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,484 @@
|
|||
#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 void _eina_value_struct_free(Eina_Value *value, Eina_Array *array);
|
||||
static Eina_Value *_message_iter_struct_to_eina_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"
|
||||
|
||||
static Eina_Value *
|
||||
_message_iter_struct_to_eina_value(EDBus_Message_Iter *iter)
|
||||
{
|
||||
int type;
|
||||
Eina_Value *value_st;
|
||||
Eina_Array *st_members = eina_array_new(1);
|
||||
unsigned int offset = 0, z;
|
||||
static char name[7];//arg000 + \0
|
||||
Eina_Value_Struct_Member *members;
|
||||
Eina_Value_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;
|
||||
|
||||
//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++;
|
||||
}
|
||||
|
||||
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->members = members;
|
||||
st_desc->member_count = eina_array_count(st_members);
|
||||
st_desc->size = offset;
|
||||
value_st = eina_value_struct_new(st_desc);
|
||||
eina_array_free(st_members);
|
||||
|
||||
//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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
EAPI void edbus_message_to_eina_value_free(Eina_Value *value);
|
||||
|
||||
EAPI Eina_Value *edbus_message_to_eina_value(const EDBus_Message *msg);
|
Loading…
Reference in New Issue