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:
parent
75151722f6
commit
1ed3627e77
2 changed files with 234 additions and 0 deletions
176
src/idnode.c
176
src/idnode.c
|
@ -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);
|
||||
}
|
||||
|
|
58
src/idnode.h
58
src/idnode.h
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue