/* * 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 #include #include #include #include #include #include #include #include #include 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; }