idnode: added new set processing routines

This allow a list of arbitrary idnode's to be compiled, including the
ability to filter (based on props and filter config) what gets included
and then a matching sort routine.

This makes generating idnode based grids fairly straight-forward.
This commit is contained in:
Adam Sutton 2013-06-07 21:34:24 +01:00
parent 75151722f6
commit 1ed3627e77
2 changed files with 234 additions and 0 deletions

View file

@ -1,8 +1,10 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "idnode.h"
#include "notify.h"
@ -428,3 +430,177 @@ idnode_get_u32
}
return 1;
}
/* **************************************************************************
* Set procsesing
* *************************************************************************/
static int
idnode_cmp_sort
( const void *a, const void *b, void *s )
{
idnode_t *ina = *(idnode_t**)a;
idnode_t *inb = *(idnode_t**)b;
idnode_sort_t *sort = s;
const property_t *p = idnode_find_prop(ina, sort->key);
switch (p->type) {
case PT_STR:
{
const char *stra = idnode_get_str(ina, sort->key);
const char *strb = idnode_get_str(inb, sort->key);
if (sort->dir == IS_ASC)
return strcmp(stra ?: "", strb ?: "");
else
return strcmp(strb ?: "", stra ?: "");
}
break;
case PT_INT:
case PT_U16:
case PT_U32:
{
uint32_t u32a = 0, u32b = 0;
idnode_get_u32(ina, sort->key, &u32a);
idnode_get_u32(inb, sort->key, &u32b);
if (sort->dir == IS_ASC)
return u32a - u32b;
else
return u32b - u32a;
}
break;
case PT_BOOL:
// TODO
break;
}
return 0;
}
int
idnode_filter
( idnode_t *in, idnode_filter_t *filter )
{
idnode_filter_ele_t *f;
LIST_FOREACH(f, filter, link) {
if (f->type == IF_STR) {
const char *str;
if (!(str = idnode_get_str(in, f->key)))
return 1;
switch(f->comp) {
case IC_IN:
if (strstr(str, f->u.s) == NULL)
return 1;
break;
case IC_EQ:
if (strcmp(str, f->u.s) != 0)
return 1;
case IC_LT:
if (strcmp(str, f->u.s) > 0)
return 1;
break;
case IC_GT:
if (strcmp(str, f->u.s) < 0)
return 1;
break;
case IC_RE:
break; // TODO: not yet supported
}
} else if (f->type == IF_NUM || f->type == IF_BOOL) {
uint32_t u32;
int64_t a, b;
if (idnode_get_u32(in, f->key, &u32))
return 1;
a = u32;
b = (f->type == IF_NUM) ? f->u.n : f->u.b;
switch (f->comp) {
case IC_IN:
case IC_RE:
break; // Note: invalid
case IC_EQ:
if (a != b)
return 1;
break;
case IC_LT:
if (a > b)
return 1;
break;
case IC_GT:
if (a < b)
return 1;
break;
}
}
}
return 0;
}
void
idnode_filter_add_str
( idnode_filter_t *filt, const char *key, const char *val, int comp )
{
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
ele->key = strdup(key);
ele->type = IF_STR;
ele->comp = comp;
ele->u.s = strdup(val);
LIST_INSERT_HEAD(filt, ele, link);
}
void
idnode_filter_add_num
( idnode_filter_t *filt, const char *key, int64_t val, int comp )
{
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
ele->key = strdup(key);
ele->type = IF_NUM;
ele->comp = comp;
ele->u.n = val;
LIST_INSERT_HEAD(filt, ele, link);
}
void
idnode_filter_add_bool
( idnode_filter_t *filt, const char *key, int val, int comp )
{
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
ele->key = strdup(key);
ele->type = IF_BOOL;
ele->comp = comp;
ele->u.b = val;
LIST_INSERT_HEAD(filt, ele, link);
}
void
idnode_filter_clear
( idnode_filter_t *filt )
{
idnode_filter_ele_t *ele;
while ((ele = LIST_FIRST(filt))) {
LIST_REMOVE(ele, link);
if (ele->type == IF_STR)
free(ele->u.s);
free(ele);
}
}
void
idnode_set_add
( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt )
{
if (filt && idnode_filter(in, filt))
return;
/* Allocate more space */
if (is->is_alloc == is->is_count) {
is->is_alloc = MAX(100, is->is_alloc * 2);
is->is_array = realloc(is->is_array, is->is_alloc * sizeof(idnode_t*));
}
is->is_array[is->is_count++] = in;
}
void
idnode_set_sort
( idnode_set_t *is, idnode_sort_t *sort )
{
qsort_r(is->is_array, is->is_count, sizeof(idnode_t*), idnode_cmp_sort, sort);
}

View file

@ -25,6 +25,46 @@ typedef struct idnode {
const idclass_t *in_class;
} idnode_t;
typedef struct idnode_sort {
const char *key;
enum {
IS_ASC,
IS_DSC
} dir;
} idnode_sort_t;
typedef struct idnode_filter_ele
{
LIST_ENTRY(idnode_filter_ele) link;
char *key;
enum {
IF_STR,
IF_NUM,
IF_BOOL
} type;
union {
int b;
char *s;
int64_t n;
} u;
enum {
IC_EQ, // Equals
IC_LT, // LT
IC_GT, // GT
IC_IN, // contains (STR only)
IC_RE, // regexp (STR only)
} comp;
} idnode_filter_ele_t;
typedef LIST_HEAD(,idnode_filter_ele) idnode_filter_t;
typedef struct idnode_set
{
idnode_t **is_array;
size_t is_alloc;
size_t is_count;
} idnode_set_t;
void idnode_init(void);
int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
@ -57,3 +97,21 @@ void idnode_load ( idnode_t *self, htsmsg_t *m );
const char *idnode_get_str ( idnode_t *self, const char *key );
int idnode_get_u32(idnode_t *self, const char *key, uint32_t *u32);
int idnode_get_bool(idnode_t *self, const char *key, int *b);
/*
* Set processing
*/
void idnode_filter_add_str
(idnode_filter_t *f, const char *k, const char *v, int t);
void idnode_filter_add_num
(idnode_filter_t *f, const char *k, int64_t s64, int t);
void idnode_filter_add_bool
(idnode_filter_t *f, const char *k, int b, int t);
void idnode_filter_clear
(idnode_filter_t *f);
int idnode_filter
( idnode_t *in, idnode_filter_t *filt );
void idnode_set_add
( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt );
void idnode_set_sort ( idnode_set_t *is, idnode_sort_t *s );