comparison tern.c @ 1326:071e761bcdcf

Fix a deficiency in the way types were handled in my ternary tree. Fixes in which some paths that were constructed from a template with variables would sometimes get an extra garbage character thrown in
author Michael Pavone <pavone@retrodev.com>
date Fri, 21 Apr 2017 23:35:32 -0700
parents 72ea3885e7b5
children e890971f3757
comparison
equal deleted inserted replaced
1325:58bfbed6cdb5 1326:071e761bcdcf
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <string.h> 9 #include <string.h>
10 #include <stdio.h> 10 #include <stdio.h>
11 #include "util.h" 11 #include "util.h"
12 12
13 tern_node * tern_insert(tern_node * head, char const * key, tern_val value) 13 tern_node * tern_insert(tern_node * head, char const * key, tern_val value, uint8_t valtype)
14 { 14 {
15 tern_node ** cur = &head; 15 tern_node ** cur = &head;
16 while(*key) 16 while(*key)
17 { 17 {
18 if (*cur) { 18 if (*cur) {
29 *cur = malloc(sizeof(tern_node)); 29 *cur = malloc(sizeof(tern_node));
30 (*cur)->left = NULL; 30 (*cur)->left = NULL;
31 (*cur)->right = NULL; 31 (*cur)->right = NULL;
32 (*cur)->straight.next = NULL; 32 (*cur)->straight.next = NULL;
33 (*cur)->el = *key; 33 (*cur)->el = *key;
34 (*cur)->valtype = TVAL_NONE;
34 } 35 }
35 cur = &((*cur)->straight.next); 36 cur = &((*cur)->straight.next);
36 key++; 37 key++;
37 } 38 }
38 while(*cur && (*cur)->el) 39 while(*cur && (*cur)->el)
44 (*cur)->left = NULL; 45 (*cur)->left = NULL;
45 (*cur)->right = NULL; 46 (*cur)->right = NULL;
46 (*cur)->el = 0; 47 (*cur)->el = 0;
47 } 48 }
48 (*cur)->straight.value = value; 49 (*cur)->straight.value = value;
50 (*cur)->valtype = valtype;
49 return head; 51 return head;
50 } 52 }
51 53
52 int tern_find(tern_node * head, char const * key, tern_val *ret) 54 uint8_t tern_find(tern_node * head, char const * key, tern_val *ret)
53 { 55 {
54 tern_node * cur = head; 56 tern_node * cur = head;
55 while (cur) 57 while (cur)
56 { 58 {
57 if (cur->el == *key) { 59 if (cur->el == *key) {
58 if (*key) { 60 if (*key) {
59 cur = cur->straight.next; 61 cur = cur->straight.next;
60 key++; 62 key++;
61 } else { 63 } else {
62 *ret = cur->straight.value; 64 *ret = cur->straight.value;
63 return 1; 65 return cur->valtype;
64 } 66 }
65 } else if (*key < cur->el) { 67 } else if (*key < cur->el) {
66 cur = cur->left; 68 cur = cur->left;
67 } else { 69 } else {
68 cur = cur->right; 70 cur = cur->right;
69 } 71 }
70 } 72 }
71 return 0; 73 return TVAL_NONE;
72 } 74 }
73 75
74 tern_node * tern_find_prefix(tern_node * head, char const * key) 76 tern_node * tern_find_prefix(tern_node * head, char const * key)
75 { 77 {
76 tern_node * cur = head; 78 tern_node * cur = head;
89 } 91 }
90 92
91 intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def) 93 intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def)
92 { 94 {
93 tern_val ret; 95 tern_val ret;
94 if (tern_find(head, key, &ret)) { 96 uint8_t valtype = tern_find(head, key, &ret);
97 if (valtype == TVAL_INT) {
95 return ret.intval; 98 return ret.intval;
96 } 99 }
97 return def; 100 return def;
98 } 101 }
99 102
100 tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value) 103 tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value)
101 { 104 {
102 tern_val val; 105 tern_val val;
103 val.intval = value; 106 val.intval = value;
104 return tern_insert(head, key, val); 107 return tern_insert(head, key, val, TVAL_INT);
105 } 108 }
106 109
107 void * tern_find_ptr_default(tern_node * head, char const * key, void * def) 110 void * tern_find_ptr_default(tern_node * head, char const * key, void * def)
108 { 111 {
109 tern_val ret; 112 tern_val ret;
110 if (tern_find(head, key, &ret)) { 113 uint8_t valtype = tern_find(head, key, &ret);
111 if (ret.intval & 1) { 114 if (valtype == TVAL_PTR) {
112 return (void *)(ret.intval & ~1); 115 return ret.ptrval;
113 } else {
114 return ret.ptrval;
115 }
116 } 116 }
117 return def; 117 return def;
118 } 118 }
119 119
120 void * tern_find_ptr(tern_node * head, char const * key) 120 void * tern_find_ptr(tern_node * head, char const * key)
121 { 121 {
122 return tern_find_ptr_default(head, key, NULL); 122 return tern_find_ptr_default(head, key, NULL);
123 } 123 }
124 124
125 tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def) 125 tern_node *tern_find_node(tern_node *head, char const *key)
126 {
127 tern_val ret;
128 uint8_t valtype = tern_find(head, key, &ret);
129 if (valtype == TVAL_NODE) {
130 return ret.ptrval;
131 }
132 return NULL;
133 }
134
135 tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype)
126 { 136 {
127 tern_val ret; 137 tern_val ret;
128 while (*key) 138 while (*key)
129 { 139 {
130 if (!tern_find(head, key, &ret)) { 140 uint8_t valtype = tern_find(head, key, &ret);
141 if (!valtype) {
131 return def; 142 return def;
132 } 143 }
133 key = key + strlen(key) + 1; 144 key = key + strlen(key) + 1;
134 if (*key) { 145 if (*key) {
135 head = tern_get_node(ret); 146 if (valtype != TVAL_NODE) {
136 if (!head) {
137 return def; 147 return def;
138 } 148 }
149 head = ret.ptrval;
150 } else if (req_valtype && req_valtype != valtype) {
151 return def;
139 } 152 }
140 } 153 }
141 return ret; 154 return ret;
142 } 155 }
143 156
144 tern_val tern_find_path(tern_node *head, char const *key) 157 tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype)
145 { 158 {
146 tern_val def; 159 tern_val def;
147 def.ptrval = NULL; 160 def.ptrval = NULL;
148 return tern_find_path_default(head, key, def); 161 return tern_find_path_default(head, key, def, valtype);
149 } 162 }
150 163
151 tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value) 164 tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value)
152 { 165 {
153 tern_val val; 166 tern_val val;
154 val.ptrval = value; 167 val.ptrval = value;
155 return tern_insert(head, key, val); 168 return tern_insert(head, key, val, TVAL_PTR);
156 } 169 }
157 170
158 tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value) 171 tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value)
159 { 172 {
160 tern_val val; 173 tern_val val;
161 val.intval = ((intptr_t)value) | 1; 174 val.ptrval = value;
162 return tern_insert(head, key, val); 175 return tern_insert(head, key, val, TVAL_NODE);
163 } 176 }
164 177
165 uint32_t tern_count(tern_node *head) 178 uint32_t tern_count(tern_node *head)
166 { 179 {
167 uint32_t count = 0; 180 uint32_t count = 0;
182 #define MAX_ITER_KEY 127 195 #define MAX_ITER_KEY 127
183 void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, int pos) 196 void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, int pos)
184 { 197 {
185 if (!head->el) { 198 if (!head->el) {
186 keybuf[pos] = 0; 199 keybuf[pos] = 0;
187 fun(keybuf, head->straight.value, data); 200 fun(keybuf, head->straight.value, head->valtype, data);
188 } 201 }
189 if (head->left) { 202 if (head->left) {
190 tern_foreach_int(head->left, fun, data, keybuf, pos); 203 tern_foreach_int(head->left, fun, data, keybuf, pos);
191 } 204 }
192 if (head->el) { 205 if (head->el) {
218 } 231 }
219 *cur = 0; 232 *cur = 0;
220 return buf; 233 return buf;
221 } 234 }
222 235
223 tern_node * tern_get_node(tern_val value)
224 {
225 return value.intval & 1 ? (tern_node *)(value.intval & ~1) : NULL;
226 }
227
228 void tern_free(tern_node *head) 236 void tern_free(tern_node *head)
229 { 237 {
230 if (head->left) { 238 if (head->left) {
231 tern_free(head->left); 239 tern_free(head->left);
232 } 240 }
234 tern_free(head->right); 242 tern_free(head->right);
235 } 243 }
236 if (head->el) { 244 if (head->el) {
237 tern_free(head->straight.next); 245 tern_free(head->straight.next);
238 } 246 }
239 } 247 free(head);
248 }