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/data.c

227 lines
5.7 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/>.";
*
*/
#include <ydaemon/dataobject.h>
static long __cmp_uint8(const void *a, const void *b)
{
return *(uint8_t *)a - *(uint8_t *)b;
}
static long __cmp_cstr(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
dataobject_t *dotr_create(const char *name)
{
dataobject_t *dtr = malloc(sizeof(dataobject_t));
if(!dtr) return NULL;
else memset(dtr, 0, sizeof(dataobject_t));
/* init name, indexes etc ... */
strncpy(dtr->name, name, MAX_ITEM_NAME - sizeof(char));
list_init_head(&dtr->description);
usrtc_init(&dtr->id_index, USRTC_REDBLACK, MAX_ITEMS, __cmp_uint8);
usrtc_init(&dtr->name_index, USRTC_REDBLACK, MAX_ITEMS, __cmp_cstr);
return dtr;
}
int dotr_set_item(dataobject_t *dotr, uint8_t type, uint64_t len,
const char *name)
{
dataobject_item_t *ditem = malloc(sizeof(dataobject_item_t));
char *indexes = malloc(2*sizeof(item_idx_t));
item_idx_t *iidx, *nidx;
if(!ditem || !indexes) {
if(ditem) free(ditem);
if(indexes) free(indexes);
return ENOMEM;
} else {
iidx = (item_idx_t *)indexes;
nidx = (item_idx_t *)(indexes + sizeof(item_idx_t));
}
/* init items */
strncpy(ditem->name, name, MAX_ITEM_NAME - sizeof(char));
ditem->id = usrtc_count(&dotr->id_index);
ditem->type = type;
ditem->len = len;
list_init_node(&ditem->node);
iidx->key = &ditem->id;
iidx->dtr = ditem;
usrtc_node_init(&iidx->node, iidx);
nidx->key = ditem->name;
nidx->dtr = ditem;
usrtc_node_init(&nidx->node, nidx);
/* now insert all */
list_add2tail(&dotr->description, &ditem->node);
usrtc_insert(&dotr->id_index, &iidx->node, iidx->key);
usrtc_insert(&dotr->name_index, &nidx->node, nidx->key);
return 0;
}
void dotr_destroy(dataobject_t *dotr)
{
usrtc_t *tree = &dotr->id_index;
usrtc_node_t *node = NULL;
item_idx_t *idx;
list_node_t *iter, *save;
dataobject_item_t *ditem;
if(usrtc_count(tree)) { /* we can free only index, since it was allocated as one memory chunk */
for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
idx = (item_idx_t *)usrtc_node_getdata(node);
usrtc_delete(tree, node);
free(idx);
}
/* free description */
list_for_each_safe(&dotr->description, iter, save) {
ditem = container_of(iter, dataobject_item_t, node);
list_del(&ditem->node);
free(ditem);
}
}
free(dotr);
return;
}
uint8_t dotr_item_type(dataobject_t *obj, const char *name, uint64_t *len)
{
usrtc_node_t *node = usrtc_lookup(&obj->name_index, name);
item_idx_t *idxnode;
dataobject_item_t *dtr = NULL;
if(!node) { /* not found ! */
__failed:
*len = 0;
return 0;
}
idxnode = (item_idx_t *)usrtc_node_getdata(node);
if(!idxnode) goto __failed;
else dtr = idxnode->dtr;
if(!dtr) goto __failed;
*len = dtr->len;
return dtr->type;
}
char *dotr_item_nameptr(dataobject_t *obj, const char *name)
{
usrtc_node_t *node = usrtc_lookup(&obj->name_index, name);
item_idx_t *idxnode;
dataobject_item_t *dtr = NULL;
if(!node) /* not found ! */ return NULL;
idxnode = (item_idx_t *)usrtc_node_getdata(node);
if(!idxnode) return NULL;
else dtr = idxnode->dtr;
if(!dtr) return NULL;
return dtr->name;
}
int dotr_item_nameidx(dataobject_t *obj, const char *name)
{
usrtc_node_t *node = usrtc_lookup(&obj->name_index, name);
item_idx_t *idxnode;
dataobject_item_t *dtr = NULL;
if(!node) /* not found ! */ return -1;
idxnode = (item_idx_t *)usrtc_node_getdata(node);
if(!idxnode) return -1;
else dtr = idxnode->dtr;
if(!dtr) return -1;
return dtr->id;
}
static inline int __itemcmp(const dataobject_item_t *s1,
const dataobject_item_t *s2)
{
int r = 0;
if((r = strcmp(s1->name, s2->name))) return r;
if((r = s1->len - s2->len)) return r;
if((r = s1->type - s2->type)) return r;
return 0;
}
int dtocmp(const dataobject_t *src, const dataobject_t *dst)
{
int r = 0;
list_node_t *iter, *siter;
dataobject_item_t *ditem, *sitem;
usrtc_node_t *unode;
item_idx_t *iidx;
/* check name */
if((r = strcmp(src->name, dst->name))) return r;
/* check amount of items */
if((r = usrtc_count((usrtc_t *)&src->id_index) - usrtc_count((usrtc_t *)&dst->id_index)))
return r;
/* check items itself */
list_for_each_safe(&src->description, iter, siter) {
ditem = container_of(iter, dataobject_item_t, node);
if(!(unode = usrtc_lookup((usrtc_t *)&dst->id_index, (const void *)&ditem->id)))
return 100*ditem->id;
iidx = (item_idx_t *)usrtc_node_getdata(unode);
sitem = iidx->dtr;
if((r = __itemcmp(ditem, sitem))) return r*ditem->id;
}
return 0;
}
size_t dtolen(const dataobject_t *src)
{
size_t len = 0;
list_node_t *iter, *siter;
dataobject_item_t *ditem;
list_for_each_safe(&src->description, iter, siter) {
ditem = container_of(iter, dataobject_item_t, node);
len += ditem->len;
}
return len;
}