idnode: Add intsplit filtering (include double ops, too)

This commit is contained in:
Jaroslav Kysela 2014-09-11 19:49:19 +02:00
parent c073538e05
commit b8fa239354
4 changed files with 196 additions and 15 deletions

View file

@ -57,7 +57,7 @@ static void
api_idnode_grid_conf
( htsmsg_t *args, api_idnode_grid_conf_t *conf )
{
htsmsg_field_t *f;
htsmsg_field_t *f, *f2;
htsmsg_t *filter, *e;
const char *str;
@ -84,11 +84,20 @@ api_idnode_grid_conf
if ((v = htsmsg_get_str(e, "value")))
idnode_filter_add_str(&conf->filter, k, v, IC_RE);
} else if (!strcmp(t, "numeric")) {
uint32_t v;
if (!htsmsg_get_u32(e, "value", &v)) {
int t = str2val(htsmsg_get_str(e, "comparison") ?: "",
filtcmptab);
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t);
f2 = htsmsg_field_find(e, "value");
if (f2) {
int t = str2val(htsmsg_get_str(e, "comparison") ?: "", filtcmptab);
if (f2->hmf_type == HMF_DBL) {
double dbl;
if (!htsmsg_field_get_dbl(f2, &dbl))
idnode_filter_add_dbl(&conf->filter, k, dbl, t == -1 ? IC_EQ : t);
} else {
int64_t v;
int64_t intsplit = 0;
htsmsg_get_s64(e, "intsplit", &intsplit);
if (!htsmsg_field_get_s64(f2, &v))
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t, intsplit);
}
}
} else if (!strcmp(t, "boolean")) {
uint32_t v;

View file

@ -407,8 +407,54 @@ idnode_get_s64
case PT_S64:
*s64 = *(int64_t*)ptr;
return 0;
case PT_DBL:
*s64 = *(double*)ptr;
return 0;
case PT_TIME:
*s64 = *(time_t*)ptr;
return 0;
default:
break;
}
}
return 1;
}
/*
* Get field as double
*/
int
idnode_get_dbl
( idnode_t *self, const char *key, double *dbl )
{
const property_t *p = idnode_find_prop(self, key);
if (p->islist) return 1;
if (p) {
const void *ptr;
if (p->get)
ptr = p->get(self);
else
ptr = ((void*)self) + p->off;
switch (p->type) {
case PT_INT:
case PT_BOOL:
*dbl = *(int*)ptr;
return 0;
case PT_U16:
*dbl = *(uint16_t*)ptr;
return 0;
case PT_U32:
*dbl = *(uint32_t*)ptr;
return 0;
case PT_S64:
*dbl = *(int64_t*)ptr;
return 0;
case PT_DBL:
*dbl = *(double *)ptr;
return 0;
case PT_TIME:
*dbl = *(time_t*)ptr;
return 0;
default:
break;
}
@ -597,7 +643,16 @@ idnode_cmp_sort
}
break;
case PT_DBL:
// TODO
{
double dbla = 0, dblb = 0;
idnode_get_dbl(ina, sort->key, &dbla);
idnode_get_dbl(inb, sort->key, &dblb);
if (sort->dir == IS_ASC)
return dbla - dblb;
else
return dblb - dbla;
}
break;
case PT_TIME:
{
time_t ta = 0, tb = 0;
@ -617,6 +672,31 @@ idnode_cmp_sort
return 0;
}
static void
idnode_filter_init
( idnode_t *in, idnode_filter_t *filter )
{
idnode_filter_ele_t *f;
const property_t *p;
LIST_FOREACH(f, filter, link) {
if (f->type == IF_NUM) {
p = idnode_find_prop(in, f->key);
if (p) {
if (p->type == PT_U32 || p->type == PT_S64 ||
p->type == PT_TIME) {
int64_t v = f->u.n.n;
if (p->intsplit != f->u.n.intsplit) {
v = (v / (f->u.n.intsplit <= 0 ? 1 : 0)) * p->intsplit;
f->u.n.n = v;
}
}
}
}
f->checked = 1;
}
}
int
idnode_filter
( idnode_t *in, idnode_filter_t *filter )
@ -624,6 +704,8 @@ idnode_filter
idnode_filter_ele_t *f;
LIST_FOREACH(f, filter, link) {
if (!f->checked)
idnode_filter_init(in, filter);
if (f->type == IF_STR) {
const char *str;
str = idnode_get_display(in, idnode_find_prop(in, f->key));
@ -655,7 +737,29 @@ idnode_filter
int64_t a, b;
if (idnode_get_s64(in, f->key, &a))
return 1;
b = (f->type == IF_NUM) ? f->u.n : f->u.b;
b = (f->type == IF_NUM) ? f->u.n.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;
}
} else if (f->type == IF_DBL) {
double a, b;
if (idnode_get_dbl(in, f->key, &a))
return 1;
b = f->u.dbl;
switch (f->comp) {
case IC_IN:
case IC_RE:
@ -699,13 +803,26 @@ idnode_filter_add_str
void
idnode_filter_add_num
( idnode_filter_t *filt, const char *key, int64_t val, int comp )
( idnode_filter_t *filt, const char *key, int64_t val, int comp, int64_t intsplit )
{
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;
ele->u.n.n = val;
ele->u.n.intsplit = intsplit;
LIST_INSERT_HEAD(filt, ele, link);
}
void
idnode_filter_add_dbl
( idnode_filter_t *filt, const char *key, double dbl, int comp )
{
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
ele->key = strdup(key);
ele->type = IF_DBL;
ele->comp = comp;
ele->u.dbl = dbl;
LIST_INSERT_HEAD(filt, ele, link);
}

View file

@ -100,16 +100,22 @@ typedef struct idnode_filter_ele
{
LIST_ENTRY(idnode_filter_ele) link; ///< List link
int checked;
char *key; ///< Filter key
enum {
IF_STR,
IF_NUM,
IF_DBL,
IF_BOOL
} type; ///< Filter type
union {
int b;
char *s;
int64_t n;
struct {
int64_t n;
int64_t intsplit;
} n;
double dbl;
regex_t re;
} u; ///< Filter data
enum {
@ -175,13 +181,16 @@ idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write)
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_s64 (idnode_t *self, const char *key, int64_t *s64);
int idnode_get_dbl (idnode_t *self, const char *key, double *dbl);
int idnode_get_bool(idnode_t *self, const char *key, int *b);
int idnode_get_time(idnode_t *self, const char *key, time_t *tm);
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);
(idnode_filter_t *f, const char *k, int64_t s64, int t, int64_t intsplit);
void idnode_filter_add_dbl
(idnode_filter_t *f, const char *k, double dbl, int t);
void idnode_filter_add_bool
(idnode_filter_t *f, const char *k, int b, int t);
void idnode_filter_clear

View file

@ -107,6 +107,44 @@ tvheadend.idnode_enum_store = function(f)
return store;
};
Ext.ux.grid.filter.IntsplitFilter = Ext.extend(Ext.ux.grid.filter.NumericFilter, {
fieldCls : Ext.form.TextField,
constructor: function(conf) {
this.intsplit = conf.intsplit;
if (!conf.fields)
conf.fields = {
gt: { maskRe: /[0-9\.]/ },
lt: { maskRe: /[0-9\.]/ },
eq: { maskRe: /[0-9\.]/ }
};
Ext.ux.grid.filter.IntsplitFilter.superclass.constructor.call(this, conf);
},
getSerialArgs: function () {
var key,
args = [],
values = this.menu.getValue();
for (key in values) {
var s = values[key].toString().split('.');
var v = 0;
if (s.length > 0)
v = parseInt(s[0]) * this.intsplit;
if (s.length > 1)
v += parseInt(s[1]);
args.push({
type: 'numeric',
comparison: key,
value: v,
intsplit: this.intsplit
});
}
return args;
}
});
tvheadend.IdNodeField = function(conf)
{
/*
@ -151,7 +189,10 @@ tvheadend.IdNodeField = function(conf)
var cfg = conf && this.id in conf ? conf[this.id] : {};
var w = 300;
var ftype = 'string';
if (this.type === 'int' || this.type === 'u32' ||
if (this.intsplit) {
ftype = 'intsplit';
w = 80;
} else if (this.type === 'int' || this.type === 'u32' ||
this.type === 'u16' || this.type === 's64' ||
this.type === 'dbl') {
ftype = 'numeric';
@ -180,7 +221,8 @@ tvheadend.IdNodeField = function(conf)
hidden: this.hidden,
filter: {
type: ftype,
dataIndex: this.id
dataIndex: this.id,
intsplit: this.intsplit
}
};
@ -307,7 +349,11 @@ tvheadend.IdNodeField = function(conf)
case 's32':
case 'dbl':
case 'time':
cons = Ext.form.NumberField;
if (this.intsplit) {
c['maskRe'] = /[0-9\.]/;
cons = Ext.form.TextField;
} else
cons = Ext.form.NumberField;
break;
/* 'str' and 'perm' */