/* * Yet another daemon library especially designed to be used * with libsxmp based daemons. * * (c) Alexander Vdolainen 2016 * * 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 ."; * */ #include 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; }