idnode prop: new API for specifying lists

This is to avoid the need for string processing within the C code to combine
and split lists from CSV strings.
This commit is contained in:
Adam Sutton 2013-09-14 23:24:51 +01:00
parent 1fe897492b
commit a4adf79a7c
2 changed files with 85 additions and 73 deletions

View file

@ -58,11 +58,24 @@ prop_find(const property_t *p, const char *id)
*/
int
prop_write_values
(void *obj, const property_t *pl, htsmsg_t *m, int optmask, htsmsg_t *updated)
(void *obj, const property_t *pl, htsmsg_t *m, int optmask,
htsmsg_t *updated)
{
int save, save2 = 0;
htsmsg_field_t *f;
const property_t *p;
void *cur;
const void *new;
double dbl;
int i;
uint32_t u32;
uint16_t u16;
#define PROP_UPDATE(v, t)\
new = &v;\
if (!p->set && (*((t*)cur) != *((t*)new))) {\
save = 1;\
*((t*)cur) = *((t*)new);\
} (void)0
if (!pl) return 0;
@ -75,74 +88,67 @@ prop_write_values
/* Write */
save = 0;
void *v = obj + p->off;
cur = obj + p->off;
new = NULL;
switch (p->type) {
/* List */
if (p->islist)
new = htsmsg_field_get_list(f);
/* Singular */
else {
switch (p->type) {
case PT_BOOL: {
int *val = v, tmp;
if (!htsmsg_field_get_bool(f, &tmp))
if (*val != tmp) {
*val = tmp;
save = 1;
}
if (htsmsg_field_get_bool(f, &i))
continue;
PROP_UPDATE(i, int);
break;
}
case PT_INT: {
uint32_t tmp;
int *val = v;
if (!htsmsg_field_get_u32(f, &tmp))
if (*val != (int)tmp) {
*val = (int)tmp;
save = 1;
}
if (htsmsg_field_get_u32(f, &u32))
continue;
i = u32;
PROP_UPDATE(i, int);
break;
}
case PT_U16: {
uint32_t tmp;
uint16_t *val = v;
if (!htsmsg_field_get_u32(f, &tmp))
if (*val != (uint16_t)tmp) {
*val = (uint16_t)tmp;
save = 1;
}
if (htsmsg_field_get_u32(f, &u32))
continue;
u16 = (uint16_t)u32;
PROP_UPDATE(u16, uint16_t);
break;
}
case PT_U32: {
uint32_t tmp;
uint32_t *val = v;
if (!htsmsg_field_get_u32(f, &tmp))
if (*val != tmp) {
*val = tmp;
save = 1;
}
if (htsmsg_field_get_u32(f, &u32))
continue;
PROP_UPDATE(u32, uint32_t);
break;
}
case PT_DBL: {
double tmp;
double *val = v;
if (!htsmsg_field_get_dbl(f, &tmp))
if (*val != tmp) {
*val = tmp;
save = 1;
}
if (htsmsg_field_get_dbl(f, &dbl))
continue;
PROP_UPDATE(dbl, double);
break;
}
case PT_STR: {
char **val = v;
const char *tmp = htsmsg_field_get_str(f);
if (tmp) {
if(p->set != NULL)
save |= p->set(obj, tmp);
else if (strcmp(*val ?: "", tmp)) {
free(*val);
*val = strdup(tmp);
save = 1;
}
char **str = cur;
if (!(new = htsmsg_field_get_str(f)))
continue;
if (!p->set && strcmp((*str) ?: "", new)) {
free(*str);
*str = strdup(new);
save = 1;
}
break;
}
}
}
/* Setter */
if (p->set && new)
save = p->set(obj, new);
/* Updated */
if (save) {
save2 = 1;
if (p->notify)
@ -151,6 +157,7 @@ prop_write_values
htsmsg_set_u32(updated, p->id, 1);
}
}
#undef PROP_UPDATE
return save2;
}
@ -163,7 +170,8 @@ prop_write_values
*/
static void
prop_read_value
(void *obj, const property_t *p, htsmsg_t *m, const char *name, int optmask, htsmsg_t *inc)
(void *obj, const property_t *p, htsmsg_t *m, const char *name,
int optmask, htsmsg_t *inc)
{
const char *s;
const void *val = obj + p->off;
@ -179,29 +187,33 @@ prop_read_value
if (p->get)
val = p->get(obj);
/* Read */
switch(p->type) {
case PT_BOOL:
htsmsg_add_bool(m, name, *(int *)val);
break;
case PT_INT:
htsmsg_add_s64(m, name, *(int *)val);
break;
case PT_U32:
htsmsg_add_u32(m, name, *(uint32_t *)val);
break;
case PT_U16:
htsmsg_add_u32(m, name, *(uint16_t *)val);
break;
case PT_STR:
s = *(const char **)val;
if(s != NULL) {
htsmsg_add_str(m, name, s);
/* List */
if (p->islist)
htsmsg_add_msg(m, name, (htsmsg_t*)val);
/* Single */
else {
switch(p->type) {
case PT_BOOL:
htsmsg_add_bool(m, name, *(int *)val);
break;
case PT_INT:
htsmsg_add_s64(m, name, *(int *)val);
break;
case PT_U32:
htsmsg_add_u32(m, name, *(uint32_t *)val);
break;
case PT_U16:
htsmsg_add_u32(m, name, *(uint16_t *)val);
break;
case PT_STR:
if ((s = *(const char **)val))
htsmsg_add_str(m, name, s);
break;
case PT_DBL:
htsmsg_add_dbl(m, name, *(double*)val);
break;
}
break;
case PT_DBL:
htsmsg_add_dbl(m, name, *(double*)val);
break;
}
}
@ -238,6 +250,8 @@ prop_serialize(void *obj, const property_t *pl, htsmsg_t *msg, int optmask, htsm
htsmsg_add_str(m, "id", pl->id);
htsmsg_add_str(m, "caption", pl->name);
htsmsg_add_str(m, "type", val2str(pl->type, typetab) ?: "unknown");
if (pl->islist)
htsmsg_add_u32(m, "list", 1);
/* Options */
if (pl->opts & PO_RDONLY)
@ -246,8 +260,6 @@ prop_serialize(void *obj, const property_t *pl, htsmsg_t *msg, int optmask, htsm
htsmsg_add_u32(m, "nosave", 1);
if (pl->opts & PO_WRONCE)
htsmsg_add_u32(m, "wronce", 1);
if (pl->opts & PO_MULTI)
htsmsg_add_u32(m, "multi", 1);
/* Enum list */
if (pl->list)

View file

@ -43,7 +43,6 @@ typedef enum {
#define PO_RDONLY 0x01 // Property is read-only
#define PO_NOSAVE 0x02 // Property is transient (not saved)
#define PO_WRONCE 0x04 // Property is write-once (i.e. on creation)
#define PO_MULTI 0x08 // Multi-select
/*
* Property definition
@ -52,6 +51,7 @@ typedef struct property {
const char *id; ///< Property Key
const char *name; ///< Textual description
prop_type_t type; ///< Type
int islist; ///< Is a list
size_t off; ///< Offset into object
int opts; ///< Options