From 887f00856a32e70018bc30e688444afa9dc2c0ff Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 16 Sep 2013 21:41:21 +0100 Subject: [PATCH] idnode prop: make it possible to properly sort/filter enum/list types This does require a certain level of extra input from prop_t users where the type is enumerated. A new routine rend() must be implemented to provide the rendered value (for lists that are not enum, this is done transparently). --- src/idnode.c | 45 ++++++++++++++++++++++++++++++++++++++++----- src/prop.h | 5 +++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/idnode.c b/src/idnode.c index 92ad4c1a..bbf06825 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -126,7 +126,6 @@ idnode_init(void) { pthread_t tid; - randfd = open("/dev/urandom", O_RDONLY); if(randfd == -1) exit(1); @@ -301,6 +300,23 @@ idnode_find_prop return NULL; } +/* + * Get display value + */ +static char * +idnode_get_display + ( idnode_t *self, const property_t *p ) +{ + if (p->rend) + return p->rend(self); + if (p->islist) { + htsmsg_t *l = (htsmsg_t*)p->get(self); + if (l) + return htsmsg_list_2_csv(l); + } + return NULL; +} + /* * Get field as string */ @@ -329,6 +345,7 @@ idnode_get_u32 ( idnode_t *self, const char *key, uint32_t *u32 ) { const property_t *p = idnode_find_prop(self, key); + if (p->islist) return 1; if (p) { const void *ptr; if (p->get) @@ -361,6 +378,7 @@ idnode_get_bool ( idnode_t *self, const char *key, int *b ) { const property_t *p = idnode_find_prop(self, key); + if (p->islist) return 1; if (p) { void *ptr = self; ptr += p->off; @@ -446,17 +464,32 @@ idnode_cmp_sort idnode_t *inb = *(idnode_t**)b; idnode_sort_t *sort = s; const property_t *p = idnode_find_prop(ina, sort->key); + if (!p) return 0; + + /* Get display string */ + if (p->islist || p->list) { + int r; + char *stra = idnode_get_display(ina, p); + char *strb = idnode_get_display(inb, p); + if (sort->dir == IS_ASC) + r = strcmp(stra ?: "", strb ?: ""); + else + r = strcmp(strb ?: "", stra ?: ""); + free(stra); + free(strb); + return r; + } + switch (p->type) { case PT_STR: { int r; - char *stra = strdup(idnode_get_str(ina, sort->key) ?: ""); + const char *stra = idnode_get_str(ina, sort->key); const char *strb = idnode_get_str(inb, sort->key); if (sort->dir == IS_ASC) r = strcmp(stra ?: "", strb ?: ""); else r = strcmp(strb ?: "", stra ?: ""); - free(stra); return r; } break; @@ -490,8 +523,10 @@ idnode_filter LIST_FOREACH(f, filter, link) { if (f->type == IF_STR) { const char *str; - if (!(str = idnode_get_str(in, f->key))) - return 1; + str = idnode_get_display(in, idnode_find_prop(in, f->key)); + if (!str) + if (!(str = idnode_get_str(in, f->key))) + return 1; switch(f->comp) { case IC_IN: if (strstr(str, f->u.s) == NULL) diff --git a/src/prop.h b/src/prop.h index 995cd921..9567d8aa 100644 --- a/src/prop.h +++ b/src/prop.h @@ -59,8 +59,9 @@ typedef struct property { const void *(*get) (void *ptr); int (*set) (void *ptr, const void *v); htsmsg_t *(*list) (void *ptr); - // Note: htsmsg_t can either be a string list or object list - // where the object has "key" and "val" fields + char *(*rend) (void *ptr); ///< Provide the rendered value for enum/list + ///< Lists should be CSV. This is used for + ///< sorting and searching in UI API /* Notification callback */ void (*notify) (void *ptr);