/* * $Id$ * * Copyright (C) 2001-2003 FhG FOKUS * Copyright (C) 2005 Voice Sistem SRL (Voice-System.RO) * * This file is part of SIP Express Router. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * * This file 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * For any questions about this software and its license, please contact * Voice Sistem at following e-mail address: * office@voice-sistem.ro * * History: * ------- * 2005-01-25 first tree version (ramona) */ #include #include #include #include #include "../../dprint.h" #include "../../mem/mem.h" #include "pdtree.h" pdt_tree_t* pdt_init_tree() { pdt_tree_t *pt = NULL; pt = (pdt_tree_t*)pkg_malloc(sizeof(pdt_tree_t)); if(pt==NULL) { LOG(L_ERR, "pdt_init_tree:ERROR: no more pkg memory\n"); return NULL; } memset(pt, 0, sizeof(pdt_tree_t)); pt->head = (pdt_node_t*)pkg_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t)); if(pt->head == NULL) { pkg_free(pt); LOG(L_ERR, "pdt_init_tree:ERROR: no more pkg mem\n"); return NULL; } memset(pt->head, 0, PDT_NODE_SIZE*sizeof(pdt_node_t)); return pt; } int pdt_add_to_tree(pdt_tree_t *pt, str *sp, str *sd) { int l; pdt_node_t *itn, *itn0; if(pt==NULL || sp==NULL || sp->s==NULL || sd==NULL || sd->s==NULL) { LOG(L_ERR, "pdt_add_to_tree:ERROR: bad parameters\n"); return -1; } if(sp->len>=PDT_MAX_DEPTH) { LOG(L_ERR, "pdt_add_to_tree:ERROR: max prefix len exceeded\n"); return -1; } l = 0; itn0 = pt->head; itn = itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child; while(l < sp->len-1) { if(sp->s[l] < '0' || sp->s[l] > '9') { LOG(L_ERR, "pdt_add_to_tree:ERROR: invalid char %d in prefix [%c (0x%x)]\n", l, sp->s[l], sp->s[l]); return -1; } if(itn == NULL) { itn = (pdt_node_t*)pkg_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t)); if(itn == NULL) { LOG(L_ERR, "pdt_add_to_tree: no more pkg mem\n"); return -1; } memset(itn, 0, PDT_NODE_SIZE*sizeof(pdt_node_t)); itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child = itn; } l++; itn0 = itn; itn = itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child; } if(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s!=NULL) { LOG(L_ERR, "pdt_add_to_tree:ERROR: prefix alredy allocated\n"); return -1; } itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s = (char*)pkg_malloc((sd->len+1)*sizeof(char)); if(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s==NULL) { LOG(L_ERR, "pdt_add_to_tree:ERROR: no more pkg mem!\n"); return -1; } strncpy(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s, sd->s, sd->len); itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.len = sd->len; itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s[sd->len] = '\0'; return 0; } int pdt_remove_from_tree(pdt_tree_t *pt, str *sp) { int l; pdt_node_t *itn; if(pt==NULL || sp==NULL || sp->s==NULL || sp->s<=0) { LOG(L_ERR, "pdt_remove_from_tree:ERROR: bad parameters\n"); return -1; } l = 1; itn = pt->head; while(itn!=NULL && l < sp->len && l < PDT_MAX_DEPTH) { itn = itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].child; l++; } if(itn!=NULL && l==sp->len && itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s!=NULL) { DBG("pdt_remove_from_tree: deleting <%.*s>\n", itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.len, itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s); pkg_free(itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s); itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s = NULL; itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.len = 0; } /* todo: should free the node if no child and prefix inside */ return 0; } str* pdt_get_domain(pdt_tree_t *pt, str *sp, int *plen) { int l, len; pdt_node_t *itn; str *domain; if(pt==NULL || sp==NULL || sp->s==NULL) { LOG(L_ERR, "pdt_get_domain:ERROR: bad parameters\n"); return NULL; } l = len = 0; itn = pt->head; domain = NULL; while(itn!=NULL && l < sp->len && l < PDT_MAX_DEPTH) { if(itn[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s!=NULL) { domain = &itn[(sp->s[l]-'0')%PDT_NODE_SIZE].domain; len = l+1; } itn = itn[(sp->s[l]-'0')%PDT_NODE_SIZE].child; l++; } if(plen!=NULL) *plen = len; return domain; } void pdt_free_node(pdt_node_t *pn) { int i; if(pn==NULL) return; for(i=0; ihead); pkg_free(pt); pt = NULL; return; } int pdt_print_node(pdt_node_t *pn, char *code, int len) { int i; if(pn==NULL || code==NULL || len>=PDT_MAX_DEPTH) return 0; for(i=0; ihead, code_buf, len); }