00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00040 #include "dtrie.h"
00041
00042 #include "../../dprint.h"
00043 #include "../../mem/shm_mem.h"
00044 #include "../../mem/mem.h"
00045
00046
00047 struct dtrie_node_t *dtrie_init(const unsigned int branches)
00048 {
00049 struct dtrie_node_t *root;
00050
00051 root = shm_malloc(sizeof(struct dtrie_node_t));
00052 if (root == NULL) {
00053 SHM_MEM_ERROR;
00054 return NULL;
00055 }
00056 LM_DBG("allocate %lu bytes for root at %p\n",
00057 (long unsigned)sizeof(struct dtrie_node_t), root);
00058 memset(root, 0, sizeof(struct dtrie_node_t));
00059
00060 root->child = shm_malloc(sizeof(struct dtrie_node_t *) * branches);
00061 if (root->child == NULL) {
00062 shm_free(root);
00063 SHM_MEM_ERROR;
00064 return NULL;
00065 }
00066 LM_DBG("allocate %lu bytes for %d root children pointer at %p\n",
00067 (long unsigned)sizeof(struct dtrie_node_t *) * branches,
00068 branches, root->child);
00069 memset(root->child, 0, sizeof(struct dtrie_node_t *) * branches);
00070
00071 return root;
00072 }
00073
00074
00075 void dtrie_delete(struct dtrie_node_t *root, struct dtrie_node_t *node,
00076 dt_delete_func_t delete_payload, const unsigned int branches)
00077 {
00078 unsigned int i;
00079 if (node==NULL) return;
00080
00081 for (i=0; i<branches; i++) {
00082 dtrie_delete(root, node->child[i], delete_payload, branches);
00083 node->child[i] = NULL;
00084 }
00085
00086 if (delete_payload) {
00087 delete_payload(node->data);
00088 }
00089
00090 node->data = NULL;
00091
00092 if (node != root) {
00093 LM_DBG("free node at %p\n", node);
00094 shm_free(node->child);
00095 node->child = NULL;
00096 shm_free(node);
00097 }
00098 }
00099
00100
00101 void dtrie_destroy(struct dtrie_node_t **root, dt_delete_func_t delete_payload, const unsigned int branches)
00102 {
00103 if ((root!=NULL) && (*root!=NULL)) {
00104 dtrie_delete(*root, *root, delete_payload, branches);
00105 LM_DBG("free root at %p\n", root);
00106 shm_free((*root)->child);
00107 shm_free(*root);
00108 *root = NULL;
00109 }
00110 }
00111
00112
00113 void dtrie_clear(struct dtrie_node_t *root, dt_delete_func_t delete_payload,
00114 const unsigned int branches)
00115 {
00116 dtrie_delete(root, root, delete_payload, branches);
00117 }
00118
00119
00120 int dtrie_insert(struct dtrie_node_t *root, const char *number, const unsigned int numberlen,
00121 void *data, const unsigned int branches)
00122 {
00123 struct dtrie_node_t *node = root;
00124 unsigned char digit, i=0;
00125
00126 while (i<numberlen) {
00127 if (branches==10) {
00128 digit = number[i] - '0';
00129 if (digit>9) {
00130 LM_ERR("cannot insert non-numerical character\n");
00131 return -1;
00132 }
00133 } else {
00134 digit = number[i];
00135 if (digit>127) {
00136 LM_ERR("cannot insert extended ascii character\n");
00137 return -1;
00138 }
00139 }
00140
00141 if (node->child[digit] == NULL) {
00142 node->child[digit] = shm_malloc(sizeof(struct dtrie_node_t));
00143 if(node->child[digit] == NULL ){
00144 SHM_MEM_ERROR;
00145 return -1;
00146 }
00147
00148 LM_DBG("allocate %lu bytes for node at %p\n", (long unsigned)sizeof(struct dtrie_node_t), node->child[digit]);
00149 memset(node->child[digit], 0, sizeof(struct dtrie_node_t));
00150
00151 node->child[digit]->child = shm_malloc(sizeof(struct dtrie_node_t *) * branches);
00152 if(node->child[digit]->child == NULL){
00153 SHM_MEM_ERROR;
00154 shm_free(node->child[digit]);
00155 return -1;
00156 }
00157 LM_DBG("allocate %lu bytes for %d root children pointer at %p\n",
00158 (long unsigned)sizeof(struct dtrie_node_t *) * branches,
00159 branches, node->child[digit]->child);
00160 memset(node->child[digit]->child, 0, sizeof(struct dtrie_node_t *) * branches);
00161 }
00162 node = node->child[digit];
00163 i++;
00164 }
00165 node->data = data;
00166 return 0;
00167 }
00168
00169
00170 unsigned int dtrie_size(const struct dtrie_node_t *root, const unsigned int branches)
00171 {
00172 unsigned int i, sum = 0;
00173
00174 if (root == NULL) return 0;
00175
00176 for (i=0; i<branches; i++) {
00177 sum += dtrie_size(root->child[i], branches);
00178 }
00179
00180 return sum+1;
00181 }
00182
00183
00184 unsigned int dtrie_loaded_nodes(const struct dtrie_node_t *root, const unsigned int branches)
00185 {
00186 unsigned int i, sum = 0;
00187
00188 if (root == NULL) return 0;
00189
00190 for (i=0; i<branches; i++) {
00191 sum += dtrie_loaded_nodes(root->child[i], branches);
00192 }
00193
00194 if (root->data != NULL) sum++;
00195
00196 return sum;
00197 }
00198
00199
00200 unsigned int dtrie_leaves(const struct dtrie_node_t *root, const unsigned int branches)
00201 {
00202 unsigned int i, sum = 0, leaf = 1;
00203
00204 for (i=0; i<branches; i++) {
00205 if (root->child[i]) {
00206 sum += dtrie_leaves(root->child[i], branches);
00207 leaf = 0;
00208 }
00209 }
00210
00211 return sum+leaf;
00212 }
00213
00214
00215 void **dtrie_longest_match(struct dtrie_node_t *root, const char *number,
00216 const unsigned int numberlen, int *nmatchptr, const unsigned int branches)
00217 {
00218 struct dtrie_node_t *node = root;
00219 unsigned char digit, i = 0;
00220 void **ret = NULL;
00221
00222 if (nmatchptr) *nmatchptr=-1;
00223 if (node->data != NULL) {
00224 if (nmatchptr) *nmatchptr=0;
00225 ret = &node->data;
00226 }
00227 while (i<numberlen) {
00228 if (branches==10) {
00229 digit = number[i] - '0';
00230 if (digit>9) return ret;
00231 } else {
00232 digit = number[i];
00233 if (digit>127) return ret;
00234 }
00235
00236 if (node->child[digit] == NULL) return ret;
00237 node = node->child[digit];
00238 i++;
00239 if (node->data != NULL) {
00240 if (nmatchptr) *nmatchptr=i;
00241 ret = &node->data;
00242 }
00243 }
00244
00245 return ret;
00246 }
00247
00248
00249 void **dtrie_contains(struct dtrie_node_t *root, const char *number,
00250 const unsigned int numberlen, const unsigned int branches)
00251 {
00252 int nmatch;
00253 void **ret;
00254 ret = dtrie_longest_match(root, number, numberlen, &nmatch, branches);
00255
00256 if (nmatch == numberlen) return ret;
00257 return NULL;
00258 }