2
0

pdtree.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG FOKUS
  5. * Copyright (C) 2005 Voice Sistem SRL (Voice-System.RO)
  6. *
  7. * This file is part of SIP Express Router.
  8. *
  9. * This file is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. *
  15. * This file is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * For any questions about this software and its license, please contact
  25. * Voice Sistem at following e-mail address:
  26. * [email protected]
  27. *
  28. * History:
  29. * -------
  30. * 2005-01-25 first tree version (ramona)
  31. */
  32. #include <stdio.h>
  33. #include <unistd.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "../../dprint.h"
  37. #include "../../mem/mem.h"
  38. #include "pdtree.h"
  39. pdt_tree_t* pdt_init_tree()
  40. {
  41. pdt_tree_t *pt = NULL;
  42. pt = (pdt_tree_t*)pkg_malloc(sizeof(pdt_tree_t));
  43. if(pt==NULL)
  44. {
  45. LOG(L_ERR, "pdt_init_tree:ERROR: no more pkg memory\n");
  46. return NULL;
  47. }
  48. memset(pt, 0, sizeof(pdt_tree_t));
  49. pt->head = (pdt_node_t*)pkg_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t));
  50. if(pt->head == NULL)
  51. {
  52. pkg_free(pt);
  53. LOG(L_ERR, "pdt_init_tree:ERROR: no more pkg mem\n");
  54. return NULL;
  55. }
  56. memset(pt->head, 0, PDT_NODE_SIZE*sizeof(pdt_node_t));
  57. return pt;
  58. }
  59. int pdt_add_to_tree(pdt_tree_t *pt, str *sp, str *sd)
  60. {
  61. int l;
  62. pdt_node_t *itn, *itn0;
  63. if(pt==NULL || sp==NULL || sp->s==NULL
  64. || sd==NULL || sd->s==NULL)
  65. {
  66. LOG(L_ERR, "pdt_add_to_tree:ERROR: bad parameters\n");
  67. return -1;
  68. }
  69. if(sp->len>=PDT_MAX_DEPTH)
  70. {
  71. LOG(L_ERR, "pdt_add_to_tree:ERROR: max prefix len exceeded\n");
  72. return -1;
  73. }
  74. l = 0;
  75. itn0 = pt->head;
  76. itn = itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child;
  77. while(l < sp->len-1)
  78. {
  79. if(sp->s[l] < '0' || sp->s[l] > '9')
  80. {
  81. LOG(L_ERR,
  82. "pdt_add_to_tree:ERROR: invalid char %d in prefix [%c (0x%x)]\n",
  83. l, sp->s[l], sp->s[l]);
  84. return -1;
  85. }
  86. if(itn == NULL)
  87. {
  88. itn = (pdt_node_t*)pkg_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t));
  89. if(itn == NULL)
  90. {
  91. LOG(L_ERR, "pdt_add_to_tree: no more pkg mem\n");
  92. return -1;
  93. }
  94. memset(itn, 0, PDT_NODE_SIZE*sizeof(pdt_node_t));
  95. itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child = itn;
  96. }
  97. l++;
  98. itn0 = itn;
  99. itn = itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].child;
  100. }
  101. if(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s!=NULL)
  102. {
  103. LOG(L_ERR, "pdt_add_to_tree:ERROR: prefix alredy allocated\n");
  104. return -1;
  105. }
  106. itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s
  107. = (char*)pkg_malloc((sd->len+1)*sizeof(char));
  108. if(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s==NULL)
  109. {
  110. LOG(L_ERR, "pdt_add_to_tree:ERROR: no more pkg mem!\n");
  111. return -1;
  112. }
  113. strncpy(itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s,
  114. sd->s, sd->len);
  115. itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.len = sd->len;
  116. itn0[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s[sd->len] = '\0';
  117. return 0;
  118. }
  119. int pdt_remove_from_tree(pdt_tree_t *pt, str *sp)
  120. {
  121. int l;
  122. pdt_node_t *itn;
  123. if(pt==NULL || sp==NULL || sp->s==NULL || sp->s<=0)
  124. {
  125. LOG(L_ERR, "pdt_remove_from_tree:ERROR: bad parameters\n");
  126. return -1;
  127. }
  128. l = 1;
  129. itn = pt->head;
  130. while(itn!=NULL && l < sp->len && l < PDT_MAX_DEPTH)
  131. {
  132. itn = itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].child;
  133. l++;
  134. }
  135. if(itn!=NULL && l==sp->len
  136. && itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s!=NULL)
  137. {
  138. DBG("pdt_remove_from_tree: deleting <%.*s>\n",
  139. itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.len,
  140. itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s);
  141. pkg_free(itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s);
  142. itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.s = NULL;
  143. itn[(sp->s[l-1]-'0')%PDT_NODE_SIZE].domain.len = 0;
  144. }
  145. /* todo: should free the node if no child and prefix inside */
  146. return 0;
  147. }
  148. str* pdt_get_domain(pdt_tree_t *pt, str *sp, int *plen)
  149. {
  150. int l, len;
  151. pdt_node_t *itn;
  152. str *domain;
  153. if(pt==NULL || sp==NULL || sp->s==NULL)
  154. {
  155. LOG(L_ERR, "pdt_get_domain:ERROR: bad parameters\n");
  156. return NULL;
  157. }
  158. l = len = 0;
  159. itn = pt->head;
  160. domain = NULL;
  161. while(itn!=NULL && l < sp->len && l < PDT_MAX_DEPTH)
  162. {
  163. if(itn[(sp->s[l]-'0')%PDT_NODE_SIZE].domain.s!=NULL)
  164. {
  165. domain = &itn[(sp->s[l]-'0')%PDT_NODE_SIZE].domain;
  166. len = l+1;
  167. }
  168. itn = itn[(sp->s[l]-'0')%PDT_NODE_SIZE].child;
  169. l++;
  170. }
  171. if(plen!=NULL)
  172. *plen = len;
  173. return domain;
  174. }
  175. void pdt_free_node(pdt_node_t *pn)
  176. {
  177. int i;
  178. if(pn==NULL)
  179. return;
  180. for(i=0; i<PDT_NODE_SIZE; i++)
  181. {
  182. if(pn[i].domain.s!=NULL)
  183. {
  184. pkg_free(pn[i].domain.s);
  185. pn[i].domain.s = NULL;
  186. pn[i].domain.len = 0;
  187. }
  188. pdt_free_node(pn[i].child);
  189. pn[i].child = NULL;
  190. }
  191. pkg_free(pn);
  192. pn = NULL;
  193. return;
  194. }
  195. void pdt_free_tree(pdt_tree_t *pt)
  196. {
  197. if(pt == NULL)
  198. {
  199. LOG(L_INFO, "pdt_free_tree: bad parameters\n");
  200. return;
  201. }
  202. pdt_free_node(pt->head);
  203. pkg_free(pt);
  204. pt = NULL;
  205. return;
  206. }
  207. int pdt_print_node(pdt_node_t *pn, char *code, int len)
  208. {
  209. int i;
  210. if(pn==NULL || code==NULL || len>=PDT_MAX_DEPTH)
  211. return 0;
  212. for(i=0; i<PDT_NODE_SIZE; i++)
  213. {
  214. code[len] = '0' + (char)i;
  215. if(pn[i].domain.s!=NULL)
  216. DBG("pdt_print_node: [%.*s] [%.*s]\n",
  217. len+1, code, pn[i].domain.len, pn[i].domain.s);
  218. pdt_print_node(pn[i].child, code, len+1);
  219. }
  220. return 0;
  221. }
  222. int pdt_print_tree(pdt_tree_t *pt)
  223. {
  224. static char code_buf[PDT_MAX_DEPTH+1];
  225. int len;
  226. if(pt == NULL)
  227. {
  228. LOG(L_ERR, "pdt_remove_from_tree:ERROR: bad parameters\n");
  229. return -1;
  230. }
  231. len = 0;
  232. return pdt_print_node(pt->head, code_buf, len);
  233. }