ldns  1.7.0
radix.c
Go to the documentation of this file.
1 /*
2  * radix.c -- generic radix tree
3  *
4  * Taken from NSD4, modified for ldns
5  *
6  * Copyright (c) 2012, NLnet Labs. All rights reserved.
7  *
8  * This software is open source.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  *
17  * Redistributions in binary form must reproduce the above copyright notice,
18  * this list of conditions and the following disclaimer in the documentation
19  * and/or other materials provided with the distribution.
20  *
21  * Neither the name of the NLNET LABS nor the names of its contributors may
22  * be used to endorse or promote products derived from this software without
23  * specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
31  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38 
44 #include <ldns/config.h>
45 #include <ldns/radix.h>
46 #include <ldns/util.h>
47 #include <stdlib.h>
48 
50 static ldns_radix_node_t* ldns_radix_new_node(void* data, uint8_t* key,
51  radix_strlen_t len);
52 static int ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
53  radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* pos);
54 static int ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte);
55 static int ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need);
56 static int ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
58 static int ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
59  uint8_t* longer_str, radix_strlen_t longer_len, uint8_t** split_str,
60  radix_strlen_t* split_len);
61 static int ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
63 static int ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
64  uint8_t* str2, radix_strlen_t len2);
65 static radix_strlen_t ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
66  uint8_t* str2, radix_strlen_t len2);
67 static ldns_radix_node_t* ldns_radix_next_in_subtree(ldns_radix_node_t* node);
68 static ldns_radix_node_t* ldns_radix_prev_from_index(ldns_radix_node_t* node,
69  uint8_t index);
70 static ldns_radix_node_t* ldns_radix_last_in_subtree_incl_self(
71  ldns_radix_node_t* node);
72 static ldns_radix_node_t* ldns_radix_last_in_subtree(ldns_radix_node_t* node);
73 static void ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node);
74 static void ldns_radix_cleanup_onechild(ldns_radix_node_t* node);
75 static void ldns_radix_cleanup_leaf(ldns_radix_node_t* node);
76 static void ldns_radix_node_free(ldns_radix_node_t* node, void* arg);
77 static void ldns_radix_node_array_free(ldns_radix_node_t* node);
78 static void ldns_radix_node_array_free_front(ldns_radix_node_t* node);
79 static void ldns_radix_node_array_free_end(ldns_radix_node_t* node);
80 static void ldns_radix_array_reduce(ldns_radix_node_t* node);
81 static void ldns_radix_self_or_prev(ldns_radix_node_t* node,
82  ldns_radix_node_t** result);
83 
84 
89 static ldns_radix_node_t*
90 ldns_radix_new_node(void* data, uint8_t* key, radix_strlen_t len)
91 {
93  if (!node) {
94  return NULL;
95  }
96  node->data = data;
97  node->key = key;
98  node->klen = len;
99  node->parent = NULL;
100  node->parent_index = 0;
101  node->len = 0;
102  node->offset = 0;
103  node->capacity = 0;
104  node->array = NULL;
105  return node;
106 }
107 
108 
113 ldns_radix_t *
115 {
116  ldns_radix_t* tree;
117 
120  if (!tree) {
121  return NULL;
122  }
124  ldns_radix_init(tree);
125  return tree;
126 }
127 
128 
133 void
135 {
137  if (tree) {
138  tree->root = NULL;
139  tree->count = 0;
140  }
141  return;
142 }
143 
144 
149 void
151 {
152  if (tree) {
153  if (tree->root) {
155  ldns_radix_node_free, NULL);
156  }
157  LDNS_FREE(tree);
158  }
159  return;
160 }
161 
162 
169  void* data)
170 {
171  radix_strlen_t pos = 0;
172  ldns_radix_node_t* add = NULL;
173  ldns_radix_node_t* prefix = NULL;
174 
175  if (!tree || !key || !data) {
176  return LDNS_STATUS_NULL;
177  }
178  add = ldns_radix_new_node(data, key, len);
179  if (!add) {
180  return LDNS_STATUS_MEM_ERR;
181  }
183  if (!ldns_radix_find_prefix(tree, key, len, &prefix, &pos)) {
185  assert(tree->root == NULL);
186  if (len == 0) {
191  tree->root = add;
192  } else {
197  prefix = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
198  if (!prefix) {
199  LDNS_FREE(add);
200  return LDNS_STATUS_MEM_ERR;
201  }
203  if (!ldns_radix_array_space(prefix, key[0])) {
204  LDNS_FREE(add);
205  LDNS_FREE(prefix->array);
206  LDNS_FREE(prefix);
207  return LDNS_STATUS_MEM_ERR;
208  }
210  add->parent = prefix;
211  add->parent_index = 0;
212  prefix->array[0].edge = add;
213  if (len > 1) {
215  if (!ldns_radix_prefix_remainder(1, key,
216  len, &prefix->array[0].str,
217  &prefix->array[0].len)) {
218  LDNS_FREE(add);
219  LDNS_FREE(prefix->array);
220  LDNS_FREE(prefix);
221  return LDNS_STATUS_MEM_ERR;
222  }
223  }
224  tree->root = prefix;
225  }
226  } else if (pos == len) {
228  if (prefix->data) {
229  /* Element already exists */
230  LDNS_FREE(add);
231  return LDNS_STATUS_EXISTS_ERR;
232  }
233  prefix->data = data;
234  prefix->key = key;
235  prefix->klen = len; /* redundant */
236  } else {
238  uint8_t byte = key[pos];
239  assert(pos < len);
240  if (byte < prefix->offset ||
241  (byte - prefix->offset) >= prefix->len) {
249  if (!ldns_radix_array_space(prefix, byte)) {
250  LDNS_FREE(add);
251  return LDNS_STATUS_MEM_ERR;
252  }
253  assert(byte >= prefix->offset);
254  assert((byte - prefix->offset) <= prefix->len);
255  byte -= prefix->offset;
256  if (pos+1 < len) {
258  if (!ldns_radix_str_create(
259  &prefix->array[byte], key, pos+1,
260  len)) {
261  LDNS_FREE(add);
262  return LDNS_STATUS_MEM_ERR;
263  }
264  }
266  add->parent = prefix;
267  add->parent_index = byte;
268  prefix->array[byte].edge = add;
269  } else if (prefix->array[byte-prefix->offset].edge == NULL) {
278  byte -= prefix->offset;
279  if (pos+1 < len) {
281  if (!ldns_radix_str_create(
282  &prefix->array[byte], key, pos+1,
283  len)) {
284  LDNS_FREE(add);
285  return LDNS_STATUS_MEM_ERR;
286  }
287  }
289  add->parent = prefix;
290  add->parent_index = byte;
291  prefix->array[byte].edge = add;
292  } else {
297  if (!ldns_radix_array_split(&prefix->array[byte-(prefix->offset)],
298  key, pos+1, len, add)) {
299  LDNS_FREE(add);
300  return LDNS_STATUS_MEM_ERR;
301  }
302  }
303  }
304 
305  tree->count ++;
306  return LDNS_STATUS_OK;
307 }
308 
309 
314 void* ldns_radix_delete(ldns_radix_t* tree, const uint8_t* key, radix_strlen_t len)
315 {
316  ldns_radix_node_t* del = ldns_radix_search(tree, key, len);
317  void* data = NULL;
318  if (del) {
319  tree->count--;
320  data = del->data;
321  del->data = NULL;
322  ldns_radix_del_fix(tree, del);
323  return data;
324  }
325  return NULL;
326 }
327 
328 
334 ldns_radix_search(ldns_radix_t* tree, const uint8_t* key, radix_strlen_t len)
335 {
336  ldns_radix_node_t* node = NULL;
337  radix_strlen_t pos = 0;
338  uint8_t byte = 0;
339 
340  if (!tree || !key) {
341  return NULL;
342  }
343  node = tree->root;
344  while (node) {
345  if (pos == len) {
346  return node->data?node:NULL;
347  }
348  byte = key[pos];
349  if (byte < node->offset) {
350  return NULL;
351  }
352  byte -= node->offset;
353  if (byte >= node->len) {
354  return NULL;
355  }
356  pos++;
357  if (node->array[byte].len > 0) {
359  if (pos + node->array[byte].len > len) {
360  return NULL;
361  }
362  if (memcmp(&key[pos], node->array[byte].str,
363  node->array[byte].len) != 0) {
364  return NULL;
365  }
366  pos += node->array[byte].len;
367  }
368  node = node->array[byte].edge;
369  }
370  return NULL;
371 }
372 
373 
379 int
380 ldns_radix_find_less_equal(ldns_radix_t* tree, const uint8_t* key,
381  radix_strlen_t len, ldns_radix_node_t** result)
382 {
383  ldns_radix_node_t* node = NULL;
384  radix_strlen_t pos = 0;
385  uint8_t byte;
386  int memcmp_res = 0;
387 
388  if (!tree || !tree->root || !key) {
389  *result = NULL;
390  return 0;
391  }
392 
393  node = tree->root;
394  while (pos < len) {
395  byte = key[pos];
396  if (byte < node->offset) {
401  ldns_radix_self_or_prev(node, result);
402  return 0;
403  }
404  byte -= node->offset;
405  if (byte >= node->len) {
410  *result = ldns_radix_last_in_subtree_incl_self(node);
411  if (*result == NULL) {
412  *result = ldns_radix_prev(node);
413  }
414  return 0;
415  }
416  pos++;
417  if (!node->array[byte].edge) {
422  *result = ldns_radix_prev_from_index(node, byte);
423  if (*result == NULL) {
424  ldns_radix_self_or_prev(node, result);
425  }
426  return 0;
427  }
428  if (node->array[byte].len != 0) {
430  if (pos + node->array[byte].len > len) {
432  if (memcmp(&key[pos], node->array[byte].str,
433  len-pos) <= 0) {
435  *result = ldns_radix_prev(
436  node->array[byte].edge);
437  } else {
439  *result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
440  if (*result == NULL) {
441  *result = ldns_radix_prev(node->array[byte].edge);
442  }
443  }
444  return 0;
445  }
446  memcmp_res = memcmp(&key[pos], node->array[byte].str,
447  node->array[byte].len);
448  if (memcmp_res < 0) {
449  *result = ldns_radix_prev(
450  node->array[byte].edge);
451  return 0;
452  } else if (memcmp_res > 0) {
453  *result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
454  if (*result == NULL) {
455  *result = ldns_radix_prev(node->array[byte].edge);
456  }
457  return 0;
458  }
459 
460  pos += node->array[byte].len;
461  }
462  node = node->array[byte].edge;
463  }
464  if (node->data) {
466  *result = node;
467  return 1;
468  }
470  *result = ldns_radix_prev(node);
471  return 0;
472 }
473 
474 
481 {
482  ldns_radix_node_t* first = NULL;
483  if (!tree || !tree->root) {
484  return NULL;
485  }
486  first = tree->root;
487  if (first->data) {
488  return first;
489  }
490  return ldns_radix_next(first);
491 }
492 
493 
500 {
501  if (!tree || !tree->root) {
502  return NULL;
503  }
504  return ldns_radix_last_in_subtree_incl_self(tree->root);
505 }
506 
507 
514 {
515  if (!node) {
516  return NULL;
517  }
518  if (node->len) {
520  ldns_radix_node_t* next = ldns_radix_next_in_subtree(node);
521  if (next) {
522  return next;
523  }
524  }
526  while (node->parent) {
527  uint8_t index = node->parent_index;
528  node = node->parent;
529  index++;
530  for (; index < node->len; index++) {
531  if (node->array[index].edge) {
532  ldns_radix_node_t* next;
534  if (node->array[index].edge->data) {
535  return node->array[index].edge;
536  }
538  next = ldns_radix_next_in_subtree(node);
539  if (next) {
540  return next;
541  }
542  }
543  }
544  }
545  return NULL;
546 }
547 
548 
555 {
556  if (!node) {
557  return NULL;
558  }
559 
561  while (node->parent) {
562  uint8_t index = node->parent_index;
563  ldns_radix_node_t* prev;
564  node = node->parent;
565  assert(node->len > 0);
566  prev = ldns_radix_prev_from_index(node, index);
567  if (prev) {
568  return prev;
569  }
570  if (node->data) {
571  return node;
572  }
573  }
574  return NULL;
575 }
576 
577 
582 static void
583 ldns_radix_node_print(FILE* fd, ldns_radix_node_t* node,
584  uint8_t i, uint8_t* str, radix_strlen_t len, unsigned d)
585 {
586  uint8_t j;
587  if (!node) {
588  return;
589  }
590  for (j = 0; j < d; j++) {
591  fprintf(fd, "--");
592  }
593  if (str) {
594  radix_strlen_t l;
595  fprintf(fd, "| [%u+", (unsigned) i);
596  for (l=0; l < len; l++) {
597  fprintf(fd, "%c", (char) str[l]);
598  }
599  fprintf(fd, "]%u", (unsigned) len);
600  } else {
601  fprintf(fd, "| [%u]", (unsigned) i);
602  }
603 
604  if (node->data) {
605  fprintf(fd, " %s", (char*) node->data);
606  }
607  fprintf(fd, "\n");
608 
609  for (j = 0; j < node->len; j++) {
610  if (node->array[j].edge) {
611  ldns_radix_node_print(fd, node->array[j].edge, j,
612  node->array[j].str, node->array[j].len, d+1);
613  }
614  }
615  return;
616 }
617 
618 
623 void
624 ldns_radix_printf(FILE* fd, const ldns_radix_t* tree)
625 {
626  if (!fd || !tree) {
627  return;
628  }
629  if (!tree->root) {
630  fprintf(fd, "; empty radix tree\n");
631  return;
632  }
633  ldns_radix_node_print(fd, tree->root, 0, NULL, 0, 0);
634  return;
635 }
636 
637 
644 {
645  ldns_radix_node_t* cur_node, *next_node;
646  ldns_status status;
647  if (!tree2 || !tree2->root) {
648  return LDNS_STATUS_OK;
649  }
652  cur_node = ldns_radix_first(tree2);
653  while (cur_node) {
654  status = LDNS_STATUS_NO_DATA;
656  if (cur_node->data) {
657  status = ldns_radix_insert(tree1, cur_node->key,
658  cur_node->klen, cur_node->data);
660  if (status != LDNS_STATUS_OK &&
661  status != LDNS_STATUS_EXISTS_ERR) {
662  return status;
663  }
664  }
665  next_node = ldns_radix_next(cur_node);
666  if (status == LDNS_STATUS_OK) {
667  (void) ldns_radix_delete(tree2, cur_node->key,
668  cur_node->klen);
669  }
670  cur_node = next_node;
671  }
672 
673  return LDNS_STATUS_OK;
674 }
675 
676 
682 ldns_radix_split(ldns_radix_t* tree1, size_t num, ldns_radix_t** tree2)
683 {
684  size_t count = 0;
685  ldns_radix_node_t* cur_node;
686  ldns_status status = LDNS_STATUS_OK;
687  if (!tree1 || !tree1->root || num == 0) {
688  return LDNS_STATUS_OK;
689  }
690  if (!tree2) {
691  return LDNS_STATUS_NULL;
692  }
693  if (!*tree2) {
694  *tree2 = ldns_radix_create();
695  if (!*tree2) {
696  return LDNS_STATUS_MEM_ERR;
697  }
698  }
699  cur_node = ldns_radix_first(tree1);
700  while (count < num && cur_node) {
701  if (cur_node->data) {
703  uint8_t* cur_key = cur_node->key;
704  radix_strlen_t cur_len = cur_node->klen;
705  void* cur_data = ldns_radix_delete(tree1, cur_key,
706  cur_len);
708  if (!cur_data) {
709  return LDNS_STATUS_NO_DATA;
710  }
711  status = ldns_radix_insert(*tree2, cur_key, cur_len,
712  cur_data);
713  if (status != LDNS_STATUS_OK &&
714  status != LDNS_STATUS_EXISTS_ERR) {
715  return status;
716  }
717 /*
718  if (status == LDNS_STATUS_OK) {
719  cur_node->key = NULL;
720  cur_node->klen = 0;
721  }
722 */
724  count++;
725  cur_node = ldns_radix_first(tree1);
726  } else {
727  cur_node = ldns_radix_next(cur_node);
728  }
729  }
730  return LDNS_STATUS_OK;
731 }
732 
733 
739 void
741  void (*func)(ldns_radix_node_t*, void*), void* arg)
742 {
743  uint8_t i;
744  if (!node) {
745  return;
746  }
747  for (i=0; i < node->len; i++) {
749  func, arg);
750  }
752  (*func)(node, arg);
753  return;
754 }
755 
756 
772 static int
773 ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
774  radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* respos)
775 {
777  ldns_radix_node_t* n = tree->root;
778  radix_strlen_t pos = 0;
779  uint8_t byte;
780  *respos = 0;
781  *result = n;
782  if (!n) {
784  return 0;
785  }
787  while (n) {
788  if (pos == len) {
790  return 1;
791  }
792  byte = key[pos];
793  if (byte < n->offset) {
795  return 1;
796  }
797  byte -= n->offset;
798  if (byte >= n->len) {
800  return 1;
801  }
803  pos++;
804  if (n->array[byte].len != 0) {
806  if (pos + n->array[byte].len > len) {
807  return 1; /* no match at child node */
808  }
809  if (memcmp(&key[pos], n->array[byte].str,
810  n->array[byte].len) != 0) {
811  return 1; /* no match at child node */
812  }
813  pos += n->array[byte].len;
814  }
816  n = n->array[byte].edge;
817  if (!n) {
818  return 1;
819  }
821  *respos = pos;
822  *result = n;
823  }
825  return 1;
826 }
827 
828 
836 static int
837 ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte)
838 {
840  if (!node->array) {
841  assert(node->capacity == 0);
844  if (!node->array) {
845  return 0;
846  }
847  memset(&node->array[0], 0, sizeof(ldns_radix_array_t));
848  node->len = 1;
849  node->capacity = 1;
850  node->offset = byte;
851  return 1;
852  }
854  assert(node->array != NULL);
855  assert(node->capacity > 0);
856 
857  if (node->len == 0) {
859  node->len = 1;
860  node->offset = byte;
861  } else if (byte < node->offset) {
863  uint8_t index;
864  uint16_t need = node->offset - byte;
866  if (node->len + need > node->capacity) {
868  if (!ldns_radix_array_grow(node,
869  (unsigned) (node->len + need))) {
870  return 0; /* failed to grow array */
871  }
872  }
874  memmove(&node->array[need], &node->array[0],
875  node->len*sizeof(ldns_radix_array_t));
877  for (index = 0; index < node->len; index++) {
878  if (node->array[index+need].edge) {
879  node->array[index+need].edge->parent_index =
880  index + need;
881  }
882  }
884  memset(&node->array[0], 0, need*sizeof(ldns_radix_array_t));
885  node->len += need;
886  node->offset = byte;
887  } else if (byte - node->offset >= node->len) {
889  uint16_t need = (byte - node->offset) - node->len + 1;
891  if (node->len + need > node->capacity) {
893  if (!ldns_radix_array_grow(node,
894  (unsigned) (node->len + need))) {
895  return 0; /* failed to grow array */
896  }
897  }
899  memset(&node->array[node->len], 0,
900  need*sizeof(ldns_radix_array_t));
901  node->len += need;
902  }
903  return 1;
904 }
905 
906 
915 static int
916 ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need)
917 {
918  unsigned size = ((unsigned)node->capacity)*2;
919  ldns_radix_array_t* a = NULL;
920  if (need > size) {
921  size = need;
922  }
923  if (size > 256) {
924  size = 256;
925  }
926  a = LDNS_XMALLOC(ldns_radix_array_t, size);
927  if (!a) {
928  return 0;
929  }
930  assert(node->len <= node->capacity);
931  assert(node->capacity < size);
932  memcpy(&a[0], &node->array[0], node->len*sizeof(ldns_radix_array_t));
933  LDNS_FREE(node->array);
934  node->array = a;
935  node->capacity = size;
936  return 1;
937 }
938 
939 
949 static int
950 ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
952 {
953  array->str = LDNS_XMALLOC(uint8_t, (len-pos));
954  if (!array->str) {
955  return 0;
956  }
957  memmove(array->str, key+pos, len-pos);
958  array->len = (len-pos);
959  return 1;
960 }
961 
962 
973 static int
974 ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
975  uint8_t* longer_str, radix_strlen_t longer_len,
976  uint8_t** split_str, radix_strlen_t* split_len)
977 {
978  *split_len = longer_len - prefix_len;
979  *split_str = LDNS_XMALLOC(uint8_t, (*split_len));
980  if (!*split_str) {
981  return 0;
982  }
983  memmove(*split_str, longer_str+prefix_len, longer_len-prefix_len);
984  return 1;
985 }
986 
987 
998 static int
999 ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
1001 {
1002  uint8_t* str_to_add = key + pos;
1003  radix_strlen_t strlen_to_add = len - pos;
1004 
1005  if (ldns_radix_str_is_prefix(str_to_add, strlen_to_add,
1006  array->str, array->len)) {
1008  uint8_t* split_str = NULL, *dup_str = NULL;
1009  radix_strlen_t split_len = 0;
1018  assert(strlen_to_add < array->len);
1020  if (array->len - strlen_to_add > 1) {
1021  if (!ldns_radix_prefix_remainder(strlen_to_add+1,
1022  array->str, array->len, &split_str,
1023  &split_len)) {
1024  return 0;
1025  }
1026  }
1028  if (strlen_to_add != 0) {
1029  dup_str = LDNS_XMALLOC(uint8_t, strlen_to_add);
1030  if (!dup_str) {
1031  LDNS_FREE(split_str);
1032  return 0;
1033  }
1034  memcpy(dup_str, str_to_add, strlen_to_add);
1035  }
1037  if (!ldns_radix_array_space(add,
1038  array->str[strlen_to_add])) {
1039  LDNS_FREE(split_str);
1040  LDNS_FREE(dup_str);
1041  return 0;
1042  }
1047  add->parent = array->edge->parent;
1048  add->parent_index = array->edge->parent_index;
1049  add->array[0].edge = array->edge;
1050  add->array[0].str = split_str;
1051  add->array[0].len = split_len;
1052  array->edge->parent = add;
1053  array->edge->parent_index = 0;
1054  LDNS_FREE(array->str);
1055  array->edge = add;
1056  array->str = dup_str;
1057  array->len = strlen_to_add;
1058  } else if (ldns_radix_str_is_prefix(array->str, array->len,
1059  str_to_add, strlen_to_add)) {
1070  uint8_t* split_str = NULL;
1071  radix_strlen_t split_len = 0;
1072  assert(array->len < strlen_to_add);
1073  if (strlen_to_add - array->len > 1) {
1074  if (!ldns_radix_prefix_remainder(array->len+1,
1075  str_to_add, strlen_to_add, &split_str,
1076  &split_len)) {
1077  return 0;
1078  }
1079  }
1081  if (!ldns_radix_array_space(array->edge,
1082  str_to_add[array->len])) {
1083  LDNS_FREE(split_str);
1084  return 0;
1085  }
1089  add->parent = array->edge;
1090  add->parent_index = str_to_add[array->len] -
1091  array->edge->offset;
1092  array->edge->array[add->parent_index].edge = add;
1093  array->edge->array[add->parent_index].str = split_str;
1094  array->edge->array[add->parent_index].len = split_len;
1095  } else {
1108  ldns_radix_node_t* common = NULL;
1109  uint8_t* common_str = NULL, *s1 = NULL, *s2 = NULL;
1110  radix_strlen_t common_len = 0, l1 = 0, l2 = 0;
1111  common_len = ldns_radix_str_common(array->str, array->len,
1112  str_to_add, strlen_to_add);
1113  assert(common_len < array->len);
1114  assert(common_len < strlen_to_add);
1116  common = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
1117  if (!common) {
1118  return 0;
1119  }
1120  if (array->len - common_len > 1) {
1121  if (!ldns_radix_prefix_remainder(common_len+1,
1122  array->str, array->len, &s1, &l1)) {
1123  return 0;
1124  }
1125  }
1126  if (strlen_to_add - common_len > 1) {
1127  if (!ldns_radix_prefix_remainder(common_len+1,
1128  str_to_add, strlen_to_add, &s2, &l2)) {
1129  return 0;
1130  }
1131  }
1133  if (common_len > 0) {
1134  common_str = LDNS_XMALLOC(uint8_t, common_len);
1135  if (!common_str) {
1136  LDNS_FREE(common);
1137  LDNS_FREE(s1);
1138  LDNS_FREE(s2);
1139  return 0;
1140  }
1141  memcpy(common_str, str_to_add, common_len);
1142  }
1144  if (!ldns_radix_array_space(common, array->str[common_len]) ||
1145  !ldns_radix_array_space(common, str_to_add[common_len])) {
1146  LDNS_FREE(common->array);
1147  LDNS_FREE(common);
1148  LDNS_FREE(common_str);
1149  LDNS_FREE(s1);
1150  LDNS_FREE(s2);
1151  return 0;
1152  }
1157  common->parent = array->edge->parent;
1158  common->parent_index = array->edge->parent_index;
1159  array->edge->parent = common;
1160  array->edge->parent_index = array->str[common_len] -
1161  common->offset;
1162  add->parent = common;
1163  add->parent_index = str_to_add[common_len] - common->offset;
1164  common->array[array->edge->parent_index].edge = array->edge;
1165  common->array[array->edge->parent_index].str = s1;
1166  common->array[array->edge->parent_index].len = l1;
1167  common->array[add->parent_index].edge = add;
1168  common->array[add->parent_index].str = s2;
1169  common->array[add->parent_index].len = l2;
1170  LDNS_FREE(array->str);
1171  array->edge = common;
1172  array->str = common_str;
1173  array->len = common_len;
1174  }
1175  return 1;
1176 }
1177 
1178 
1188 static int
1189 ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
1190  uint8_t* str2, radix_strlen_t len2)
1191 {
1192  if (len1 == 0) {
1193  return 1; /* empty prefix is also a prefix */
1194  }
1195  if (len1 > len2) {
1196  return 0; /* len1 is longer so str1 cannot be a prefix */
1197  }
1198  return (memcmp(str1, str2, len1) == 0);
1199 }
1200 
1201 
1211 static radix_strlen_t
1212 ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
1213  uint8_t* str2, radix_strlen_t len2)
1214 {
1215  radix_strlen_t i, max = (len1<len2)?len1:len2;
1216  for (i=0; i<max; i++) {
1217  if (str1[i] != str2[i]) {
1218  return i;
1219  }
1220  }
1221  return max;
1222 }
1223 
1224 
1231 static ldns_radix_node_t*
1232 ldns_radix_next_in_subtree(ldns_radix_node_t* node)
1233 {
1234  uint16_t i;
1235  ldns_radix_node_t* next;
1237  for (i = 0; i < node->len; i++) {
1238  if (node->array[i].edge) {
1240  if (node->array[i].edge->data) {
1241  return node->array[i].edge;
1242  }
1244  next = ldns_radix_next_in_subtree(node->array[i].edge);
1245  if (next) {
1246  return next;
1247  }
1248  }
1249  }
1250  return NULL;
1251 }
1252 
1253 
1261 static ldns_radix_node_t*
1262 ldns_radix_prev_from_index(ldns_radix_node_t* node, uint8_t index)
1263 {
1264  uint8_t i = index;
1265  while (i > 0) {
1266  i--;
1267  if (node->array[i].edge) {
1268  ldns_radix_node_t* prev =
1269  ldns_radix_last_in_subtree_incl_self(node);
1270  if (prev) {
1271  return prev;
1272  }
1273  }
1274  }
1275  return NULL;
1276 }
1277 
1278 
1285 static ldns_radix_node_t*
1286 ldns_radix_last_in_subtree_incl_self(ldns_radix_node_t* node)
1287 {
1288  ldns_radix_node_t* last = ldns_radix_last_in_subtree(node);
1289  if (last) {
1290  return last;
1291  } else if (node->data) {
1292  return node;
1293  }
1294  return NULL;
1295 }
1296 
1297 
1304 static ldns_radix_node_t*
1305 ldns_radix_last_in_subtree(ldns_radix_node_t* node)
1306 {
1307  int i;
1309  for (i=(int)(node->len)-1; i >= 0; i--) {
1310  if (node->array[i].edge) {
1312  if (node->array[i].edge->len > 0) {
1313  ldns_radix_node_t* last =
1314  ldns_radix_last_in_subtree(
1315  node->array[i].edge);
1316  if (last) {
1317  return last;
1318  }
1319  }
1321  if (node->array[i].edge->data) {
1322  return node->array[i].edge;
1323  }
1324  }
1325  }
1326  return NULL;
1327 }
1328 
1329 
1336 static void
1337 ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node)
1338 {
1339  while (node) {
1340  if (node->data) {
1342  return;
1343  } else if (node->len == 1 && node->parent) {
1345  ldns_radix_cleanup_onechild(node);
1346  return;
1347  } else if (node->len == 0) {
1349  ldns_radix_node_t* parent = node->parent;
1350  if (!parent) {
1352  ldns_radix_node_free(node, NULL);
1353  tree->root = NULL;
1354  return;
1355  }
1357  ldns_radix_cleanup_leaf(node);
1358  node = parent;
1359  } else {
1364  return;
1365  }
1366  }
1368  return;
1369 }
1370 
1371 
1377 static void
1378 ldns_radix_cleanup_onechild(ldns_radix_node_t* node)
1379 {
1380  uint8_t* join_str;
1381  radix_strlen_t join_len;
1382  uint8_t parent_index = node->parent_index;
1383  ldns_radix_node_t* child = node->array[0].edge;
1384  ldns_radix_node_t* parent = node->parent;
1385 
1387  assert(parent_index < parent->len);
1388  join_len = parent->array[parent_index].len + node->array[0].len + 1;
1389 
1390  join_str = LDNS_XMALLOC(uint8_t, join_len);
1391  if (!join_str) {
1397  return;
1398  }
1399 
1400  memcpy(join_str, parent->array[parent_index].str,
1401  parent->array[parent_index].len);
1402  join_str[parent->array[parent_index].len] = child->parent_index +
1403  node->offset;
1404  memmove(join_str + parent->array[parent_index].len+1,
1405  node->array[0].str, node->array[0].len);
1406 
1407  LDNS_FREE(parent->array[parent_index].str);
1408  parent->array[parent_index].str = join_str;
1409  parent->array[parent_index].len = join_len;
1410  parent->array[parent_index].edge = child;
1411  child->parent = parent;
1412  child->parent_index = parent_index;
1413  ldns_radix_node_free(node, NULL);
1414  return;
1415 }
1416 
1417 
1423 static void
1424 ldns_radix_cleanup_leaf(ldns_radix_node_t* node)
1425 {
1426  uint8_t parent_index = node->parent_index;
1427  ldns_radix_node_t* parent = node->parent;
1429  assert(parent_index < parent->len);
1430  ldns_radix_node_free(node, NULL);
1431  LDNS_FREE(parent->array[parent_index].str);
1432  parent->array[parent_index].str = NULL;
1433  parent->array[parent_index].len = 0;
1434  parent->array[parent_index].edge = NULL;
1436  if (parent->len == 1) {
1437  ldns_radix_node_array_free(parent);
1438  } else if (parent_index == 0) {
1439  ldns_radix_node_array_free_front(parent);
1440  } else {
1441  ldns_radix_node_array_free_end(parent);
1442  }
1443  return;
1444 }
1445 
1446 
1453 static void
1454 ldns_radix_node_free(ldns_radix_node_t* node, void* arg)
1455 {
1456  uint16_t i;
1457  (void) arg;
1458  if (!node) {
1459  return;
1460  }
1461  for (i=0; i < node->len; i++) {
1462  LDNS_FREE(node->array[i].str);
1463  }
1464  node->key = NULL;
1465  node->klen = 0;
1466  LDNS_FREE(node->array);
1467  LDNS_FREE(node);
1468  return;
1469 }
1470 
1471 
1477 static void
1478 ldns_radix_node_array_free(ldns_radix_node_t* node)
1479 {
1480  node->offset = 0;
1481  node->len = 0;
1482  LDNS_FREE(node->array);
1483  node->array = NULL;
1484  node->capacity = 0;
1485  return;
1486 }
1487 
1488 
1494 static void
1495 ldns_radix_node_array_free_front(ldns_radix_node_t* node)
1496 {
1497  uint16_t i, n = 0;
1499  while (n < node->len && node->array[n].edge == NULL) {
1500  n++;
1501  }
1502  if (n == 0) {
1503  return;
1504  }
1505  if (n == node->len) {
1506  ldns_radix_node_array_free(node);
1507  return;
1508  }
1509  assert(n < node->len);
1510  assert((int) n <= (255 - (int) node->offset));
1511  memmove(&node->array[0], &node->array[n],
1512  (node->len - n)*sizeof(ldns_radix_array_t));
1513  node->offset += n;
1514  node->len -= n;
1515  for (i=0; i < node->len; i++) {
1516  if (node->array[i].edge) {
1517  node->array[i].edge->parent_index = i;
1518  }
1519  }
1520  ldns_radix_array_reduce(node);
1521  return;
1522 }
1523 
1524 
1530 static void
1531 ldns_radix_node_array_free_end(ldns_radix_node_t* node)
1532 {
1533  uint16_t n = 0;
1535  while (n < node->len && node->array[node->len-1-n].edge == NULL) {
1536  n++;
1537  }
1538  if (n == 0) {
1539  return;
1540  }
1541  if (n == node->len) {
1542  ldns_radix_node_array_free(node);
1543  return;
1544  }
1545  assert(n < node->len);
1546  node->len -= n;
1547  ldns_radix_array_reduce(node);
1548  return;
1549 }
1550 
1551 
1557 static void
1558 ldns_radix_array_reduce(ldns_radix_node_t* node)
1559 {
1560  if (node->len <= node->capacity/2 && node->len != node->capacity) {
1562  node->len);
1563  if (!a) {
1564  return;
1565  }
1566  memcpy(a, node->array, sizeof(ldns_radix_array_t)*node->len);
1567  LDNS_FREE(node->array);
1568  node->array = a;
1569  node->capacity = node->len;
1570  }
1571  return;
1572 }
1573 
1574 
1581 static void
1582 ldns_radix_self_or_prev(ldns_radix_node_t* node, ldns_radix_node_t** result)
1583 {
1584  if (node->data) {
1585  *result = node;
1586  } else {
1587  *result = ldns_radix_prev(node);
1588  }
1589  return;
1590 }
ldns_radix_traverse_postorder
void ldns_radix_traverse_postorder(ldns_radix_node_t *node, void(*func)(ldns_radix_node_t *, void *), void *arg)
Call function for all nodes in the tree, such that leaf nodes are called before parent nodes.
Definition: radix.c:740
ldns_radix_last
ldns_radix_node_t * ldns_radix_last(const ldns_radix_t *tree)
Get the last element in the tree.
Definition: radix.c:499
ldns_radix_array_t::len
radix_strlen_t len
Length of additional string for this edge.
Definition: radix.h:62
ldns_radix_node_t::klen
radix_strlen_t klen
Key length corresponding to this node.
Definition: radix.h:72
ldns_radix_create
ldns_radix_t * ldns_radix_create(void)
Create a new radix tree.
Definition: radix.c:114
LDNS_FREE
#define LDNS_FREE(ptr)
Definition: util.h:60
ldns_radix_next
ldns_radix_node_t * ldns_radix_next(ldns_radix_node_t *node)
Next element.
Definition: radix.c:513
LDNS_STATUS_OK
@ LDNS_STATUS_OK
Definition: error.h:26
radix_strlen_t
uint16_t radix_strlen_t
Definition: radix.h:52
ldns_radix_t::root
ldns_radix_node_t * root
Root.
Definition: radix.h:92
ldns_radix_node_t::capacity
uint16_t capacity
Capacity of the array.
Definition: radix.h:84
ldns_radix_array_t
Radix node select edge array.
Definition: radix.h:58
ldns_radix_node_t::offset
uint16_t offset
Offset of the array.
Definition: radix.h:82
ldns_radix_prev
ldns_radix_node_t * ldns_radix_prev(ldns_radix_node_t *node)
Previous element.
Definition: radix.c:554
ldns_radix_free
void ldns_radix_free(ldns_radix_t *tree)
Free radix tree.
Definition: radix.c:150
ldns_radix_split
ldns_status ldns_radix_split(ldns_radix_t *tree1, size_t num, ldns_radix_t **tree2)
Split a radix tree intwo.
Definition: radix.c:682
ldns_radix_node_t::len
uint16_t len
Length of the array.
Definition: radix.h:80
ldns_radix_insert
ldns_status ldns_radix_insert(ldns_radix_t *tree, uint8_t *key, radix_strlen_t len, void *data)
Insert data into the tree.
Definition: radix.c:168
ldns_radix_t
An entire radix tree.
Definition: radix.h:90
ldns_radix_array_t::edge
ldns_radix_node_t * edge
Node that deals with byte+str.
Definition: radix.h:64
LDNS_MALLOC
#define LDNS_MALLOC(type)
Memory management macros.
Definition: util.h:49
ldns_radix_node_t
A node in a radix tree.
Definition: radix.h:68
ldns_status
enum ldns_enum_status ldns_status
Definition: error.h:134
LDNS_XMALLOC
#define LDNS_XMALLOC(type, count)
Definition: util.h:51
LDNS_STATUS_NO_DATA
@ LDNS_STATUS_NO_DATA
Definition: error.h:77
config.h
ldns_radix_printf
void ldns_radix_printf(FILE *fd, const ldns_radix_t *tree)
Print radix tree.
Definition: radix.c:624
ldns_radix_delete
void * ldns_radix_delete(ldns_radix_t *tree, const uint8_t *key, radix_strlen_t len)
Delete data from the tree.
Definition: radix.c:314
ldns_radix_node_t::parent
ldns_radix_node_t * parent
Parent node.
Definition: radix.h:76
ldns_radix_join
ldns_status ldns_radix_join(ldns_radix_t *tree1, ldns_radix_t *tree2)
Join two radix trees.
Definition: radix.c:643
ldns_radix_node_t::parent_index
uint8_t parent_index
Index in the the parent node select edge array.
Definition: radix.h:78
ldns_radix_first
ldns_radix_node_t * ldns_radix_first(const ldns_radix_t *tree)
Get the first element in the tree.
Definition: radix.c:480
ldns_radix_search
ldns_radix_node_t * ldns_radix_search(ldns_radix_t *tree, const uint8_t *key, radix_strlen_t len)
Search data in the tree.
Definition: radix.c:334
LDNS_STATUS_MEM_ERR
@ LDNS_STATUS_MEM_ERR
Definition: error.h:34
ldns_radix_find_less_equal
int ldns_radix_find_less_equal(ldns_radix_t *tree, const uint8_t *key, radix_strlen_t len, ldns_radix_node_t **result)
Search data in the tree, and if not found, find the closest smaller element in the tree.
Definition: radix.c:380
ldns_radix_node_t::key
uint8_t * key
Key corresponding to this node.
Definition: radix.h:70
LDNS_STATUS_NULL
@ LDNS_STATUS_NULL
Definition: error.h:51
ldns_radix_node_t::array
ldns_radix_array_t * array
Select edge array.
Definition: radix.h:86
ldns_radix_array_t::str
uint8_t * str
Additional string after the selection byte for this edge.
Definition: radix.h:60
util.h
ldns_radix_t::count
size_t count
Number of nodes in tree.
Definition: radix.h:94
radix.h
ldns_radix_init
void ldns_radix_init(ldns_radix_t *tree)
Initialize radix tree.
Definition: radix.c:134
LDNS_STATUS_EXISTS_ERR
@ LDNS_STATUS_EXISTS_ERR
Definition: error.h:121
ldns_radix_node_t::data
void * data
Data corresponding to this node.
Definition: radix.h:74