32 #ifndef _INCLUDE_SOURCEMOD_TEMPLATED_TRIE_H_
33 #define _INCLUDE_SOURCEMOD_TEMPLATED_TRIE_H_
79 bool remove(
const char *key)
81 KTrieNode *node = internal_retrieve(key);
82 if (!node || !node->valset)
103 KTrieNode *node = internal_retrieve(key);
104 if (!node || !node->valset)
120 KTrieNode *node = internal_retrieve(key);
121 if (!node || !node->valset)
123 *result = node->value;
136 KTrieNode *prev_node = internal_retrieve(key);
142 if (prev_node->valset)
144 prev_node->value.~K();
147 new (&prev_node->value) K(obj);
160 bool insert(
const char *key,
const K & obj)
162 unsigned int lastidx = 1;
164 const char *keyptr = key;
165 KTrieNode *node = NULL;
166 KTrieNode *basenode = NULL;
168 unsigned int curoffs;
176 if (m_empty != NULL && m_empty->valset)
183 m_empty = (KTrieNode *)malloc(
sizeof(KTrieNode));
186 m_empty->valset =
true;
187 new (&m_empty->value) K(obj);
198 curidx = m_base[lastidx].idx;
199 basenode = &m_base[curidx];
200 curoffs = charval(*keyptr);
202 node = &m_base[curidx];
208 if ( (curidx > m_baseSize) || (node->mode == Node_Unused) )
210 if (curidx > m_baseSize)
216 node = &m_base[curidx];
218 node->parent = lastidx;
221 node->mode = Node_Arc;
225 node->idx = x_addstring(keyptr);
226 node->mode = Node_Term;
229 new (&node->value) K(obj);
235 else if (node->parent != lastidx)
256 unsigned int outgoing_base = m_base[lastidx].idx;
257 unsigned int outgoing_list[256];
258 unsigned int outgoing_count = 0;
259 cur = &m_base[outgoing_base] + 1;
260 unsigned int outgoing_limit = 255;
262 if (outgoing_base + outgoing_limit > m_baseSize)
264 outgoing_limit = m_baseSize - outgoing_base;
267 for (
unsigned int i=1; i<=outgoing_limit; i++,cur++)
269 if (cur->mode == Node_Unused || cur->parent != lastidx)
273 outgoing_list[outgoing_count++] = i;
275 outgoing_list[outgoing_count++] = curidx - outgoing_base;
280 assert(m_base[node->parent].mode == Node_Arc);
281 unsigned int incoming_list[256];
282 unsigned int incoming_base = m_base[node->parent].idx;
283 unsigned int incoming_count = 0;
284 unsigned int incoming_limit = 255;
285 cur = &m_base[incoming_base] + 1;
287 if (incoming_base + incoming_limit > m_baseSize)
289 incoming_limit = m_baseSize - incoming_base;
292 assert(incoming_limit > 0 && incoming_limit <= 255);
294 for (
unsigned int i=1; i<=incoming_limit; i++,cur++)
296 if (cur->mode == Node_Arc || cur->mode == Node_Term)
298 if (cur->parent == node->parent)
300 incoming_list[incoming_count++] = i;
305 if (incoming_count < outgoing_count + 1)
307 unsigned int q = x_check_multi(incoming_list, incoming_count);
309 node = &m_base[curidx];
312 m_base[node->parent].idx = q;
317 unsigned int idx, newidx, oldidx;
318 for (
unsigned int i=0; i<incoming_count; i++)
320 idx = incoming_list[i];
322 oldidx = incoming_base + idx;
323 if (oldidx == lastidx)
329 memcpy(&m_base[newidx], &m_base[oldidx],
sizeof(KTrieNode));
330 if (m_base[oldidx].valset)
332 new (&m_base[newidx].value) K(m_base[oldidx].value);
333 m_base[oldidx].value.~K();
335 assert(m_base[m_base[newidx].parent].mode == Node_Arc);
337 memset(&m_base[oldidx], 0,
sizeof(KTrieNode));
339 if (m_base[newidx].mode == Node_Arc)
341 KTrieNode *check_base = &m_base[m_base[newidx].idx] + 1;
342 outgoing_limit = (m_base + m_baseSize + 1) - check_base;
343 if (outgoing_limit > 255)
345 outgoing_limit = 255;
347 for (
unsigned int j=1; j<=outgoing_limit; j++, check_base++)
349 if (check_base->parent == oldidx)
351 check_base->parent = newidx;
359 unsigned int q = x_check_multi(outgoing_list, outgoing_count);
361 node = &m_base[curidx];
364 m_base[lastidx].idx = q;
374 unsigned int idx, newidx, oldidx;
375 for (
unsigned int i=0; i<outgoing_count; i++)
377 idx = outgoing_list[i];
379 oldidx = outgoing_base + idx;
380 if (oldidx == lastidx)
386 memcpy(&m_base[newidx], &m_base[oldidx],
sizeof(KTrieNode));
387 if (m_base[oldidx].valset)
389 new (&m_base[newidx].value) K(m_base[oldidx].value);
390 m_base[oldidx].value.~K();
392 assert(m_base[m_base[newidx].parent].mode == Node_Arc);
394 memset(&m_base[oldidx], 0,
sizeof(KTrieNode));
396 if (m_base[newidx].mode == Node_Arc)
398 KTrieNode *check_base = &m_base[m_base[newidx].idx] + 1;
399 outgoing_limit = (m_base + m_baseSize + 1) - check_base;
400 if (outgoing_limit > 255)
402 outgoing_limit = 255;
404 for (
unsigned int j=1; j<=outgoing_limit; j++, check_base++)
406 if (check_base->parent == oldidx)
408 check_base->parent = newidx;
415 node = &m_base[q + outgoing_list[outgoing_count]];
419 node->parent = lastidx;
422 node->mode = Node_Arc;
426 node->idx = x_addstring(keyptr);
427 node->mode = Node_Term;
430 new (&node->value) K(obj);
439 if (node->mode == Node_Term)
444 char *term = &m_stringtab[node->idx];
446 if (strcmp(keyptr, term) == 0)
451 new (&node->value) K(obj);
466 bool oldvalset = node->valset;
469 oldvalue = node->value;
471 if (*term == *keyptr)
473 while (*term == *keyptr)
479 node = &m_base[curidx];
482 node->mode = Node_Arc;
483 if (node->valset ==
true)
486 node->valset =
false;
490 curidx = q + charval(*term);
491 node = &m_base[curidx];
493 node->parent = lastidx;
494 node->mode = Node_Arc;
500 else if (node->valset)
502 node->valset =
false;
514 node->valset = oldvalset;
517 new (&node->value) K(oldvalue);
527 q = x_check(*keyptr);
528 node = &m_base[curidx];
531 node->mode = Node_Arc;
534 curidx = q + charval(*keyptr);
535 node = &m_base[curidx];
540 node->mode = Node_Arc;
544 node->idx = x_addstring(keyptr);
545 node->mode = Node_Term;
547 node->parent = lastidx;
549 new (&node->value) K(obj);
551 else if (*keyptr ==
'\0')
557 new (&node->value) K(obj);
561 node = &m_base[curidx];
564 node->mode = Node_Arc;
567 curidx = q + charval(*term);
568 node = &m_base[curidx];
573 node->mode = Node_Arc;
577 node->idx = (term - m_stringtab);
578 node->mode = Node_Term;
580 node->parent = lastidx;
581 node->valset = oldvalset;
584 new (&node->value) K(oldvalue);
590 node->mode = Node_Arc;
593 q = x_check2(*keyptr, *term);
594 node = &m_base[curidx];
600 curidx = q + charval(*term);
601 node = &m_base[curidx];
603 node->valset = oldvalset;
606 new (&node->value) K(oldvalue);
608 node->parent = lastidx;
611 node->mode = Node_Arc;
615 node->mode = Node_Term;
616 node->idx = (term - m_stringtab);
620 curidx = q + charval(*keyptr);
621 node = &m_base[curidx];
624 new (&node->value) K(obj);
625 node->parent = lastidx;
628 node->mode = Node_Arc;
632 node->mode = Node_Term;
633 node->idx = x_addstring(keyptr);
644 assert(node->mode == Node_Arc);
648 }
while (*keyptr !=
'\0');
659 assert(node->mode == Node_Arc);
664 new (&node->value) K(obj);
693 void (*func)(
KTrie *,
const char *, K & obj,
void *data))
695 bad_iterator_r(buffer, maxlength, 0, data, func, 1);
699 void bad_iterator_r(
char *buffer,
703 void (*func)(
KTrie *,
const char *, K & obj,
void *data),
707 unsigned int idx, limit, start;
710 start = m_base[root].idx;
713 if (start + limit > m_baseSize)
715 limit = m_baseSize - start;
719 for (
unsigned int i = 1; i <= limit; i++)
722 if (m_base[idx].mode == Node_Unused
723 || m_base[idx].parent != root)
728 if (m_base[idx].mode == Node_Arc)
730 if (buf_pos < maxlength - 1)
732 buffer[buf_pos++] = (char)i;
735 if (m_base[idx].valset)
737 buffer[buf_pos] =
'\0';
738 func(
this, buffer, m_base[idx].value, data);
741 bad_iterator_r(buffer,
750 else if (m_base[idx].mode == Node_Term
751 && m_base[idx].valset ==
true)
755 save_buf_pos = buf_pos;
756 if (buf_pos < maxlength - 1)
758 buffer[buf_pos++] = (char)i;
760 if (buf_pos < maxlength - 1)
764 term = &m_stringtab[m_base[idx].idx];
765 destlen = strlen(term);
767 j < destlen && j + buf_pos < maxlength - 1;
770 buffer[buf_pos + j] = term[j];
774 buffer[buf_pos] =
'\0';
776 func(
this, buffer, m_base[idx].value, data);
778 buf_pos = save_buf_pos;
785 m_base = (KTrieNode *)malloc(
sizeof(KTrieNode) * (256 + 1));
786 m_stringtab = (
char *)malloc(
sizeof(
char) * 256);
796 if (m_empty != NULL && m_empty->valset)
799 m_empty->valset =
false;
806 void run_destructor(
void (*dtor)(K * ptr))
808 for (
size_t i = 0; i <= m_baseSize; i++)
810 if (m_base[i].valset)
812 dtor(&m_base[i].value);
813 m_base[i].valset =
false;
840 KTrieNode *internal_retrieve(
const char *key)
842 unsigned int lastidx = 1;
844 const char *keyptr = key;
845 KTrieNode *node = NULL;
856 curidx = m_base[lastidx].idx;
857 node = &m_base[curidx];
858 curidx += charval(*keyptr);
859 node = &m_base[curidx];
863 if ((curidx > m_baseSize) || node->mode == Node_Unused || node->parent != lastidx)
867 else if (node->mode == Node_Term)
869 char *term = &m_stringtab[node->idx];
870 if (strcmp(keyptr, term) == 0)
880 }
while (*keyptr !=
'\0');
887 unsigned int cur_size = m_baseSize;
888 unsigned int new_size = cur_size * 2;
890 KTrieNode *new_base = (KTrieNode *)malloc((new_size + 1) *
sizeof(KTrieNode));
896 memcpy(new_base, m_base,
sizeof(KTrieNode) * (m_baseSize + 1));
897 memset(&new_base[cur_size + 1], 0, (new_size - cur_size) *
sizeof(KTrieNode));
899 for (
size_t i = 0; i <= m_baseSize; i++)
901 if (m_base[i].valset)
904 new (&new_base[i].value) K(m_base[i].value);
905 m_base[i].value.~K();
911 m_baseSize = new_size;
915 inline unsigned char charval(
char c)
917 return (
unsigned char)c;
919 void internal_clear()
924 memset(m_base, 0,
sizeof(KTrieNode) * (m_baseSize + 1));
925 memset(m_stringtab, 0,
sizeof(
char) * m_stSize);
929 m_base[1].mode = Node_Arc;
930 m_base[1].parent = 1;
932 void run_destructors()
934 for (
size_t i = 0; i <= m_baseSize; i++)
936 if (m_base[i].valset)
938 m_base[i].value.~K();
942 unsigned int x_addstring(
const char *ptr)
944 size_t len = strlen(ptr) + 1;
946 if (m_tail + len >= m_stSize)
948 while (m_tail + len >= m_stSize)
952 m_stringtab = (
char *)realloc(m_stringtab,m_stSize);
955 unsigned int tail = m_tail;
956 strcpy(&m_stringtab[tail], ptr);
961 unsigned int x_check(
char c,
unsigned int start=1)
963 unsigned char _c = charval(c);
964 unsigned int to_check = m_baseSize - _c;
965 for (
unsigned int i=start; i<=to_check; i++)
967 if (m_base[i+_c].mode == Node_Unused)
975 return x_check(c, to_check+1);
977 unsigned int x_check2(
char c1,
char c2,
unsigned int start=1)
979 unsigned char _c1 = charval(c1);
980 unsigned char _c2 = charval(c2);
981 unsigned int to_check = m_baseSize - (_c1 > _c2 ? _c1 : _c2);
982 for (
unsigned int i=start; i<=to_check; i++)
984 if (m_base[i+_c1].mode == Node_Unused
985 && m_base[i+_c2].mode == Node_Unused)
993 return x_check2(c1, c2, to_check+1);
995 unsigned int x_check_multi(
996 unsigned int offsets[],
998 unsigned int start=1)
1001 unsigned int to_check = m_baseSize;
1002 unsigned int highest = 0;
1004 for (
unsigned int i=0; i<count; i++)
1006 if (offsets[i] > highest)
1008 highest = offsets[i];
1012 to_check -= highest;
1014 for (
unsigned int i=start; i<=to_check; i++)
1017 for (
unsigned int j=0; j<count; j++)
1019 cur = &m_base[i+offsets[j]];
1020 if (cur->mode != Node_Unused)
1034 return x_check_multi(offsets, count, to_check+1);
1039 return (
sizeof(KTrieNode) * (m_baseSize))
1041 +
sizeof(KTrieNode);
1045 return m_numElements;
1051 unsigned int m_baseSize;
1052 unsigned int m_stSize;
1053 unsigned int m_tail;
1054 size_t m_numElements;
1122 #endif //_INCLUDE_SOURCEMOD_TEMPLATED_TRIE_H_
bool insert(const char *key, const K &obj)
Inserts an object at a key.
Definition: sm_trie_tpl.h:160
bool replace(const char *key, const K &obj)
Inserts or updates the object stored at a key.
Definition: sm_trie_tpl.h:134
bool retrieve(const char *key, K *result)
Wrapper around retrieve(key) for a cleaner API.
Definition: sm_trie_tpl.h:118
void bad_iterator(char *buffer, size_t maxlength, void *data, void(*func)(KTrie *, const char *, K &obj, void *data))
Iterates over the trie returning all known values.
Definition: sm_trie_tpl.h:690
NodeType
Definition: sm_trie_tpl.h:40
K * retrieve(const char *key)
Retrieves a pointer to the object stored at a given key.
Definition: sm_trie_tpl.h:101
Definition: sm_trie_tpl.h:60
void clear()
Clears all set objects in the trie.
Definition: sm_trie_tpl.h:67