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

185 lines
4.4 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <tdata/usrtc.h>
#include <sexpr/sexp.h>
#include <ydaemon/ydaemon.h>
static long __cmp_cstrs(const void *a, const void *b)
{
return (long)(strcmp((const char *)a, (const char *)b));
}
static void __scm_func_tree_init(scm_function_tree_t *pt, void *priv)
{
usrtc_t *foost = (usrtc_t *)&(pt->functions);
usrtc_init(foost, USRTC_SPLAY, MAX_SCM_FUNCTIONS, __cmp_cstrs);
return;
}
static scm_function_tree_t *__scm_func_tree_alloc(void *priv)
{
scm_function_tree_t *t = malloc(sizeof(scm_function_tree_t));
if(!t) goto __fail;
else __scm_func_tree_init(t, priv);
__fail:
return t;
}
void scm_func_tree_free(scm_function_tree_t *pt)
{
usrtc_t *ftree = &(pt->functions);
usrtc_node_t *node = NULL;
scm_function_t *sf;
if(usrtc_count(ftree)) {
for(node = usrtc_first(ftree); node != NULL; node = usrtc_first(ftree)) {
sf = (scm_function_t *)usrtc_node_getdata(node);
/* remove from the tree first */
usrtc_delete(ftree, node);
/* free all */
free(sf->name);
free(sf);
}
}
free(pt);
return;
}
/* external API */
int scm_func_tree_init(scm_function_tree_t **pt, void *priv)
{
scm_function_tree_t *nt = __scm_func_tree_alloc(priv);
if(!nt) return ENOENT;
else *pt = nt;
return 0;
}
int scm_func_tree_insert(yd_context_t *zdx, const char *name,
scret_t (*call)(yd_context_t *, sexp_t *, void *),
void *priv)
{
scm_function_tree_t *pt = zdx->func;
usrtc_t *ftree = &(pt->functions);
scm_function_t *n_func = malloc(sizeof(scm_function_t));
usrtc_node_t *node = NULL;
int e = 0;
/* just check existence */
if(!n_func) return ENOMEM;
if(usrtc_count(ftree) >= MAX_SCM_FUNCTIONS) {
e = ENOMEM;
goto __end;
}
if((node = usrtc_lookup(ftree, (const void *)name))) {
e = EEXIST;
goto __end;
}
/* init structure */
if(!(n_func->name = strdup(name))) {
free(n_func);
return ENOMEM;
}
n_func->call = call;
n_func->priv = priv;
node = &(n_func->node);
usrtc_node_init(node, n_func);
/* insert to the tree */
usrtc_insert(ftree, node, (const void *)name);
__end:
if(e) free(n_func);
return e;
}
int scm_func_tree_insert_t(yd_context_t *zdx, scm_function_t *f)
{
scm_function_tree_t *pt = zdx->func;
usrtc_t *ftree = &(pt->functions);
usrtc_node_t *node = usrtc_lookup(ftree, (const void *)f->name);
if(node) return EEXIST;
else node = &(f->node);
if(usrtc_count(ftree) >= MAX_SCM_FUNCTIONS) return ENOMEM;
usrtc_node_init(node, f);
usrtc_insert(ftree, node, (const void *)f->name);
return 0;
}
scret_t scm_func_tree_call(yd_context_t *zdx, void *cnf, sexp_t *sx,
char *name)
{
scm_function_tree_t *pt = zdx->func;
usrtc_t *ftree = &(pt->functions);
usrtc_node_t *node = usrtc_lookup(ftree, (const void *)name);
scm_function_t *fn;
if(!node) {
scret_t rets;
RETURN_SRET_SERR(rets, ENOENT);
} else fn = (scm_function_t *)usrtc_node_getdata(node);
cnf = zdx;
return fn->call(cnf, sx, fn->priv);
}
int scm_func_tree_delete(yd_context_t *zdx, char *name)
{
scm_function_tree_t *pt = zdx->func;
usrtc_t *ftree = &(pt->functions);
usrtc_node_t *node = usrtc_lookup(ftree, (const void *)name);
scm_function_t *fn;
if(!node) return ENOENT;
else fn = (scm_function_t *)usrtc_node_getdata(node);
/* remove from tree first */
usrtc_delete(ftree, node);
/* free */
free(fn->name);
free(fn);
return 0;
}