You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libsxmp/ydaemon/filter.c

220 lines
5.6 KiB
C

/*
* Yet another daemon library especially designed to be used
* with libsxmp based daemons.
*
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
*
* libsxmp is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libsxmp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.";
*
*/
#define DMUX_USE 1
#include <ydaemon/dataobject.h>
yd_filter_t *yd_filter_create(domx_t *refobj)
{
yd_filter_t *f = malloc(sizeof(yd_filter_t));
if(f) {
f->domx = refobj;
list_init_head(&f->filter);
}
return f;
}
void yd_filter_destroy(yd_filter_t *f)
{
list_head_t *lhead;
list_node_t *iter, *siter, *liter, *lsiter;
yd_filter_item_t *filter_item;
yd_inlist_item_t *inl_item;
dataobject_t *obj;
uint64_t len;
uint8_t type;
if(!f) return;
else {
lhead = &f->filter;
obj = f->domx->dox;
}
list_for_each_safe(lhead, iter, siter) {
filter_item = container_of(iter, yd_filter_item_t, node);
type = dotr_item_type(obj, filter_item->name, &len);
if(type && len) {
switch(filter_item->ftype) {
case YDEQUAL:
case YDNOTEQUAL:
if(type == CSTR || type == TBLOB) free(filter_item->cstr);
break;
case YDINLIST:
/* we must destroy the list */
list_for_each_safe(filter_item->inlist, liter, lsiter) {
inl_item = container_of(liter, yd_inlist_item_t, node);
if(type == CSTR || type == TBLOB) free(inl_item->dta);
list_del(&inl_item->node);
free(inl_item);
}
free(filter_item->inlist);
break;
default: break; /* nothing to do */
}
}
/* free struct itself */
list_del(&filter_item->node);
free(filter_item);
}
free(f);
return;
}
static yd_filter_item_t *__alloc_init_fitem(filt_t ftype, char *name)
{
yd_filter_item_t *fitem = NULL;
if(name && (fitem = malloc(sizeof(yd_filter_item_t)))) {
memset(fitem, 0, sizeof(yd_filter_item_t));
fitem->name = name;
fitem->ftype = ftype;
list_init_node(&fitem->node);
}
return fitem;
}
int yd_filter_add_sf(yd_filter_t *f, const char *name, filt_t ftype,
uint64_t vf, uint64_t vc)
{
yd_filter_item_t *fitem;
dataobject_t *obj;
uint64_t len;
uint8_t type;
if(!f || !name) return EINVAL;
/* lookup for existing entry and check it */
obj = f->domx->dox;
type = dotr_item_type(obj, name, &len);
if(!type && !len) return EINVAL;
/* check validity */
if((type < CSTR) && (len > tltable[type].len)) return EINVAL; /* we cannot filter by array here */
if(type > S64) return EINVAL; /* we're adding a simple filter rule */
if(ftype == YDINLIST) return EINVAL; /* we're not working with that in this function */
fitem = __alloc_init_fitem(ftype, dotr_item_nameptr(obj, name));
if(!fitem) return ENOMEM;
fitem->vf = vf;
if(ftype == YDINLIST) fitem->vc = vc;
/* add this entry */
list_add2tail(&f->filter, &fitem->node);
return 0;
}
int yd_filter_add_str(yd_filter_t *f, const char *name, const char *value, int eq)
{
yd_filter_item_t *fitem;
dataobject_t *obj;
filt_t ftype;
uint64_t len;
uint8_t type;
if(!f || !name) return EINVAL;
/* lookup for existing entry and check it */
obj = f->domx->dox;
type = dotr_item_type(obj, name, &len);
if(!type && !len) return EINVAL;
if(type != CSTR) return EINVAL; /* cannot do it, invalid */
if(!eq) ftype = YDNOTEQUAL;
else ftype = YDEQUAL;
fitem = __alloc_init_fitem(ftype, dotr_item_nameptr(obj, name));
if(!fitem) return ENOMEM;
if(!(fitem->cstr = strndup(value, len - sizeof(char)))) {
free(fitem);
return ENOMEM;
}
/* add this entry */
list_add2tail(&f->filter, &fitem->node);
return 0;
}
int yd_filter_add_inlist(yd_filter_t *f, const char *name, int length, void **array)
{
yd_filter_item_t *fitem;
yd_inlist_item_t *list_item;
dataobject_t *obj;
list_node_t *iter, *siter;
uint64_t len;
int i;
uint8_t type;
if(!f || !name) return EINVAL;
if(!length || !array) return EINVAL;
/* lookup for existing entry and check it */
obj = f->domx->dox;
type = dotr_item_type(obj, name, &len);
if(!type && !len) return EINVAL;
fitem = __alloc_init_fitem(YDINLIST, dotr_item_nameptr(obj, name));
if(!fitem) return ENOMEM;
if(!(fitem->inlist = malloc(sizeof(list_head_t)))) {
__enomem:
free(fitem);
return ENOMEM;
}
/* fill the list */
for(i = 0; i < length; i++) {
if(!(list_item = malloc(sizeof(yd_inlist_item_t)))) {
__deep_enomem:
list_for_each_safe(fitem->inlist, iter, siter) {
list_item = container_of(iter, yd_inlist_item_t, node);
if(type == CSTR || type == TBLOB) free(list_item->dta);
list_del(&list_item->node);
free(list_item);
}
/* free the list */
free(fitem->inlist);
goto __enomem;
}
if(type < CSTR) list_item->val = *(uint64_t *)array[i];
else if(!(list_item->dta = strndup((const char *)array[i], len - sizeof(char)))) goto __deep_enomem;
list_init_node(&list_item->node);
list_add2tail(fitem->inlist, &list_item->node);
}
/* add this entry */
list_add2tail(&f->filter, &fitem->node);
return 0;
}