nedtries  v1.03 trunk (?)
nedtrie.h
Go to the documentation of this file.
1 /* An in-place binary trie implementation for C and C++ aka. the
2 ridiculously fast way of indexing stuff. (C) 2010-2012 Niall Douglas.
3 
4 
5 Boost Software License - Version 1.0 - August 17th, 2003
6 
7 Permission is hereby granted, free of charge, to any person or organization
8 obtaining a copy of the software and accompanying documentation covered by
9 this license (the "Software") to use, reproduce, display, distribute,
10 execute, and transmit the Software, and to prepare derivative works of the
11 Software, and to permit third-parties to whom the Software is furnished to
12 do so, all subject to the following:
13 
14 The copyright notices in the Software and this entire statement, including
15 the above license grant, this restriction and the following disclaimer,
16 must be included in all copies of the Software, in whole or in part, and
17 all derivative works of the Software, unless such copies or derivative
18 works are solely in the form of machine-executable object code generated by
19 a source language processor.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 */
29 
30 #include <assert.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h> /* for memset */
34 #include <limits.h> /* For INT_MAX */
35 
36 #ifdef _MSC_VER
37 /* Disable stupid warnings */
38 #pragma warning(push)
39 #pragma warning(disable: 4702) /* unreachable code */
40 #pragma warning(disable: 4706) /* assignment within conditional expression */
41 #pragma warning(disable: 4127) /* conditional expression is constant */
42 #pragma warning(disable: 4133) /* incompatible types */
43 #endif
44 
47 #ifndef RESTRICT
48 #if __STDC_VERSION__ >= 199901L /* C99 or better */
49  #define RESTRICT restrict
50 #else
51  #if defined(_MSC_VER) && _MSC_VER>=1400
52  #define RESTRICT __restrict
53  #endif
54  #ifdef __GNUC__
55  #define RESTRICT __restrict
56  #endif
57 #endif
58 #ifndef RESTRICT
59  #define RESTRICT
60 #endif
61 #endif
62 
65 #ifndef INLINE
66 #if __STDC_VERSION__ >= 199901L /* C99 or better */ || defined(__cplusplus)
67  #define INLINE inline
68 #else
69  #if defined(_MSC_VER)
70  #define INLINE __inline
71  #endif
72  #ifdef __GNUC__
73  #define INLINE __inline
74  #endif
75 #endif
76 #ifndef INLINE
77  #define INLINE
78 #endif
79 #endif
80 
83 #ifndef NOINLINE
84  #if defined(__GNUC__)
85  #define NOINLINE __attribute__ ((noinline))
86  #elif defined(_MSC_VER)
87  #define NOINLINE __declspec(noinline)
88  #else
89  #define NOINLINE
90  #endif
91 #endif
92 
96 #ifndef DEBUGINLINE
97 #ifdef NDEBUG
98 #define DEBUGINLINE INLINE
99 #elif defined(DEBUG)
100 #define DEBUGINLINE NOINLINE
101 #else
102 #define DEBUGINLINE
103 #endif
104 #endif
105 
111 #ifndef NEDTRIEUSEMACROS
112 #ifdef __cplusplus
113 #define NEDTRIEUSEMACROS 0
114 #else
115 #define NEDTRIEUSEMACROS 1
116 #endif
117 #endif
118 
123 #ifndef NEDTRIEDEBUG
124 #ifdef DEBUG
125 #define NEDTRIEDEBUG 1
126 #else
127 #define NEDTRIEDEBUG 0
128 #endif
129 #endif
130 #ifdef NDEBUG
131 #undef NEDTRIEDEBUG
132 #define NEDTRIEDEBUG 0
133 #endif
134 
135 /* Define bit scanning intrinsics */
136 #ifdef _MSC_VER
137 #include <intrin.h>
138 #endif
139 
140 #ifdef __cplusplus
141 #include <list>
142 #if (defined(_MSC_VER) && _MSC_VER<=1500) || (defined(__GNUC__) && !defined(HAVE_CPP0X))
143 // Doesn't have std::move<> by default, so define
144 namespace std
145 {
146  template<class T> T &move(T &a) { return a; }
147  template<class T> T &move(const T &a) { return const_cast<T &>(a); }
148  template<class T, class A> T &forward(A &a) { return a; }
149 }
150 #endif
151 namespace {
152 #endif
153 static INLINE unsigned nedtriebitscanr(size_t value)
154 {
155  if(!value) return 0;
156 #if defined(_MSC_VER) && !defined(__cplusplus_cli)
157  {
158  unsigned long bitpos;
159 #if defined(_M_IA64) || defined(_M_X64) || defined(WIN64)
160  assert(8==sizeof(size_t));
161  _BitScanReverse64(&bitpos, value);
162 #else
163  assert(4==sizeof(size_t));
164  _BitScanReverse(&bitpos, value);
165 #endif
166  return (unsigned) bitpos;
167  }
168 #elif defined(__GNUC__)
169  return sizeof(value)*CHAR_BIT - 1 - (unsigned) __builtin_clzl(value);
170 #else
171  /* The following code is illegal C, but it almost certainly will work.
172  If not use the legal implementation below */
173 #if !defined(__cplusplus_cli)
174  union {
175  unsigned asInt[2];
176  double asDouble;
177  };
178  int n;
179 
180  asDouble = (double)value + 0.5;
181  n = (asInt[0 /*Use 1 if your CPU is big endian!*/] >> 20) - 1023;
182 #ifdef _MSC_VER
183 #pragma message(__FILE__ ": WARNING: Make sure you change the line above me if your CPU is big endian!")
184 #else
185 #warning Make sure you change the line above me if your CPU is big endian!
186 #endif
187  return (unsigned) n;
188 #else
189 #if CHAR_BIT != 8
190 #error CHAR_BIT is not eight, and therefore this generic bitscan routine will need adjusting!
191 #endif
192  /* This is a generic 32 and 64 bit compatible branch free bitscan right */
193  size_t x=value;
194  x = x | (x >> 1);
195  x = x | (x >> 2);
196  x = x | (x >> 4);
197  x = x | (x >> 8);
198  if(16 < sizeof(x)*CHAR_BIT) x = x | (x >>16);
199  if(32 < sizeof(x)*CHAR_BIT) x = x | (x >>32);
200  x = ~x;
201  x = x - ((x >> 1) & (SIZE_MAX/3));
202  x = (x & (SIZE_MAX/15*3)) + ((x >> 2) & (SIZE_MAX/15*3));
203  x = ((x + (x >> 4)) & (SIZE_MAX/UCHAR_MAX*15)) * (SIZE_MAX/UCHAR_MAX);
204  x = (CHAR_BIT*sizeof(x)-1) - (x >> (CHAR_BIT*(sizeof(x)-1)));
205  return (unsigned) x;
206 #endif
207 #endif
208 }
209 
210 #ifdef __cplusplus
211 } /* Anonymous namespace */
212 #endif
213 
217 #define NEDTRIE_INDEXBINS (8*sizeof(void *))
218 
221 #define NEDTRIE_HEAD2(name, type) \
222 struct name { \
223  size_t count; \
224  type *triebins[NEDTRIE_INDEXBINS]; /* each containing (1<<x)<=bitscanrev(x)<(1<<(x+1)) */ \
225  int nobbledir; \
226 }
227 #define NEDTRIE_HEAD(name, type) NEDTRIE_HEAD2(name, struct type)
228 
231 #define NEDTRIE_ENTRY(type) \
232 struct { \
233  struct type *trie_parent; /* parent element */ \
234  struct type *trie_child[2]; /* my children based on whether they are zero or one. */ \
235  struct type *trie_prev, *trie_next; /* my siblings of identical key to me. */ \
236 }
237 #define NEDTRIE_INITIALIZER(root)
238 
241 #define NEDTRIE_INIT(root) do { memset((root), 0, sizeof(*(root))); } while(0)
242 
245 #define NEDTRIE_EMPTY(head) (!(head)->count)
246 
249 #define NEDTRIE_COUNT(head) ((head)->count)
250 
251 /* As macro instantiated code is a royal PITA to debug and even to see what
252 the hell is going on, we use a templated implementation when in C++. This
253 aids future debuggability by keeping the template and macro implementations
254 side by side and hopefully harmonised. */
255 #ifdef __cplusplus
256 namespace nedtries {
257 
258  template<class trietype> int trienobblezeros(trietype *)
259  {
260  return 0;
261  }
262  template<class trietype> int trienobbleones(trietype *)
263  {
264  return 1;
265  }
266  template<class trietype> int trienobbleequally(trietype *head)
267  {
268  return (head->nobbledir=!head->nobbledir);
269  }
273 #define NEDTRIE_NOBBLEZEROS(name) nedtries::trienobblezeros<name>
274 
277 #define NEDTRIE_NOBBLEONES(name) nedtries::trienobbleones<name>
278 
281 #define NEDTRIE_NOBBLEEQUALLY(name) nedtries::trienobbleequally<name>
282 #define NEDTRIE_GENERATE_NOBBLES(proto, name, type, field, keyfunct)
283 #else
284 #define NEDTRIE_NOBBLEZEROS(name) name##_nobblezeros
285 #define NEDTRIE_NOBBLEONES(name) name##_nobbleones
286 #define NEDTRIE_NOBBLEEQUALLY(name) name##_nobbleequally
287 #define NEDTRIE_GENERATE_NOBBLES(proto, name, type, field, keyfunct) \
288  static INLINE int name##_nobblezeros(struct name *head) { (void) head; return 0; } \
289  static INLINE int name##_nobbleones(struct name *head) { (void) head; return 1; } \
290  static INLINE int name##_nobbleequally(struct name *head) { return (head->nobbledir=!head->nobbledir); }
291 #endif /* __cplusplus */
292 
293 #ifdef __cplusplus
294  template<class type> struct TrieLink_t {
295  type *trie_parent; /* parent element */
296  type *trie_child[2]; /* my children based on whether they are zero or one. */
297  type *trie_prev, *trie_next; /* my siblings of identical key to me. */
298  };
299  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE void triecheckvalidity(trietype *head);
300  namespace testtrielinksize {
301  struct foo1; struct foo2;
302  struct foo1 { NEDTRIE_ENTRY(foo1) link; size_t n; };
303  struct foo2 { TrieLink_t<foo2> link; size_t n; };
304  static char test_sizeof_trielink_t_equal[sizeof(foo1)==sizeof(foo2)];
305  }
306 
307 } /* namespace */
308 #endif
309 
310 /* GCC recently has started puking if you use operators -> and & in template parameters :( */
311 #ifdef __GNUC__
312 #define NEDTRIEFIELDOFFSET2(type, field) __builtin_offsetof(type, field)
313 #else
314 #define NEDTRIEFIELDOFFSET2(type, field) ((size_t) &(((type *)0)->field))
315 #endif
316 #define NEDTRIEFIELDOFFSET(type, field) NEDTRIEFIELDOFFSET2(struct type, field)
317 
318 #ifdef __cplusplus
319 namespace nedtries {
320  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE void trieinsert(trietype *RESTRICT head, type *RESTRICT r)
321  {
322  type *RESTRICT node, *RESTRICT childnode;
323  TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink;
324  size_t rkey=keyfunct(r), keybit, nodekey;
325  unsigned bitidx;
326  int keybitset;
327 
328  rlink=(TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
329  memset(rlink, 0, sizeof(TrieLink_t<type>));
330  bitidx=nedtriebitscanr(rkey);
331  assert(bitidx<NEDTRIE_INDEXBINS);
332  if(!(node=head->triebins[bitidx]))
333  { /* Bottom two bits set indicates a node hanging off of head */
334  rlink->trie_parent=(type *RESTRICT)(size_t)(3|(bitidx<<2));
335  head->triebins[bitidx]=r;
336  goto end;
337  }
338  /* Avoid variable bit shifts where possible, their performance can suck */
339  keybit=(size_t) 1<<bitidx;
340  for(;;node=childnode)
341  {
342  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
343  nodekey=keyfunct(node);
344  if(nodekey==rkey)
345  { /* Insert into ring list */
346  rlink->trie_parent=0;
347  rlink->trie_prev=node;
348  rlink->trie_next=nodelink->trie_next;
349  nodelink->trie_next=r;
350  if(rlink->trie_next) ((TrieLink_t<type> *RESTRICT)((size_t) rlink->trie_next + fieldoffset))->trie_prev=r;
351  break;
352  }
353  keybit>>=1;
354  keybitset=!!(rkey&keybit);
355  childnode=nodelink->trie_child[keybitset];
356  if(!childnode)
357  { /* Insert here */
358  rlink->trie_parent=node;
359  nodelink->trie_child[keybitset]=r;
360  break;
361  }
362  }
363 end:
364  head->count++;
365 #if NEDTRIEDEBUG
366  triecheckvalidity<trietype, type, fieldoffset, keyfunct>(head);
367 #endif
368  }
369 }
370 #endif /* __cplusplus */
371 #if NEDTRIEUSEMACROS
372 #define NEDTRIE_GENERATE_INSERT(proto, name, type, field, keyfunct) \
373  proto INLINE void name##_NEDTRIE_INSERT(struct name *RESTRICT head, struct type *RESTRICT r) \
374  { \
375  struct type *RESTRICT node, *RESTRICT childnode; \
376  size_t rkey=keyfunct(r), keybit, nodekey; \
377  unsigned bitidx; \
378  int keybitset; \
379 \
380  memset(&r->field, 0, sizeof(r->field)); \
381  bitidx=nedtriebitscanr(rkey); \
382  assert(bitidx<NEDTRIE_INDEXBINS); \
383  if(!(node=head->triebins[bitidx])) \
384  { /* Bottom two bits set indicates a node hanging off of head */ \
385  r->field.trie_parent=(struct type *RESTRICT)(size_t)(3|(bitidx<<2)); \
386  head->triebins[bitidx]=r; \
387  goto end; \
388  } \
389  /* Avoid variable bit shifts where possible, their performance can suck */ \
390  keybit=(size_t) 1<<bitidx; \
391  for(;;node=childnode) \
392  { \
393  nodekey=keyfunct(node); \
394  if(nodekey==rkey) \
395  { /* Insert into ring list */ \
396  r->field.trie_parent=0; \
397  r->field.trie_prev=node; \
398  r->field.trie_next=node->field.trie_next; \
399  node->field.trie_next=r; \
400  if(r->field.trie_next) r->field.trie_next->field.trie_prev=r; \
401  break; \
402  } \
403  keybit>>=1; \
404  keybitset=!!(rkey&keybit); \
405  childnode=node->field.trie_child[keybitset]; \
406  if(!childnode) \
407  { /* Insert here */ \
408  r->field.trie_parent=node; \
409  node->field.trie_child[keybitset]=r; \
410  break; \
411  } \
412  } \
413 end: \
414  head->count++; \
415  }
416 #else /* NEDTRIEUSEMACROS */
417 #define NEDTRIE_GENERATE_INSERT(proto, name, type, field, keyfunct) \
418  proto INLINE void name##_NEDTRIE_INSERT(struct name *RESTRICT head, struct type *RESTRICT r) \
419 { \
420  nedtries::trieinsert<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
421 }
422 #endif /* NEDTRIEUSEMACROS */
423 
424 #ifdef __cplusplus
425 namespace nedtries {
426  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT), int (*nobblefunct)(trietype *head)> DEBUGINLINE void trieremove(trietype *RESTRICT head, type *RESTRICT r)
427  {
428  type *RESTRICT node, **myaddrinparent=0;
429  TrieLink_t<type> *RESTRICT nodelink, *RESTRICT childlink, *RESTRICT rlink;
430  unsigned bitidx;
431 
432  rlink=(TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
433  /* Am I a leaf off the tree? */
434  if(rlink->trie_prev)
435  { /* Remove from linked list */
436  assert(!rlink->trie_parent);
437  node=rlink->trie_prev;
438  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
439  nodelink->trie_next=rlink->trie_next;
440  if(rlink->trie_next)
441  {
442  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) rlink->trie_next + fieldoffset);
443  nodelink->trie_prev=node;
444  }
445  goto functexit;
446  }
447  /* I must therefore be part of the tree */
448  assert(rlink->trie_parent);
449  assert(!rlink->trie_prev);
450  /* Am I at the top of the tree? */
451  if(((size_t) rlink->trie_parent & 3)==3)
452  { /* Extract my bitidx */
453  bitidx=(unsigned)(((size_t) rlink->trie_parent)>>2);
454  assert(head->triebins[bitidx]==r);
455  /* Set the node addr to be modified */
456  myaddrinparent=&head->triebins[bitidx];
457  }
458  else
459  { /* Otherwise I am one of my parent's children */
460  node=rlink->trie_parent;
461  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
462  myaddrinparent=(nodelink->trie_child[0]==r) ? &nodelink->trie_child[0] : &nodelink->trie_child[1];
463  }
464  assert(*myaddrinparent==r);
465  node=0;
466  /* Can I replace me with a sibling? */
467  if(rlink->trie_next)
468  {
469  node=rlink->trie_next;
470  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
471  assert(nodelink->trie_prev==r);
472  nodelink->trie_prev=0;
473  goto end;
474  }
475  /* Can I simply remove myself from my parent? */
476  if(!rlink->trie_child[0] && !rlink->trie_child[1])
477  goto end;
478  /* I need someone to replace me in the trie, so simply find any
479  grandchild of mine (who has the right bits to be here) which has no children.
480  */
481  {
482  type *RESTRICT *RESTRICT childaddrinparent=myaddrinparent, *RESTRICT *RESTRICT newchildaddrinparent;
483  int nobbledir=nobblefunct(head);
484  while(*(newchildaddrinparent=&(((TrieLink_t<type> *RESTRICT)((size_t) *childaddrinparent + fieldoffset))->trie_child[nobbledir]))
485  || *(newchildaddrinparent=&(((TrieLink_t<type> *RESTRICT)((size_t) *childaddrinparent + fieldoffset))->trie_child[!nobbledir])))
486  childaddrinparent=newchildaddrinparent;
487  node=*childaddrinparent;
488  *childaddrinparent=0;
489  }
490  end:
491  if(node)
492  {
493  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
494  assert(!nodelink->trie_child[0] && !nodelink->trie_child[1]);
495  nodelink->trie_parent=rlink->trie_parent;
496  nodelink->trie_child[0]=rlink->trie_child[0];
497  nodelink->trie_child[1]=rlink->trie_child[1];
498  if(nodelink->trie_child[0])
499  {
500  childlink=(TrieLink_t<type> *RESTRICT)((size_t) nodelink->trie_child[0] + fieldoffset);
501  childlink->trie_parent=node;
502  }
503  if(nodelink->trie_child[1])
504  {
505  childlink=(TrieLink_t<type> *RESTRICT)((size_t) nodelink->trie_child[1] + fieldoffset);
506  childlink->trie_parent=node;
507  }
508  }
509  *myaddrinparent=node;
510  functexit:
511  head->count--;
512 #if NEDTRIEDEBUG
513  triecheckvalidity<trietype, type, fieldoffset, keyfunct>(head);
514 #endif
515  }
516 }
517 #endif /* __cplusplus */
518 #if NEDTRIEUSEMACROS
519 #define NEDTRIE_GENERATE_REMOVE(proto, name, type, field, keyfunct, nobblefunct) \
520  proto INLINE void name##_NEDTRIE_REMOVE(struct name *RESTRICT head, struct type *RESTRICT r) \
521  { \
522  struct type *RESTRICT node, **myaddrinparent=0; \
523  unsigned bitidx; \
524 \
525  /* Am I a leaf off the tree? */ \
526  if(r->field.trie_prev) \
527  { /* Remove from linked list */ \
528  assert(!r->field.trie_parent); \
529  node=r->field.trie_prev; \
530  node->field.trie_next=r->field.trie_next; \
531  if(r->field.trie_next) \
532  { \
533  r->field.trie_next->field.trie_prev=node; \
534  } \
535  goto functexit; \
536  } \
537  /* I must therefore be part of the tree */ \
538  assert(r->field.trie_parent); \
539  assert(!r->field.trie_prev); \
540  /* Am I at the top of the tree? */ \
541  if(((size_t) r->field.trie_parent & 3)==3) \
542  { /* Extract my bitidx */ \
543  bitidx=(unsigned)(((size_t) r->field.trie_parent)>>2); \
544  assert(head->triebins[bitidx]==r); \
545  /* Set the node addr to be modified */ \
546  myaddrinparent=&head->triebins[bitidx]; \
547  } \
548  else \
549  { /* Otherwise I am one of my parent's children */ \
550  node=r->field.trie_parent; \
551  myaddrinparent=(node->field.trie_child[0]==r) ? &node->field.trie_child[0] : &node->field.trie_child[1]; \
552  } \
553  assert(*myaddrinparent==r); \
554  node=0; \
555  /* Can I replace me with a sibling? */ \
556  if(r->field.trie_next) \
557  { \
558  node=r->field.trie_next; \
559  assert(node->field.trie_prev==r); \
560  node->field.trie_prev=0; \
561  goto end; \
562  } \
563  /* Can I simply remove myself from my parent? */ \
564  if(!r->field.trie_child[0] && !r->field.trie_child[1]) \
565  goto end; \
566  /* I need someone to replace me in the trie, so simply find any \
567  grandchild of mine (who has the right bits to be here) which has no children. \
568  */ \
569  { \
570  struct type *RESTRICT *RESTRICT childaddrinparent=myaddrinparent, *RESTRICT *RESTRICT newchildaddrinparent; \
571  int nobbledir=nobblefunct(head); \
572  while(*(newchildaddrinparent=&(*childaddrinparent)->field.trie_child[nobbledir]) \
573  || *(newchildaddrinparent=&(*childaddrinparent)->field.trie_child[!nobbledir])) \
574  childaddrinparent=newchildaddrinparent; \
575  node=*childaddrinparent; \
576  *childaddrinparent=0; \
577  } \
578  end: \
579  if(node) \
580  { \
581  assert(!node->field.trie_child[0] && !node->field.trie_child[1]); \
582  node->field.trie_parent=r->field.trie_parent; \
583  node->field.trie_child[0]=r->field.trie_child[0]; \
584  node->field.trie_child[1]=r->field.trie_child[1]; \
585  if(node->field.trie_child[0]) \
586  { \
587  node->field.trie_child[0]->field.trie_parent=node; \
588  } \
589  if(node->field.trie_child[1]) \
590  { \
591  node->field.trie_child[1]->field.trie_parent=node; \
592  } \
593  } \
594  *myaddrinparent=node; \
595  functexit: \
596  head->count--; \
597  }
598 #else /* NEDTRIEUSEMACROS */
599 #define NEDTRIE_GENERATE_REMOVE(proto, name, type, field, keyfunct, nobblefunct) \
600  proto INLINE void name##_NEDTRIE_REMOVE(struct name *RESTRICT head, struct type *RESTRICT r) \
601 { \
602  nedtries::trieremove<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct, nobblefunct>(head, r); \
603 }
604 #endif /* NEDTRIEUSEMACROS */
605 
606 #ifdef __cplusplus
607 namespace nedtries {
608  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *triefind(const trietype *RESTRICT head, const type *RESTRICT r)
609  {
610  const type *RESTRICT node, *RESTRICT childnode;
611  const TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink;
612  size_t rkey=keyfunct(r), keybit, nodekey;
613  unsigned bitidx;
614  int keybitset;
615 
616  if(!head->count) return 0;
617  rlink=(const TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
618  bitidx=nedtriebitscanr(rkey);
619  assert(bitidx<NEDTRIE_INDEXBINS);
620  if(!(node=head->triebins[bitidx]))
621  return 0;
622  /* Avoid variable bit shifts where possible, their performance can suck */
623  keybit=(size_t) 1<<bitidx;
624  for(;;node=childnode)
625  {
626  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
627  nodekey=keyfunct(node);
628  if(nodekey==rkey)
629  goto end;
630  keybit>>=1;
631  keybitset=!!(rkey&keybit);
632  childnode=nodelink->trie_child[keybitset];
633  if(!childnode)
634  return 0;
635  }
636  return 0;
637  end:
638  return nodelink->trie_next ? nodelink->trie_next : (type *) node;
639  }
640 }
641 #endif /* __cplusplus */
642 #if NEDTRIEUSEMACROS
643 #define NEDTRIE_GENERATE_FIND(proto, name, type, field, keyfunct) \
644  proto INLINE struct type * name##_NEDTRIE_FIND(struct name *RESTRICT head, struct type *RESTRICT r) \
645  { \
646  struct type *RESTRICT node, *RESTRICT childnode; \
647  size_t rkey=keyfunct(r), keybit, nodekey; \
648  unsigned bitidx; \
649  int keybitset; \
650 \
651  if(!head->count) return 0; \
652  bitidx=nedtriebitscanr(rkey); \
653  assert(bitidx<NEDTRIE_INDEXBINS); \
654  if(!(node=head->triebins[bitidx])) \
655  return 0; \
656  /* Avoid variable bit shifts where possible, their performance can suck */ \
657  keybit=(size_t) 1<<bitidx; \
658  for(;;node=childnode) \
659  { \
660  nodekey=keyfunct(node); \
661  if(nodekey==rkey) \
662  goto end; \
663  keybit>>=1; \
664  keybitset=!!(rkey&keybit); \
665  childnode=node->field.trie_child[keybitset]; \
666  if(!childnode) \
667  return 0; \
668  } \
669  return 0; \
670  end: \
671  return node->field.trie_next ? node->field.trie_next : node; \
672  }
673 #else /* NEDTRIEUSEMACROS */
674 #define NEDTRIE_GENERATE_FIND(proto, name, type, field, keyfunct) \
675  proto INLINE struct type * name##_NEDTRIE_FIND(struct name *RESTRICT head, struct type *RESTRICT r) \
676 { \
677  return nedtries::triefind<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
678 }
679 #endif /* NEDTRIEUSEMACROS */
680 
681 #ifdef __cplusplus
682 namespace nedtries {
683  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE int trieexactfind(const trietype *RESTRICT head, const type *RESTRICT r)
684  {
685  const type *RESTRICT node;
686  const TrieLink_t<type> *RESTRICT nodelink;
687 
688  if(!head->count) return 0;
689  if(!(node=triefind<trietype, type, fieldoffset, keyfunct>(head, r))) return 0;
690  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
691  if(nodelink->trie_prev) node=nodelink->trie_prev;
692  do
693  {
694  if(node==r) return 1;
695  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
696  node=nodelink->trie_next;
697  } while(node);
698  return 0;
699  }
700 }
701 #endif /* __cplusplus */
702 #if NEDTRIEUSEMACROS
703 #define NEDTRIE_GENERATE_EXACTFIND(proto, name, type, field, keyfunct) \
704  proto INLINE int name##_NEDTRIE_EXACTFIND(struct name *RESTRICT head, struct type *RESTRICT r) \
705  { \
706  struct type *RESTRICT node; \
707 \
708  if(!head->count) return 0; \
709  if(!(node=name##_NEDTRIE_FIND(head, r))) return 0; \
710  if(node->field.trie_prev) node=node->field.trie_prev; \
711  do \
712  { \
713  if(node==r) return 1; \
714  node=node->field.trie_next; \
715  } while(node); \
716  return 0; \
717  }
718 #else /* NEDTRIEUSEMACROS */
719 #define NEDTRIE_GENERATE_EXACTFIND(proto, name, type, field, keyfunct) \
720  proto INLINE int name##_NEDTRIE_EXACTFIND(struct name *RESTRICT head, struct type *RESTRICT r) \
721 { \
722  return nedtries::trieexactfind<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
723 }
724 #endif /* NEDTRIEUSEMACROS */
725 
726 #ifdef __cplusplus
727 namespace nedtries {
728  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *trieCfind(const trietype *RESTRICT head, const type *RESTRICT r, int rounds)
729  {
730  const type *RESTRICT node=0, *RESTRICT childnode, *RESTRICT ret=0;
731  const TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink;
732  size_t rkey=keyfunct(r), keybit, nodekey;
733  unsigned binbitidx;
734  int keybitset;
735 
736  if(!head->count) return 0;
737  rlink=(const TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
738  binbitidx=nedtriebitscanr(rkey);
739  assert(binbitidx<NEDTRIE_INDEXBINS);
740  do
741  {
742  size_t retkey=(size_t)-1;
743  unsigned bitidx;
744  /* Keeping raising the bin until we find a larger key */
745  while(binbitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[binbitidx]))
746  binbitidx++;
747  if(binbitidx>=NEDTRIE_INDEXBINS)
748  return 0;
749  bitidx=binbitidx;
750  /* Avoid variable bit shifts where possible, their performance can suck */
751  keybit=(size_t) 1<<bitidx;
752  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
753  nodekey=keyfunct(node);
754  /* If nodekey is a closer fit to search key, mark as best result so far */
755  if(nodekey>=rkey && nodekey-rkey<retkey)
756  {
757  ret=node;
758  retkey=nodekey-rkey;
759  }
760  if(rounds--<=0 && ret) return (type *) ret;
761  for(;;node=childnode)
762  {
763  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
764  /* If a child is a closer fit to search key, mark as best result so far */
765  if(nodelink->trie_child[0])
766  {
767  nodekey=keyfunct(nodelink->trie_child[0]);
768  if(nodekey>=rkey && nodekey-rkey<retkey)
769  {
770  ret=nodelink->trie_child[0];
771  retkey=nodekey-rkey;
772  }
773  }
774  if(nodelink->trie_child[1])
775  {
776  nodekey=keyfunct(nodelink->trie_child[1]);
777  if(nodekey>=rkey && nodekey-rkey<retkey)
778  {
779  ret=nodelink->trie_child[1];
780  retkey=nodekey-rkey;
781  }
782  }
783  if(rounds--<=0 && ret) return (type *) ret;
784  /* Which child branch should we check? */
785  keybit>>=1;
786  keybitset=!!(rkey&keybit);
787  childnode=nodelink->trie_child[keybitset];
788  /* If no child and we were checking lowest, check highest */
789  if(!childnode && !keybitset)
790  childnode=nodelink->trie_child[1];
791  if(!childnode) break;
792  }
793  if(!ret)
794  { /* If we didn't find any node bigger than rkey, bump up a bin
795  and look for the smallest possible key in that */
796  binbitidx++;
797  /* From now on, always match lowest */
798  retkey+=rkey;
799  rkey=0;
800  continue;
801  }
802  } while(!ret);
803  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) ret + fieldoffset);
804  return nodelink->trie_next ? nodelink->trie_next : (type *) ret;
805  }
806 }
807 #endif /* __cplusplus */
808 #if NEDTRIEUSEMACROS
809 #define NEDTRIE_GENERATE_CFIND(proto, name, type, field, keyfunct) \
810  proto INLINE struct type * name##_NEDTRIE_CFIND(struct name *RESTRICT head, struct type *RESTRICT r, int rounds) \
811  { \
812  struct type *RESTRICT node=0, *RESTRICT childnode, *RESTRICT ret=0; \
813  size_t rkey=keyfunct(r), keybit, nodekey; \
814  unsigned binbitidx; \
815  int keybitset; \
816  \
817  if(!head->count) return 0; \
818  binbitidx=nedtriebitscanr(rkey); \
819  assert(binbitidx<NEDTRIE_INDEXBINS); \
820  do \
821  { \
822  size_t retkey=(size_t)-1; \
823  unsigned bitidx; \
824  /* Keeping raising the bin until we find a larger key */ \
825  while(binbitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[binbitidx])) \
826  binbitidx++; \
827  if(binbitidx>=NEDTRIE_INDEXBINS) \
828  return 0; \
829  bitidx=binbitidx; \
830  /* Avoid variable bit shifts where possible, their performance can suck */ \
831  keybit=(size_t) 1<<bitidx; \
832  nodekey=keyfunct(node); \
833  /* If nodekey is a closer fit to search key, mark as best result so far */ \
834  if(nodekey>=rkey && nodekey-rkey<retkey) \
835  { \
836  ret=node; \
837  retkey=nodekey-rkey; \
838  } \
839  if(rounds--<=0 && ret) return ret; \
840  for(;;node=childnode) \
841  { \
842  /* If a child is a closer fit to search key, mark as best result so far */ \
843  if(node->field.trie_child[0]) \
844  { \
845  nodekey=keyfunct(node->field.trie_child[0]); \
846  if(nodekey>=rkey && nodekey-rkey<retkey) \
847  { \
848  ret=node->field.trie_child[0]; \
849  retkey=nodekey-rkey; \
850  } \
851  } \
852  if(node->field.trie_child[1]) \
853  { \
854  nodekey=keyfunct(node->field.trie_child[1]); \
855  if(nodekey>=rkey && nodekey-rkey<retkey) \
856  { \
857  ret=node->field.trie_child[1]; \
858  retkey=nodekey-rkey; \
859  } \
860  } \
861  if(rounds--<=0 && ret) return ret; \
862  /* Which child branch should we check? */ \
863  keybit>>=1; \
864  keybitset=!!(rkey&keybit); \
865  childnode=node->field.trie_child[keybitset]; \
866  /* If no child and we were checking lowest, check highest */ \
867  if(!childnode && !keybitset) \
868  childnode=node->field.trie_child[1]; \
869  if(!childnode) break; \
870  } \
871  if(!ret) \
872  { /* If we didn't find any node bigger than rkey, bump up a bin \
873  and look for the smallest possible key in that */ \
874  binbitidx++; \
875  /* From now on, always match lowest */ \
876  retkey+=rkey; \
877  rkey=0; \
878  continue; \
879  } \
880  } while(!ret); \
881  return ret->field.trie_next ? ret->field.trie_next : ret; \
882  }
883 #else /* NEDTRIEUSEMACROS */
884 #define NEDTRIE_GENERATE_CFIND(proto, name, type, field, keyfunct) \
885  proto INLINE struct type * name##_NEDTRIE_CFIND(struct name *RESTRICT head, struct type *RESTRICT r, int rounds) \
886 { \
887  return nedtries::trieCfind<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r, rounds); \
888 }
889 #endif /* NEDTRIEUSEMACROS */
890 
891 #ifdef __cplusplus
892 namespace nedtries {
893  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *trieminmax(const trietype *RESTRICT head, const unsigned dir)
894  {
895  const type *RESTRICT node=0, *RESTRICT child;
896  const TrieLink_t<type> *RESTRICT nodelink;
897  unsigned bitidx;
898  if(!head->count) return 0;
899  if(!dir)
900  { /* He wants min */
901  for(bitidx=0; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx++);
902  assert(node);
903  return (type *) node;
904  }
905  /* He wants max */
906  for(bitidx=NEDTRIE_INDEXBINS-1; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx--);
907  assert(node);
908  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
909  while((child=nodelink->trie_child[1] ? nodelink->trie_child[1] : nodelink->trie_child[0]))
910  {
911  node=child;
912  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
913  }
914  /* Now go to end leaf */
915  while(nodelink->trie_next)
916  {
917  node=nodelink->trie_next;
918  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
919  }
920  return (type *) node;
921  }
922 }
923 #endif /* __cplusplus */
924 #if NEDTRIEUSEMACROS
925 #define NEDTRIE_GENERATE_MINMAX(proto, name, type, field, keyfunct) \
926  proto INLINE struct type * name##_NEDTRIE_MINMAX(struct name *RESTRICT head, const unsigned dir) \
927  { \
928  struct type *RESTRICT node=0, *RESTRICT child; \
929  unsigned bitidx; \
930  if(!head->count) return 0; \
931  if(!dir) \
932  { /* He wants min */ \
933  for(bitidx=0; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx++); \
934  assert(node); \
935  return node; \
936  } \
937  /* He wants max */ \
938  for(bitidx=NEDTRIE_INDEXBINS-1; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx--); \
939  assert(node); \
940  while((child=node->field.trie_child[1] ? node->field.trie_child[1] : node->field.trie_child[0])) \
941  { \
942  node=child; \
943  } \
944  /* Now go to end leaf */ \
945  while(node->field.trie_next) \
946  { \
947  node=node->field.trie_next; \
948  } \
949  return node; \
950  }
951 #else /* NEDTRIEUSEMACROS */
952 #define NEDTRIE_GENERATE_MINMAX(proto, name, type, field, keyfunct) \
953  proto INLINE struct type * name##_NEDTRIE_MINMAX(struct name *RESTRICT head, unsigned dir) \
954 { \
955  return nedtries::trieminmax<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, dir); \
956 }
957 #endif /* NEDTRIEUSEMACROS */
958 
959 #ifdef __cplusplus
960 namespace nedtries {
961  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *triebranchprev(const type *RESTRICT r, const TrieLink_t<type> *RESTRICT *rlinkaddr)
962  {
963  const type *RESTRICT node=0, *RESTRICT child;
964  const TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink;
965 
966  rlink=(TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
967  /* Am I a leaf off the tree? */
968  if(rlink->trie_prev)
969  {
970  assert(!rlink->trie_parent);
971  return rlink->trie_prev;
972  }
973  /* Trace up my parents to prev branch */
974  while(((size_t) rlink->trie_parent & 3)!=3)
975  {
976  node=rlink->trie_parent;
977  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
978  /* If I was on child[1] and there is a child[0], go to bottom of child[0] */
979  if(nodelink->trie_child[1]==r && nodelink->trie_child[0])
980  {
981  node=nodelink->trie_child[0];
982  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
983  /* Follow child[1] preferentially downwards */
984  while((child=nodelink->trie_child[1] ? nodelink->trie_child[1] : nodelink->trie_child[0]))
985  {
986  node=child;
987  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
988  }
989  }
990  /* If I was already on child[0] or there are no more children, return this node */
991  /* Now go to end leaf */
992  while(nodelink->trie_next)
993  {
994  node=nodelink->trie_next;
995  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
996  }
997  return (type *) node;
998  }
999  /* I have reached the top of my trie, no more on this branch */
1000  if(rlinkaddr) *rlinkaddr=rlink;
1001  return 0;
1002  }
1003 
1004  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *trieprev(const trietype *RESTRICT head, const type *RESTRICT r)
1005  {
1006  const type *RESTRICT node=0, *RESTRICT child;
1007  const TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink=0;
1008  unsigned bitidx;
1009 
1010  if((node=triebranchprev<trietype, type, fieldoffset, keyfunct>(r, &rlink)) || !rlink) return (type *) node;
1011  /* I have reached the top of my trie, so on to prev bin */
1012  bitidx=(unsigned)(((size_t) rlink->trie_parent)>>2);
1013  assert(head->triebins[bitidx]==r);
1014  for(bitidx--; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx--);
1015  if(bitidx>=NEDTRIE_INDEXBINS) return 0;
1016  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1017  /* Follow child[1] preferentially downwards */
1018  while((child=nodelink->trie_child[1] ? nodelink->trie_child[1] : nodelink->trie_child[0]))
1019  {
1020  node=child;
1021  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1022  }
1023  /* Now go to end leaf */
1024  while(nodelink->trie_next)
1025  {
1026  node=nodelink->trie_next;
1027  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1028  }
1029  return (type *) node;
1030  }
1031 }
1032 #endif /* __cplusplus */
1033 #if NEDTRIEUSEMACROS
1034 #define NEDTRIE_GENERATE_PREV(proto, name, type, field, keyfunct) \
1035  proto INLINE struct type * name##_NEDTRIE_BRANCHPREV(struct type *RESTRICT *RESTRICT r) \
1036  { \
1037  struct type *RESTRICT node=0, *RESTRICT child; \
1038 \
1039  /* Am I a leaf off the tree? */ \
1040  if((*r)->field.trie_prev) \
1041  { \
1042  assert(!(*r)->field.trie_parent); \
1043  return (*r)->field.trie_prev; \
1044  } \
1045  /* Trace up my parents to prev branch */ \
1046  while(((size_t) (*r)->field.trie_parent & 3)!=3) \
1047  { \
1048  node=(*r)->field.trie_parent; \
1049  /* If I was on child[1] and there is a child[0], go to bottom of child[0] */ \
1050  if(node->field.trie_child[1]==(*r) && node->field.trie_child[0]) \
1051  { \
1052  node=node->field.trie_child[0]; \
1053  /* Follow child[1] preferentially downwards */ \
1054  while((child=node->field.trie_child[1] ? node->field.trie_child[1] : node->field.trie_child[0])) \
1055  { \
1056  node=child; \
1057  } \
1058  } \
1059  /* If I was already on child[0] or there are no more children, return this node */ \
1060  /* Now go to end leaf */ \
1061  while(node->field.trie_next) \
1062  { \
1063  node=node->field.trie_next; \
1064  } \
1065  return node; \
1066  } \
1067  /* I have reached the top of my trie, no more on this branch */ \
1068  return 0; \
1069  } \
1070  proto INLINE struct type * name##_NEDTRIE_PREV(struct name *RESTRICT head, struct type *RESTRICT r) \
1071  { \
1072  struct type *RESTRICT node=0, *RESTRICT child; \
1073  unsigned bitidx; \
1074 \
1075  if((node=name##_NEDTRIE_BRANCHPREV(&r))) return node; \
1076  /* I have reached the top of my trie, so on to prev bin */ \
1077  bitidx=(unsigned)(((size_t) r->field.trie_parent)>>2); \
1078  assert(head->triebins[bitidx]==r); \
1079  for(bitidx--; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx--); \
1080  if(bitidx>=NEDTRIE_INDEXBINS) return 0; \
1081  /* Follow child[1] preferentially downwards */ \
1082  while((child=node->field.trie_child[1] ? node->field.trie_child[1] : node->field.trie_child[0])) \
1083  { \
1084  node=child; \
1085  } \
1086  /* Now go to end leaf */ \
1087  while(node->field.trie_next) \
1088  { \
1089  node=node->field.trie_next; \
1090  } \
1091  return node; \
1092  }
1093 #else /* NEDTRIEUSEMACROS */
1094 #define NEDTRIE_GENERATE_PREV(proto, name, type, field, keyfunct) \
1095  proto INLINE struct type * name##_NEDTRIE_PREV(struct name *RESTRICT head, struct type *RESTRICT r) \
1096 { \
1097  return nedtries::trieprev<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
1098 }
1099 #endif /* NEDTRIEUSEMACROS */
1100 
1101 #ifdef __cplusplus
1102 namespace nedtries {
1103  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *triebranchnext(const type *RESTRICT r, const TrieLink_t<type> *RESTRICT *rlinkaddr)
1104  {
1105  const type *RESTRICT node;
1106  const TrieLink_t<type> *RESTRICT nodelink, *RESTRICT rlink;
1107 
1108  rlink=(const TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
1109  /* Am I a leaf off the tree? */
1110  if(rlink->trie_next)
1111  return rlink->trie_next;
1112  /* If I am the end leaf off a tree, put me back at my tree node */
1113  while(!rlink->trie_parent)
1114  {
1115  r=rlink->trie_prev;
1116  rlink=(const TrieLink_t<type> *RESTRICT)((size_t) r + fieldoffset);
1117  }
1118  /* Follow my children, preferring child[0] */
1119  if((node=rlink->trie_child[0] ? rlink->trie_child[0] : rlink->trie_child[1]))
1120  {
1121  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1122  assert(nodelink->trie_parent==r);
1123  return (type *) node;
1124  }
1125  /* Trace up my parents to next branch */
1126  while(((size_t) rlink->trie_parent & 3)!=3)
1127  {
1128  node=rlink->trie_parent;
1129  nodelink=(const TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1130  if(nodelink->trie_child[0]==r && nodelink->trie_child[1])
1131  {
1132  return nodelink->trie_child[1];
1133  }
1134  r=node;
1135  rlink=nodelink;
1136  }
1137  /* I have reached the top of my trie, no more on this branch */
1138  if(rlinkaddr) *rlinkaddr=rlink;
1139  return 0;
1140  }
1141 
1142  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *trienext(const trietype *RESTRICT head, const type *RESTRICT r)
1143  {
1144  const type *RESTRICT node;
1145  const TrieLink_t<type> *RESTRICT rlink=0;
1146  unsigned bitidx;
1147 
1148  if((node=triebranchnext<trietype, type, fieldoffset, keyfunct>(r, &rlink))) return (type *) node;
1149  /* I have reached the top of my trie, so on to next bin */
1150  bitidx=(unsigned)(((size_t) rlink->trie_parent)>>2);
1151  for(bitidx++; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx++);
1152  if(bitidx>=NEDTRIE_INDEXBINS) return 0;
1153  return (type *) node;
1154  }
1155 }
1156 #endif /* __cplusplus */
1157 #if NEDTRIEUSEMACROS
1158 #define NEDTRIE_GENERATE_NEXT(proto, name, type, field, keyfunct) \
1159  proto INLINE struct type * name##_NEDTRIE_BRANCHNEXT(struct type *RESTRICT *RESTRICT r) \
1160  { \
1161  struct type *RESTRICT node; \
1162 \
1163  /* Am I a leaf off the tree? */ \
1164  if((*r)->field.trie_next) \
1165  return (*r)->field.trie_next; \
1166  /* If I am the end leaf off a tree, put me back at my tree node */ \
1167  while(!(*r)->field.trie_parent) \
1168  { \
1169  (*r)=(*r)->field.trie_prev; \
1170  } \
1171  /* Follow my children, preferring child[0] */ \
1172  if((node=(*r)->field.trie_child[0] ? (*r)->field.trie_child[0] : (*r)->field.trie_child[1])) \
1173  { \
1174  assert(node->field.trie_parent==(*r)); \
1175  return node; \
1176  } \
1177  /* Trace up my parents to next branch */ \
1178  while(((size_t) (*r)->field.trie_parent & 3)!=3) \
1179  { \
1180  node=(*r)->field.trie_parent; \
1181  if(node->field.trie_child[0]==(*r) && node->field.trie_child[1]) \
1182  { \
1183  return node->field.trie_child[1]; \
1184  } \
1185  (*r)=node; \
1186  } \
1187  return 0; \
1188  } \
1189  proto INLINE struct type * name##_NEDTRIE_NEXT(struct name *RESTRICT head, struct type *RESTRICT r) \
1190  { \
1191  struct type *RESTRICT node; \
1192  unsigned bitidx; \
1193 \
1194  if((node=name##_NEDTRIE_BRANCHNEXT(&r))) return node; \
1195  /* I have reached the top of my trie, so on to next bin */ \
1196  bitidx=(unsigned)(((size_t) r->field.trie_parent)>>2); \
1197  assert(head->triebins[bitidx]==r); \
1198  for(bitidx++; bitidx<NEDTRIE_INDEXBINS && !(node=head->triebins[bitidx]); bitidx++); \
1199  if(bitidx>=NEDTRIE_INDEXBINS) return 0; \
1200  return node; \
1201  }
1202 #else /* NEDTRIEUSEMACROS */
1203 #define NEDTRIE_GENERATE_NEXT(proto, name, type, field, keyfunct) \
1204  proto INLINE struct type * name##_NEDTRIE_NEXT(struct name *RESTRICT head, struct type *RESTRICT r) \
1205 { \
1206  return nedtries::trienext<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
1207 }
1208 #endif /* NEDTRIEUSEMACROS */
1209 
1210 #ifdef __cplusplus
1211 namespace nedtries {
1212  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE type *trieNfind(const trietype *RESTRICT head, const type *RESTRICT r)
1213  {
1214  const type *RESTRICT node=0, *RESTRICT ret=trieCfind<trietype, type, fieldoffset, keyfunct>(head, r, INT_MAX), *RESTRICT stop;
1215  const TrieLink_t<type> *RESTRICT rlink;
1216  size_t rkey=keyfunct(r), retkey, nodekey;
1217 
1218  if(!ret) return 0;
1219  if(!(retkey=keyfunct(ret)-rkey)) return (type *) ret;
1220  /* Cfind basically does a find but if it doesn't find an exact match it early outs
1221  with the closest result it found during the find. As nodes with children have a key
1222  which is only guaranteed to be correct under its parent's constraints and has nothing
1223  to do with its children, there may be a closer key in any of the children of the node
1224  returned. Hence we iterate the local subbranch, looking for closer fits. */
1225  rlink=(const TrieLink_t<type> *RESTRICT)((size_t) ret + fieldoffset);
1226  stop=rlink->trie_parent;
1227  for(node=triebranchnext<trietype, type, fieldoffset, keyfunct>(ret, 0); node && node!=stop; node=triebranchnext<trietype, type, fieldoffset, keyfunct>(node, 0))
1228  {
1229  nodekey=keyfunct(node);
1230  /* If nodekey is a closer fit to search key, mark as best result so far */
1231  if(nodekey>=rkey && nodekey-rkey<retkey)
1232  {
1233  ret=node;
1234  retkey=nodekey-rkey;
1235  }
1236  }
1237  return (type *) ret;
1238  }
1239 }
1240 #endif /* __cplusplus */
1241 #if NEDTRIEUSEMACROS
1242 #define NEDTRIE_GENERATE_NFIND(proto, name, type, field, keyfunct) \
1243  proto INLINE struct type * name##_NEDTRIE_NFIND(struct name *RESTRICT head, struct type *RESTRICT r) \
1244  { \
1245  struct type *RESTRICT node=0, *RESTRICT ret=name##_NEDTRIE_CFIND(head, r, INT_MAX), *RESTRICT stop; \
1246  size_t rkey=keyfunct(r), retkey, nodekey; \
1247  \
1248  if(!ret) return 0; \
1249  if(!(retkey=keyfunct(ret)-rkey)) return ret; \
1250  /* Cfind basically does a find but if it doesn't find an exact match it early outs \
1251  with the closest result it found during the find. As nodes with children have a key \
1252  which is only guaranteed to be correct under its parent's constraints and has nothing \
1253  to do with its children, there may be a closer key in any of the children of the node \
1254  returned. Hence we iterate the local subbranch, looking for closer fits. */ \
1255  stop=r->field.trie_parent; \
1256  for(node=ret, node=name##_NEDTRIE_BRANCHNEXT(&node); node && node!=stop; node=name##_NEDTRIE_BRANCHNEXT(&node)) \
1257  { \
1258  nodekey=keyfunct(node); \
1259  /* If nodekey is a closer fit to search key, mark as best result so far */ \
1260  if(nodekey>=rkey && nodekey-rkey<retkey) \
1261  { \
1262  ret=node; \
1263  retkey=nodekey-rkey; \
1264  } \
1265  } \
1266  return ret; \
1267  }
1268 #else /* NEDTRIEUSEMACROS */
1269 #define NEDTRIE_GENERATE_NFIND(proto, name, type, field, keyfunct) \
1270  proto INLINE struct type * name##_NEDTRIE_NFIND(struct name *RESTRICT head, struct type *RESTRICT r) \
1271 { \
1272  return nedtries::trieNfind<struct name, struct type, NEDTRIEFIELDOFFSET(type, field), keyfunct>(head, r); \
1273 }
1274 #endif /* NEDTRIEUSEMACROS */
1275 
1276 
1280 #define NEDTRIE_GENERATE(proto, name, type, field, keyfunct, nobblefunct) \
1281  NEDTRIE_GENERATE_NOBBLES (proto, name, type, field, keyfunct) \
1282  NEDTRIE_GENERATE_INSERT (proto, name, type, field, keyfunct) \
1283  NEDTRIE_GENERATE_REMOVE (proto, name, type, field, keyfunct, nobblefunct) \
1284  NEDTRIE_GENERATE_FIND (proto, name, type, field, keyfunct) \
1285  NEDTRIE_GENERATE_EXACTFIND(proto, name, type, field, keyfunct) \
1286  NEDTRIE_GENERATE_CFIND (proto, name, type, field, keyfunct) \
1287  NEDTRIE_GENERATE_MINMAX (proto, name, type, field, keyfunct) \
1288  NEDTRIE_GENERATE_PREV (proto, name, type, field, keyfunct) \
1289  NEDTRIE_GENERATE_NEXT (proto, name, type, field, keyfunct) \
1290  NEDTRIE_GENERATE_NFIND (proto, name, type, field, keyfunct) \
1291  proto INLINE struct type * name##_NEDTRIE_PREVLEAF(struct type *r) { return (r)->field.trie_prev; } \
1292  proto INLINE struct type * name##_NEDTRIE_NEXTLEAF(struct type *r) { return (r)->field.trie_next; }
1293 
1297 #define NEDTRIE_INSERT(name, x, y) name##_NEDTRIE_INSERT(x, y)
1298 
1301 #define NEDTRIE_REMOVE(name, x, y) name##_NEDTRIE_REMOVE(x, y)
1302 
1305 #define NEDTRIE_FIND(name, x, y) name##_NEDTRIE_FIND(x, y)
1306 
1309 #define NEDTRIE_EXACTFIND(name, x, y) name##_NEDTRIE_EXACTFIND(x, y)
1310 
1317 #define NEDTRIE_CFIND(name, x, y, rounds) name##_NEDTRIE_CFIND(x, y, rounds)
1318 
1322 #define NEDTRIE_NFIND(name, x, y) name##_NEDTRIE_NFIND(x, y)
1323 
1326 #define NEDTRIE_PREV(name, x, y) name##_NEDTRIE_PREV(x, y)
1327 
1330 #define NEDTRIE_NEXT(name, x, y) name##_NEDTRIE_NEXT(x, y)
1331 
1334 #define NEDTRIE_PREVLEAF(name, x) name##_NEDTRIE_PREVLEAF(x)
1335 
1338 #define NEDTRIE_NEXTLEAF(name, x) name##_NEDTRIE_NEXTLEAF(x)
1339 
1342 #define NEDTRIE_MIN(name, x) name##_NEDTRIE_MINMAX(x, 0)
1343 
1346 #define NEDTRIE_MAX(name, x) name##_NEDTRIE_MINMAX(x, 1)
1347 
1352 #define NEDTRIE_FOREACH(x, name, head) \
1353  for ((x) = NEDTRIE_MIN(name, head); \
1354  (x) != NULL; \
1355  (x) = NEDTRIE_NEXT(name, head, x))
1356 
1362 #define NEDTRIE_FOREACH_SAFE(x, name, head, y) \
1363  for ((x) = NEDTRIE_MIN(name, head); \
1364  (x) != NULL && ((y) = NEDTRIE_NEXT(name, head, x), 1); \
1365  (x) = (y))
1366 
1371 #define NEDTRIE_FOREACH_REVERSE(x, name, head) \
1372  for ((x) = NEDTRIE_MAX(name, head); \
1373  (x) != NULL; \
1374  (x) = NEDTRIE_PREV(name, head, x))
1375 
1381 #define NEDTRIE_FOREACH_REVERSE_SAFE(x, name, head, y) \
1382  for ((x) = NEDTRIE_MAX(name, head); \
1383  (x) != NULL && ((y) = NEDTRIE_PREV(name, head, x), 1); \
1384  (x) = (y))
1385 
1389 #define NEDTRIE_HASNODEHEADER(treevar, node, link) ((node)->link.trie_parent || (node)->link.trie_prev)
1390 
1391 #ifdef __cplusplus
1392 #include <functional>
1393 namespace nedtries {
1394 
1395 #ifndef NDEBUG
1396  typedef struct TrieValidityState_t
1397  {
1400 
1401  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE
1402  void triecheckvaliditybranch(trietype *head, type *RESTRICT node, unsigned bitidx, TrieValidityState &state)
1403  {
1404  type *RESTRICT child;
1405  TrieLink_t<type> *RESTRICT nodelink, *RESTRICT childlink;
1406  size_t nodekey=keyfunct(node);
1407 
1408  if(nodekey<state.smallestkey) state.smallestkey=nodekey;
1409  if(nodekey>state.largestkey) state.largestkey=nodekey;
1410  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1411  assert(nodelink->trie_parent);
1412  child=nodelink->trie_parent;
1413  childlink=(TrieLink_t<type> *RESTRICT)((size_t) child + fieldoffset);
1414  assert(childlink->trie_child[0]==node || childlink->trie_child[1]==node);
1415  assert(node==childlink->trie_child[!!(nodekey & ((size_t) 1<<bitidx))]);
1416  assert(!nodelink->trie_prev);
1417  while((child=nodelink->trie_next))
1418  {
1419  state.leafs++;
1420  childlink=(TrieLink_t<type> *RESTRICT)((size_t) child + fieldoffset);
1421  assert(!childlink->trie_parent);
1422  assert(!childlink->trie_child[0]);
1423  assert(!childlink->trie_child[1]);
1424  assert(childlink->trie_prev);
1425  assert(!childlink->trie_next || child==((TrieLink_t<type> *RESTRICT)((size_t) childlink->trie_next + fieldoffset))->trie_prev);
1426  nodelink=childlink;
1427  state.count++;
1428  }
1429  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1430  state.count++;
1431  if(nodelink->trie_child[0])
1432  {
1433  state.lefts++;
1434  triecheckvaliditybranch<trietype, type, fieldoffset, keyfunct>(head, nodelink->trie_child[0], bitidx-1, state);
1435  }
1436  if(nodelink->trie_child[1])
1437  {
1438  state.rights++;
1439  triecheckvaliditybranch<trietype, type, fieldoffset, keyfunct>(head, nodelink->trie_child[1], bitidx-1, state);
1440  }
1441  }
1442 #endif
1443  template<class trietype, class type, size_t fieldoffset, size_t (*keyfunct)(const type *RESTRICT)> DEBUGINLINE void triecheckvalidity(trietype *head)
1444  {
1445 #ifndef NDEBUG
1446  type *RESTRICT node, *RESTRICT child;
1447  TrieLink_t<type> *RESTRICT nodelink, *RESTRICT childlink;
1448  unsigned n, bitidx;
1449  TrieValidityState state={0};
1450  for(n=0; n<NEDTRIE_INDEXBINS; n++)
1451  {
1452  if((node=head->triebins[n]))
1453  {
1454  size_t nodekey=keyfunct(node);
1455  state.tops++;
1456  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1457  bitidx=(unsigned)(((size_t) nodelink->trie_parent)>>2);
1458  assert(bitidx==n);
1459  assert(head->triebins[bitidx]==node);
1460  assert(!nodekey || ((((size_t)-1)<<bitidx) & nodekey)==((size_t) 1<<bitidx));
1461  assert(!nodelink->trie_prev);
1462  while((child=nodelink->trie_next))
1463  {
1464  state.leafs++;
1465  childlink=(TrieLink_t<type> *RESTRICT)((size_t) child + fieldoffset);
1466  assert(!childlink->trie_parent);
1467  assert(!childlink->trie_child[0]);
1468  assert(!childlink->trie_child[1]);
1469  assert(childlink->trie_prev);
1470  assert(!childlink->trie_next || child==((TrieLink_t<type> *RESTRICT)((size_t) childlink->trie_next + fieldoffset))->trie_prev);
1471  nodelink=childlink;
1472  state.count++;
1473  }
1474  nodelink=(TrieLink_t<type> *RESTRICT)((size_t) node + fieldoffset);
1475  state.count++;
1476  if(nodelink->trie_child[0])
1477  {
1478  state.lefts++;
1479  state.smallestkey=(size_t)-1;
1480  state.largestkey=0;
1481  triecheckvaliditybranch<trietype, type, fieldoffset, keyfunct>(head, nodelink->trie_child[0], bitidx-1, state);
1482  assert(!state.smallestkey || state.smallestkey>=(size_t)1<<bitidx);
1483  assert(state.largestkey<(size_t)1<<(bitidx+1));
1484  }
1485  if(nodelink->trie_child[1])
1486  {
1487  state.rights++;
1488  state.smallestkey=(size_t)-1;
1489  state.largestkey=0;
1490  triecheckvaliditybranch<trietype, type, fieldoffset, keyfunct>(head, nodelink->trie_child[1], bitidx-1, state);
1491  assert(state.smallestkey>=(size_t)1<<bitidx);
1492  assert(state.largestkey<(size_t)1<<(bitidx+1));
1493  }
1494  }
1495  }
1496  assert(state.count==head->count);
1497  for(state.count=0, node=trieminmax<trietype, type, fieldoffset, keyfunct>(head, 0); node; (node=trienext<trietype, type, fieldoffset, keyfunct>(head, node)), state.count++)
1498 #if 0
1499  printf("%p\n", node)
1500 #endif
1501  ;
1502  if(state.count!=head->count)
1503  {
1504  assert(state.count==head->count);
1505  }
1506 #if 0
1507  printf("\n");
1508 #endif
1509  for(state.count=0, node=trieminmax<trietype, type, fieldoffset, keyfunct>(head, 1); node; (node=trieprev<trietype, type, fieldoffset, keyfunct>(head, node)), state.count++)
1510 #if 0
1511  printf("%p\n", node)
1512 #endif
1513  ;
1514  if(state.count!=head->count)
1515  {
1516  assert(state.count==head->count);
1517  }
1518 #if 0
1519  printf("\n");
1520 #endif
1521 #if !defined(NDEBUG) && 0
1522  if(count>50)
1523  printf("Of count %u, tops %.2lf%%, lefts %.2lf%%, rights %.2lf%%, leafs %.2lf%%\n", count, 100.0*tops/count, 100.0*lefts/count, 100.0*rights/count, 100.0*leafs/count);
1524 #endif
1525 #endif /* !NDEBUG */
1526  }
1527 
1528 #if NEDTRIE_ENABLE_STL_CONTAINERS
1529 
1537 #if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER>=1600) || defined(HAVE_CPP0X) /* Do we have C++0x? */
1538 #undef HAVE_CPP0XRVALUEREFS
1539 #define HAVE_CPP0XRVALUEREFS 1
1540 #undef HAVE_CPP0XTYPETRAITS
1541 #define HAVE_CPP0XTYPETRAITS 1
1542 #endif
1543 
1545  namespace nedpolicy
1546  {
1550  template<class triemaptype> class nobblezeros
1551  {
1552  protected:
1553  template<class trietype> static int trie_nobblefunction(trietype *)
1554  {
1555  return 0;
1556  }
1557  };
1561  template<class triemaptype> class nobbleones
1562  {
1563  protected:
1564  template<class trietype> static int trie_nobblefunction(trietype *)
1565  {
1566  return 1;
1567  }
1568  };
1572  template<class triemaptype> class nobbleequally
1573  {
1574  protected:
1575  template<class trietype> static int trie_nobblefunction(trietype *head)
1576  {
1577  return (head->nobbledir=!head->nobbledir);
1578  }
1579  };
1580  } // namspace
1581  template<class type> NEDTRIE_HEAD2(trie_map_head, type);
1582  template<class keytype, class type, class keyfunct, class iteratortype> struct trie_maptype;
1604  template<class keytype, class type> struct trie_keyfunct : public std::unary_function<type, keytype>
1605  {
1606 #ifdef HAVE_CPP0XRVALUEREFS
1607  keytype operator()(const type &v) const
1608  {
1609  static_assert(typeid(type)==typeid(type), "trie_keyfunct has not been specialised for this type");
1610  }
1611 #else
1612  private:
1613  keytype operator()(const type &) const;
1614 #endif
1615  };
1616  template<class keytype, class type> struct trie_maptype_keyfunct : public std::unary_function<type, keytype>
1617  {
1618  template<class maptype> keytype operator()(const maptype &v) const
1619  {
1620  return v.trie_keyvalue;
1621  }
1622  };
1623  namespace intern {
1624  template<class type> struct noconstiteratortype : public type { };
1625  template<class keyfunct_, class mapvaluetype> size_t to_Ckeyfunct(const mapvaluetype *RESTRICT v)
1626  {
1627  return keyfunct_()(*v);
1628  }
1629  }
1630  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer,
1631  class iteratortype, int dir, class mapvaluetype, class constiteratortype=intern::noconstiteratortype<iteratortype> > class trie_iterator;
1632  template<class keytype, class type, class keyfunct=trie_maptype_keyfunct<keytype, type>,
1633  class allocator=std::allocator<trie_maptype<keytype, type, keyfunct, std::list<size_t>::iterator> >,
1634  template<class> class nobblepolicy=nedpolicy::nobblezeros,
1635  class stlcontainer=std::list<trie_maptype<keytype, type, keyfunct, std::list<size_t>::iterator>, allocator> > class trie_map;
1636  template<class keytype, class type, class keyfunct=trie_keyfunct<keytype, type>,
1637  class allocator=std::allocator<trie_maptype<keytype, type, keyfunct, std::list<size_t>::iterator> >,
1638  template<class> class nobblepolicy=nedpolicy::nobblezeros,
1639  class stlcontainer=std::list<trie_maptype<keytype, type, keyfunct, std::list<size_t>::iterator>, allocator> > class trie_multimap;
1647  namespace fake {
1648  template<class keytype, class type, class keyfunct, class iteratortype> struct trie_maptype
1649  {
1650  template<class keytype_, class type_> friend struct trie_keyfunct;
1651  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1652  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_map;
1653  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_multimap;
1654  typedef keytype trie_key_type;
1655  typedef type trie_value_type;
1656  typedef keyfunct trie_keyfunct_type;
1657  typedef iteratortype trie_iterator_type;
1658  type trie_value;
1659  iteratortype trie_iterator;
1660  TrieLink_t<type> trie_link;
1661  };
1662  }
1663  template<class keytype, class type, class keyfunct, class iteratortype> struct trie_maptype
1664  {
1665  private: // ENSURE the fake type above mirrors this one
1666  template<class keytype_, class type_> friend struct trie_keyfunct;
1667  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1668  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_map;
1669  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_multimap;
1670  typedef keytype trie_key_type;
1671  typedef type trie_value_type;
1672  typedef keyfunct trie_keyfunct_type;
1673  typedef iteratortype trie_iterator_type;
1674  typedef fake::trie_maptype<keytype, type, keyfunct, iteratortype> fakemirrorofme_type;
1675  type trie_value;
1676  iteratortype trie_iterator;
1677  TrieLink_t<type> trie_link;
1678  static const size_t trie_link_offset=NEDTRIEFIELDOFFSET2(fakemirrorofme_type, trie_link);
1679  public:
1680  trie_maptype(const type &v) : trie_value(v)
1681  { // Prevent that memory corruption bug ever happening again
1682  static char ensure_trie_link_offset_is_bounded[trie_link_offset+sizeof(trie_link)<=sizeof(*this)];
1683  }
1684  template<class keytype_, class type_, class keyfunct_, class iteratortype_> trie_maptype(const trie_maptype<keytype_, type_, keyfunct_, iteratortype_> &o) : trie_value(o.trie_value) { }
1685 #ifdef HAVE_CPP0XRVALUEREFS
1686  template<class keytype_, class type_, class keyfunct_, class iteratortype_> trie_maptype(trie_maptype<keytype_, type_, keyfunct_, iteratortype_> &&o) : trie_value(std::move(o.trie_value)) { }
1687 #endif
1688  operator const type &() const { return trie_value; }
1690  };
1691  namespace fake {
1692  template<class keytype, class type, class iteratortype> struct trie_maptype2
1693  {
1694  template<class keytype_, class type_> friend struct trie_keyfunct;
1695  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1696  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_map;
1697  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_multimap;
1698  template<class keytype_, class type_> friend struct trie_maptype_keyfunct;
1699  typedef keytype trie_key_type;
1700  typedef type trie_value_type;
1701  typedef trie_maptype_keyfunct<keytype, type> trie_keyfunct_type;
1702  typedef iteratortype trie_iterator_type;
1703  type trie_value;
1704  keytype trie_keyvalue; // For when key is overriden using trie_map::operator[]
1705  iteratortype trie_iterator;
1706  TrieLink_t<type> trie_link;
1707  };
1708  }
1709  template<class keytype, class type, class iteratortype> struct trie_maptype<keytype, type, trie_maptype_keyfunct<keytype, type>, iteratortype>
1710  {
1711  private: // ENSURE the fake type above mirrors this one
1712  template<class keytype_, class type_> friend struct trie_keyfunct;
1713  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1714  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_map;
1715  template<class keytype_, class type_, class keyfunct_, class allocator, template<class> class nobblepolicy, class stlcontainer> friend class trie_multimap;
1716  template<class keytype_, class type_> friend struct trie_maptype_keyfunct;
1717  typedef keytype trie_key_type;
1718  typedef type trie_value_type;
1719  typedef trie_maptype_keyfunct<keytype, type> trie_keyfunct_type;
1720  typedef iteratortype trie_iterator_type;
1721  typedef fake::trie_maptype2<keytype, type, iteratortype> fakemirrorofme_type;
1722  type trie_value;
1723  keytype trie_keyvalue; // For when key is overriden using trie_map::operator[]
1724  iteratortype trie_iterator;
1725  TrieLink_t<type> trie_link;
1726  static const size_t trie_link_offset=NEDTRIEFIELDOFFSET2(fakemirrorofme_type, trie_link);
1727  public:
1728  trie_maptype(const type &v) : trie_value(v)
1729  { // Prevent that memory corruption bug ever happening again
1730  static char ensure_trie_link_offset_is_bounded[trie_link_offset+sizeof(trie_link)<=sizeof(*this)];
1731  }
1732  template<class keytype_, class type_, class iteratortype_> trie_maptype(const trie_maptype<keytype_, type_, trie_maptype_keyfunct<keytype_, type_>, iteratortype_> &o) : trie_value(o.trie_value), trie_keyvalue(o.trie_keyvalue) { }
1733 #ifdef HAVE_CPP0XRVALUEREFS
1734  template<class keytype_, class type_, class iteratortype_> trie_maptype(trie_maptype<keytype_, type_, trie_maptype_keyfunct<keytype_, type_>, iteratortype_> &&o) : trie_value(std::move(o.trie_value)), trie_keyvalue(std::move(o.trie_keyvalue)) { }
1735 #endif
1736  operator const type &() const { return trie_value; }
1738  };
1739 
1744  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer, class iteratortype, int dir, class mapvaluetype, class constiteratortype> class trie_iterator : protected iteratortype
1745  {
1746  trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *parent;
1747  public:
1748  typedef typename iteratortype::value_type::trie_value_type value_type;
1749  typedef typename iteratortype::difference_type difference_type;
1750  typedef typename iteratortype::pointer pointer;
1751  typedef typename iteratortype::reference reference;
1752  typedef typename iteratortype::iterator_category iterator_category;
1753 
1754  operator constiteratortype () const { return constiteratortype(parent, static_cast<const iteratortype &>(*this)); }
1755 
1756  trie_iterator() : parent(0) { }
1757  trie_iterator(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *parent_, const iteratortype &o) : iteratortype(o), parent(const_cast<trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *>(parent_)) { }
1758  trie_iterator(const trie_iterator &o) : iteratortype(o), parent(o.parent) { }
1759 #ifdef HAVE_CPP0XRVALUEREFS
1760  trie_iterator(trie_iterator &&o) : iteratortype(std::move(o)), parent(o.parent) { }
1761 #endif
1762  trie_iterator &operator=(const trie_iterator &o)
1763  {
1764  return *new(this) trie_iterator(o);
1765  }
1766 #ifdef HAVE_CPP0XRVALUEREFS
1767  trie_iterator &operator=(trie_iterator &&o)
1768  {
1769  return *new(this) trie_iterator(std::move(o));
1770  }
1771 #endif
1772  trie_iterator &operator++()
1773  {
1774  mapvaluetype *r=dir>0 ?
1775  trienext<trie_map_head<mapvaluetype>, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct<typename mapvaluetype::trie_keyfunct_type> >(&parent->triehead, (mapvaluetype *)(&**this)) :
1776  trieprev<trie_map_head<mapvaluetype>, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct<typename mapvaluetype::trie_keyfunct_type> >(&parent->triehead, (mapvaluetype *)(&**this));
1777  if(r)
1778  new(this) iteratortype((iteratortype &) r->trie_iterator); // type pun safe
1779  else
1780  *this=parent->end();
1781  return *this;
1782  }
1783  trie_iterator &operator++(int) { trie_iterator tmp(*this); operator++(); return tmp; }
1784  trie_iterator &operator--()
1785  {
1786  mapvaluetype *r=dir<0 ?
1787  trienext<trie_map_head<mapvaluetype>, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct<typename mapvaluetype::trie_keyfunct_type> >(&parent->triehead, (mapvaluetype *)(&**this)) :
1788  trieprev<trie_map_head<mapvaluetype>, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct<typename mapvaluetype::trie_keyfunct_type> >(&parent->triehead, (mapvaluetype *)(&**this));
1789  if(r)
1790  new(this) iteratortype((iteratortype &) r->trie_iterator);
1791  else
1792  *this=parent->end();
1793  return *this;
1794  }
1795  trie_iterator &operator--(int) { trie_iterator tmp(*this); operator--(); return tmp; }
1796  bool operator==(const trie_iterator &o) const { return static_cast<const iteratortype &>(*this)==static_cast<const iteratortype &>(o); }
1797  bool operator!=(const trie_iterator &o) const { return static_cast<const iteratortype &>(*this)!=static_cast<const iteratortype &>(o); }
1798  const mapvaluetype &operator *() const { return (const mapvaluetype &) iteratortype::operator *(); }
1799  mapvaluetype &operator *() { return (mapvaluetype &) iteratortype::operator *(); }
1800  const mapvaluetype *operator ->() const { return (const mapvaluetype *) iteratortype::operator->(); }
1801  mapvaluetype *operator ->() { return (mapvaluetype *) iteratortype::operator->(); }
1802  };
1803 
1804  namespace intern
1805  {
1806  template<class key_type> struct keystore_t { size_t magic; const key_type &key; keystore_t(size_t magic_, const key_type &key_) : magic(magic_), key(key_) { } private: keystore_t &operator=(const keystore_t &); };
1807  template<class keytype, class type, class mapvaluetype, class keyfunct> struct findkeyfunct_t : public std::unary_function<type, keytype>
1808  {
1809  size_t operator()(const mapvaluetype &v) const
1810  {
1811  keystore_t<keytype> *r=(keystore_t<keytype> *)(void *)(&v);
1812  // NOTE: This line triggers a "conditional jump or move depends on unintialized value(s)" in valgrind if
1813  // sizeof(type)<sizeof(size_t). This is unavoidable.
1814  if(r->magic==*(size_t *)"TRIEFINDKEYSTORE")
1815  return r->key;
1816  return keyfunct()(v);
1817  }
1818  };
1819  }
1820 
1860  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> class trie_map : protected stlcontainer, protected nobblepolicy<trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> >
1861  {
1862  typedef nobblepolicy<trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> > nobblepolicytype;
1863  typedef typename stlcontainer::value_type mapvaluetype;
1864  static const size_t trie_fieldoffset=mapvaluetype::trie_link_offset;
1865  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1866  public:
1867  typedef typename stlcontainer::allocator_type allocator_type;
1868  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::const_iterator, 1, mapvaluetype> const_iterator;
1869  typedef typename stlcontainer::const_pointer const_pointer;
1870  typedef typename stlcontainer::const_reference const_reference;
1871  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::const_reverse_iterator, -1, mapvaluetype> const_reverse_iterator;
1872  typedef typename stlcontainer::difference_type difference_type;
1873  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::iterator, 1, mapvaluetype, const_iterator> iterator;
1874  typedef keytype key_type;
1875  typedef type mapped_type;
1876  typedef typename stlcontainer::pointer pointer;
1877  typedef typename stlcontainer::reference reference;
1878  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::reverse_iterator, -1, mapvaluetype, const_reverse_iterator> reverse_iterator;
1879  typedef typename stlcontainer::size_type size_type;
1880  typedef typename stlcontainer::value_type::trie_value_type value_type;
1881  private:
1882  trie_map_head<mapvaluetype> triehead;
1883  static typename mapvaluetype::trie_iterator_type &from_iterator(iterator &it)
1884  {
1885  void *_it=(void *) &it;
1886  return *(typename mapvaluetype::trie_iterator_type *)_it;
1887  }
1888  // Wipes and resets the nedtrie index
1889  void triehead_reindex()
1890  {
1891  NEDTRIE_INIT(&triehead);
1892  for(iterator it=begin(); it!=end(); ++it)
1893  {
1894  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
1895  it->trie_iterator=it;
1896  }
1897  }
1898  const mapvaluetype *triehead_find(const key_type &key) const
1899  { // Avoid a value_type construction using pure unmitigated evil
1900  char buffer[sizeof(mapvaluetype)];
1901  new(buffer) intern::keystore_t<key_type>(*(size_t *)"TRIEFINDKEYSTORE", key);
1902  return triefind<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<intern::findkeyfunct_t<keytype, type, mapvaluetype, keyfunct> > >(&triehead, (mapvaluetype *) buffer);
1903  }
1904  const mapvaluetype *triehead_nfind(const key_type &key) const
1905  { // Avoid a value_type construction using pure unmitigated evil
1906  char buffer[sizeof(mapvaluetype)];
1907  new(buffer) intern::keystore_t<key_type>(*(size_t *)"TRIEFINDKEYSTORE", key);
1908  return trieNfind<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<intern::findkeyfunct_t<keytype, type, mapvaluetype, keyfunct> > >(&triehead, (mapvaluetype *) buffer);
1909  }
1910  const mapvaluetype *triehead_cfind(const key_type &key, int rounds) const
1911  { // Avoid a value_type construction using pure unmitigated evil
1912  char buffer[sizeof(mapvaluetype)];
1913  new(buffer) intern::keystore_t<key_type>(*(size_t *)"TRIEFINDKEYSTORE", key);
1914  return trieCfind<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<intern::findkeyfunct_t<keytype, type, mapvaluetype, keyfunct> > >(&triehead, (mapvaluetype *) buffer, rounds);
1915  }
1916  iterator triehead_insert(const value_type &val)
1917  {
1918  iterator it=iterator(this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
1919  it->trie_iterator=from_iterator(it);
1920  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
1921  return it;
1922  }
1923 #ifdef HAVE_CPP0XRVALUEREFS
1924  iterator triehead_insert(value_type &&val)
1925  {
1926  iterator it=iterator(this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
1927  it->trie_iterator=from_iterator(it);
1928  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
1929  return it;
1930  }
1931 #endif
1932  iterator triehead_insert(const keytype &key, const value_type &val)
1933  {
1934  iterator it=iterator(this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
1935  it->trie_iterator=from_iterator(it);
1936  it->trie_keyvalue=key;
1937  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
1938  return it;
1939  }
1940 #ifdef HAVE_CPP0XRVALUEREFS
1941  iterator triehead_insert(const keytype &key, value_type &&val)
1942  {
1943  iterator it=iterator(this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
1944  it->trie_iterator=from_iterator(it);
1945  it->trie_keyvalue=key;
1946  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
1947  return it;
1948  }
1949 #endif
1950  public:
1951  iterator begin() { return iterator(this, stlcontainer::begin()); }
1952  const_iterator begin() const { return const_iterator(this, stlcontainer::begin()); }
1953  using stlcontainer::clear;
1955  size_type count(const key_type &key) const
1956  {
1957  size_type ret=0;
1958  const mapvaluetype *r=triehead_find(key);
1959  if(r)
1960  {
1961  if(r->trie_link.prev) r=r->trie_link.trie_prev;
1962  for(; r; r=r->trie_link.trie_next) ret++;
1963  }
1964  return ret;
1965  }
1966  using stlcontainer::empty;
1967  iterator end() { return iterator(this, stlcontainer::end()); }
1968  const_iterator end() const { return const_iterator(this, stlcontainer::end()); }
1969  //std::pair<iterator, iterator> equal_range(const key_type &key);
1970  //std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const;
1972  iterator erase(iterator it)
1973  {
1974  //int (*nobblefunct)(trietype *head)
1975  trieremove<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct>,
1976  // Need to give MSVC a little bit of help
1977 #ifdef _MSC_VER
1978  nobblepolicytype::trie_nobblefunction<trie_map_head<mapvaluetype> >
1979 #else
1980  nobblepolicytype::trie_nobblefunction
1981 #endif
1982  >(&triehead, &(*it));
1983  return iterator(this, stlcontainer::erase((typename stlcontainer::iterator &) it));
1984  }
1986  iterator erase(iterator first, iterator last)
1987  {
1988  iterator ret(last); ++ret;
1989  for(iterator it=first; it!=last; ++it)
1990  {
1991  trieremove<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct>,
1992 #ifdef _MSC_VER
1993  nobblepolicytype::trie_nobblefunction<trie_map_head<mapvaluetype> >
1994 #else
1995  nobblepolicytype::trie_nobblefunction
1996 #endif
1997  >(&triehead, &(*it));
1998  stlcontainer::erase((typename stlcontainer::iterator &) it);
1999  }
2000  return ret;
2001  }
2003  iterator find(const key_type &key) { const_iterator it=static_cast<const trie_map *>(this)->find(key); void *_it=(void *) &it; return *(iterator *)_it; }
2005  const_iterator find(const key_type &key) const
2006  {
2007  const mapvaluetype *r=triehead_find(key);
2008  return !r ? end() : const_iterator(this, (const typename stlcontainer::const_iterator &) r->trie_iterator); // type pun safe
2009  }
2011  iterator nfind(const key_type &key) { const_iterator it=static_cast<const trie_map *>(this)->nfind(key); void *_it=(void *) &it; return *(iterator *)_it; }
2013  const_iterator nfind(const key_type &key) const
2014  {
2015  const mapvaluetype *r=triehead_nfind(key);
2016  return !r ? end() : const_iterator(this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2017  }
2019  iterator cfind(const key_type &key, int rounds=INT_MAX) { const_iterator it=static_cast<const trie_map *>(this)->cfind(key, rounds); void *_it=(void *) &it; return *(iterator *)_it; }
2021  const_iterator cfind(const key_type &key, int rounds=INT_MAX) const
2022  {
2023  const mapvaluetype *r=triehead_cfind(key, rounds);
2024  return !r ? end() : const_iterator(this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2025  }
2026  using stlcontainer::get_allocator;
2028  std::pair<iterator, bool> insert(const value_type &val)
2029  {
2030  mapvaluetype *r=const_cast<mapvaluetype *>(triehead_find(keyfunct()(val)));
2031  if(r)
2032  {
2033  r->trie_value=std::move(val);
2034  return std::make_pair(iterator(this, (typename stlcontainer::iterator &) r->trie_iterator), false);
2035  }
2036  return std::make_pair(triehead_insert(std::move(val)), true);
2037  }
2039  iterator insert(iterator at, const value_type &val)
2040  {
2041  iterator it=stlcontainer::insert(at, val);
2042  it->trie_iterator=from_iterator(it);
2043  trieinsert<trie_map_head, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
2044  return it;
2045  }
2047  template<class inputiterator> void insert(inputiterator first, inputiterator last)
2048  {
2049  iterator it=--end();
2050  stlcontainer::insert(first, last);
2051  for(; it!=end(); ++it)
2052  {
2053  it->trie_iterator=from_iterator(it);
2054  trieinsert<trie_map_head, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
2055  }
2056  }
2057  //key_compare key_comp() const;
2058  //iterator lower_bound(const key_type &key);
2059  //const_iterator lower_bound(const key_type &key) const;
2060  using stlcontainer::max_size;
2061  reverse_iterator rbegin() { return reverse_iterator(this, stlcontainer::begin()); }
2062  const_reverse_iterator rbegin() const { return const_reverse_iterator(this, stlcontainer::begin()); }
2063  reverse_iterator rend() { return reverse_iterator(this, stlcontainer::end()); }
2064  const_reverse_iterator rend() const { return const_reverse_iterator(this, stlcontainer::end()); }
2065  using stlcontainer::size;
2066  using stlcontainer::swap;
2067  //iterator upper_bound(const key_type &key);
2068  //const_iterator upper_bound(const key_type &key) const;
2069  //value_compare value_comp() const;
2071  mapped_type &operator[](const keytype &key)
2072  {
2073  mapvaluetype *r=const_cast<mapvaluetype *>(triehead_find(key));
2074  iterator it;
2075  if(r)
2076  it=iterator(this, (typename stlcontainer::iterator &) r->trie_iterator); // type pun safe
2077  else
2078  {
2079  it=triehead_insert(key, std::move(type()));
2080  }
2081  return it->trie_value;
2082  }
2083 
2084  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator!=(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2085  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator<(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2086  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator<=(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2087  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator==(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2088  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator>(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2089  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator>=(const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_map<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2090 
2092  trie_map() : stlcontainer() { NEDTRIE_INIT(&triehead); }
2093  explicit trie_map(const allocator &a) : stlcontainer(a) { NEDTRIE_INIT(&triehead); }
2094  template<class okeytype, class otype, class oallocator> trie_map(const trie_map<okeytype, otype, oallocator> &o) : stlcontainer(o) { triehead_reindex(); }
2095  template<class okeytype, class otype, class oallocator> trie_map &operator=(const trie_map<okeytype, otype, oallocator> &o) { *static_cast<stlcontainer *>(this)=static_cast<const stlcontainer &>(o); triehead_reindex(); return *this; }
2096 #ifdef HAVE_CPP0XRVALUEREFS
2097  template<class okeytype, class otype, class oallocator> trie_map(trie_map<okeytype, otype, oallocator> &&o) : stlcontainer(std::move(o))
2098  {
2099  memcpy(&triehead, &o.triehead, sizeof(triehead));
2100  }
2101  template<class okeytype, class otype, class oallocator> trie_map &operator=(trie_map<okeytype, otype, oallocator> &&o)
2102  {
2103  *static_cast<stlcontainer *>(this)=std::move(static_cast<stlcontainer &&>(o));
2104  memcpy(&triehead, &o.triehead, sizeof(triehead));
2105  return *this;
2106  }
2107 #endif
2108  template<class inputiterator> trie_map(inputiterator s, inputiterator e) : stlcontainer(s, e) { triehead_reindex(); }
2109  template<class inputiterator> trie_map(inputiterator s, inputiterator e, const allocator &a) : stlcontainer(s, e, a) { triehead_reindex(); }
2110  };
2111  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator!=(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2112  {
2113  return static_cast<const stlcontainer &>(a)!=static_cast<const stlcontainer &>(b);
2114  }
2115  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator<(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2116  {
2117  return static_cast<const stlcontainer &>(a)<static_cast<const stlcontainer &>(b);
2118  }
2119  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator<=(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2120  {
2121  return static_cast<const stlcontainer &>(a)<=static_cast<const stlcontainer &>(b);
2122  }
2123  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator==(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2124  {
2125  return static_cast<const stlcontainer &>(a)==static_cast<const stlcontainer &>(b);
2126  }
2127  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator>(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2128  {
2129  return static_cast<const stlcontainer &>(a)>static_cast<const stlcontainer &>(b);
2130  }
2131  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator>=(const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2132  {
2133  return static_cast<const stlcontainer &>(a)>=static_cast<const stlcontainer &>(b);
2134  }
2135 
2175  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> class trie_multimap : protected stlcontainer, protected nobblepolicy<trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> >
2176  {
2177  typedef nobblepolicy<trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> > nobblepolicytype;
2178  typedef typename stlcontainer::value_type mapvaluetype;
2179  static const size_t trie_fieldoffset=mapvaluetype::trie_link_offset;
2180  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
2181  public:
2182  typedef typename stlcontainer::allocator_type allocator_type;
2183  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::const_iterator, 1, mapvaluetype> const_iterator;
2184  typedef typename stlcontainer::const_pointer const_pointer;
2185  typedef typename stlcontainer::const_reference const_reference;
2186  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::const_reverse_iterator, -1, mapvaluetype> const_reverse_iterator;
2187  typedef typename stlcontainer::difference_type difference_type;
2188  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::iterator, 1, mapvaluetype, const_iterator> iterator;
2189  typedef keytype key_type;
2190  typedef type mapped_type;
2191  typedef typename stlcontainer::pointer pointer;
2192  typedef typename stlcontainer::reference reference;
2193  typedef trie_iterator<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer, typename stlcontainer::reverse_iterator, -1, mapvaluetype, const_reverse_iterator> reverse_iterator;
2194  typedef typename stlcontainer::size_type size_type;
2195  typedef typename stlcontainer::value_type::trie_value_type value_type;
2196  private:
2197  trie_map_head<mapvaluetype> triehead;
2198  static typename mapvaluetype::trie_iterator_type &from_iterator(iterator &it)
2199  {
2200  void *_it=(void *) &it;
2201  return *(typename mapvaluetype::trie_iterator_type *)_it;
2202  }
2203  // Wipes and resets the nedtrie index
2204  void triehead_reindex()
2205  {
2206  NEDTRIE_INIT(&triehead);
2207  for(iterator it=begin(); it!=end(); ++it)
2208  {
2209  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
2210  it->trie_iterator=it;
2211  }
2212  }
2213  const mapvaluetype *triehead_find(const key_type &key) const
2214  { // Avoid a value_type construction using pure unmitigated evil
2215  char buffer[sizeof(mapvaluetype)];
2216  new(buffer) intern::keystore_t<key_type>(*(size_t *)"TRIEFINDKEYSTORE", key);
2217  return triefind<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<intern::findkeyfunct_t<keytype, type, mapvaluetype, keyfunct> > >(&triehead, (mapvaluetype *) buffer);
2218  }
2219  iterator triehead_insert(const value_type &val)
2220  {
2221  iterator it=iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
2222  it->trie_iterator=from_iterator(it);
2223  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
2224  return it;
2225  }
2226 #ifdef HAVE_CPP0XRVALUEREFS
2227  iterator triehead_insert(value_type &&val)
2228  {
2229  iterator it=iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
2230  it->trie_iterator=from_iterator(it);
2231  trieinsert<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, const_cast<mapvaluetype *>(&(*it)));
2232  return it;
2233  }
2234 #endif
2235  public:
2236  iterator begin() { return iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::begin()); }
2237  const_iterator begin() const { return const_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::begin()); }
2238  using stlcontainer::clear;
2240  size_type count(const key_type &key) const
2241  {
2242  size_type ret=0;
2243  const mapvaluetype *r=triehead_find(key);
2244  if(r)
2245  {
2246  if(r->trie_link.prev) r=r->trie_link.trie_prev;
2247  for(; r; r=r->trie_link.trie_next) ret++;
2248  }
2249  return ret;
2250  }
2251  using stlcontainer::empty;
2252  iterator end() { return iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::end()); }
2253  const_iterator end() const { return const_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::end()); }
2254  //std::pair<iterator, iterator> equal_range(const key_type &key);
2255  //std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const;
2257  iterator erase(iterator it)
2258  {
2259  //int (*nobblefunct)(trietype *head)
2260  trieremove<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct>,
2261  // Need to give MSVC a little bit of help
2262 #ifdef _MSC_VER
2263  nobblepolicytype::trie_nobblefunction<trie_map_head<mapvaluetype> >
2264 #else
2265  nobblepolicytype::trie_nobblefunction
2266 #endif
2267  >(&triehead, &(*it));
2268  return iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::erase((typename stlcontainer::iterator &) it));
2269  }
2271  iterator erase(iterator first, iterator last)
2272  {
2273  iterator ret(last); ++ret;
2274  for(iterator it=first; it!=last; ++it)
2275  {
2276  trieremove<trie_map_head<mapvaluetype>, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct>,
2277 #ifdef _MSC_VER
2278  nobblepolicytype::trie_nobblefunction<trie_map_head<mapvaluetype> >
2279 #else
2280  nobblepolicytype::trie_nobblefunction
2281 #endif
2282  >(&triehead, &(*it));
2283  stlcontainer::erase((typename stlcontainer::iterator &) it);
2284  }
2285  return ret;
2286  }
2288  iterator find(const key_type &key) { const_iterator it=static_cast<const trie_multimap *>(this)->find(key); void *_it=(void *) &it; return *(iterator *)_it; }
2290  const_iterator find(const key_type &key) const
2291  {
2292  const mapvaluetype *r=triehead_find(key);
2293  return !r ? end() : const_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2294  }
2296  iterator nfind(const key_type &key) { const_iterator it=static_cast<const trie_multimap *>(this)->nfind(key); void *_it=(void *) &it; return *(iterator *)_it; }
2298  const_iterator nfind(const key_type &key) const
2299  {
2300  const mapvaluetype *r=triehead_nfind(key);
2301  return !r ? end() : const_iterator(this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2302  }
2304  iterator cfind(const key_type &key, int rounds=INT_MAX) { const_iterator it=static_cast<const trie_multimap *>(this)->cfind(key, rounds); void *_it=(void *) &it; return *(iterator *)_it; }
2306  const_iterator cfind(const key_type &key, int rounds=INT_MAX) const
2307  {
2308  const mapvaluetype *r=triehead_cfind(key, rounds);
2309  return !r ? end() : const_iterator(this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2310  }
2311  using stlcontainer::get_allocator;
2313  iterator insert(const value_type &val)
2314  {
2315  return triehead_insert(std::move(val));
2316  }
2318  iterator insert(iterator at, const value_type &val)
2319  {
2320  iterator it=stlcontainer::insert(at, val);
2321  it->trie_iterator=from_iterator(it);
2322  trieinsert<trie_map_head, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
2323  return it;
2324  }
2326  template<class inputiterator> void insert(inputiterator first, inputiterator last)
2327  {
2328  iterator it=--end();
2329  stlcontainer::insert(first, last);
2330  for(; it!=end(); ++it)
2331  {
2332  it->trie_iterator=from_iterator(it);
2333  trieinsert<trie_map_head, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct<keyfunct> >(&triehead, &(*it));
2334  }
2335  }
2336  //key_compare key_comp() const;
2337  //iterator lower_bound(const key_type &key);
2338  //const_iterator lower_bound(const key_type &key) const;
2339  using stlcontainer::max_size;
2340  reverse_iterator rbegin() { return reverse_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::begin()); }
2341  const_reverse_iterator rbegin() const { return const_reverse_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::begin()); }
2342  reverse_iterator rend() { return reverse_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::end()); }
2343  const_reverse_iterator rend() const { return const_reverse_iterator((trie_map<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> *) this, stlcontainer::end()); }
2344  using stlcontainer::size;
2345  using stlcontainer::swap;
2346  //iterator upper_bound(const key_type &key);
2347  //const_iterator upper_bound(const key_type &key) const;
2348  //value_compare value_comp() const;
2349 
2350  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator!=(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2351  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator<(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2352  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator<=(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2353  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator==(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2354  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator>(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2355  template<class keytype_, class type_, class keyfunct_, class allocator_, template<class> class nobblepolicy_, class stlcontainer_> friend bool operator>=(const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &a, const trie_multimap<keytype_, type_, keyfunct_, allocator_, nobblepolicy_, stlcontainer_> &b);
2356 
2358  trie_multimap() : stlcontainer() { NEDTRIE_INIT(&triehead); }
2359  explicit trie_multimap(const allocator &a) : stlcontainer(a) { NEDTRIE_INIT(&triehead); }
2360  template<class okeytype, class otype, class oallocator> trie_multimap(const trie_multimap<okeytype, otype, oallocator> &o) : stlcontainer(o) { triehead_reindex(); }
2361  template<class okeytype, class otype, class oallocator> trie_multimap &operator=(const trie_multimap<okeytype, otype, oallocator> &o) { *static_cast<stlcontainer *>(this)=static_cast<const stlcontainer &>(o); triehead_reindex(); return *this; }
2362 #ifdef HAVE_CPP0XRVALUEREFS
2363  template<class okeytype, class otype, class oallocator> trie_multimap(trie_multimap<okeytype, otype, oallocator> &&o) : stlcontainer(std::move(o))
2364  {
2365  memcpy(&triehead, &o.triehead, sizeof(triehead));
2366  }
2367  template<class okeytype, class otype, class oallocator> trie_multimap &operator=(trie_multimap<okeytype, otype, oallocator> &&o)
2368  {
2369  *static_cast<stlcontainer *>(this)=std::move(static_cast<stlcontainer &&>(o));
2370  memcpy(&triehead, &o.triehead, sizeof(triehead));
2371  return *this;
2372  }
2373 #endif
2374  template<class inputiterator> trie_multimap(inputiterator s, inputiterator e) : stlcontainer(s, e) { triehead_reindex(); }
2375  template<class inputiterator> trie_multimap(inputiterator s, inputiterator e, const allocator &a) : stlcontainer(s, e, a) { triehead_reindex(); }
2376  };
2377  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator!=(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, allocator, keyfunct, nobblepolicy, stlcontainer> &b)
2378  {
2379  return static_cast<const stlcontainer &>(a)!=static_cast<const stlcontainer &>(b);
2380  }
2381  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator<(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, allocator, keyfunct, nobblepolicy, stlcontainer> &b)
2382  {
2383  return static_cast<const stlcontainer &>(a)<static_cast<const stlcontainer &>(b);
2384  }
2385  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator<=(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, allocator, keyfunct, nobblepolicy, stlcontainer> &b)
2386  {
2387  return static_cast<const stlcontainer &>(a)<=static_cast<const stlcontainer &>(b);
2388  }
2389  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator==(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, allocator, keyfunct, nobblepolicy, stlcontainer> &b)
2390  {
2391  return static_cast<const stlcontainer &>(a)==static_cast<const stlcontainer &>(b);
2392  }
2393  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator>(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, allocator, keyfunct, nobblepolicy, stlcontainer> &b)
2394  {
2395  return static_cast<const stlcontainer &>(a)>static_cast<const stlcontainer &>(b);
2396  }
2397  template<class keytype, class type, class keyfunct, class allocator, template<class> class nobblepolicy, class stlcontainer> bool operator>=(const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &a, const trie_multimap<keytype, type, keyfunct, allocator, nobblepolicy, stlcontainer> &b)
2398  {
2399  return static_cast<const stlcontainer &>(a)>=static_cast<const stlcontainer &>(b);
2400  }
2401 
2402 #endif
2403 
2404 } /* namespace */
2405 
2406 #ifdef _MSC_VER
2407 #pragma warning(pop)
2408 #endif
2409 #endif
void triecheckvaliditybranch(trietype *head, type *node, unsigned bitidx, TrieValidityState &state)
Definition: nedtrie.h:1402
size_t n
Definition: nedtrie.h:302
int trienobblezeros(trietype *)
Definition: nedtrie.h:258
size_t largestkey
Definition: nedtrie.h:1398
size_t leafs
Definition: nedtrie.h:1398
#define INLINE
Defined to the inline keyword or equivalent if available.
Definition: nedtrie.h:67
Definition: nedtrie.h:302
type * triefind(const trietype *head, const type *r)
Definition: nedtrie.h:608
STL namespace.
Definition: nedtrie.h:256
void triecheckvalidity(trietype *head)
Definition: nedtrie.h:1443
Definition: nedtrie.h:1396
type * trienext(const trietype *head, const type *r)
Definition: nedtrie.h:1142
void trieremove(trietype *head, type *r)
Definition: nedtrie.h:426
#define NEDTRIE_ENTRY(type)
Substitutes the type used to store the per-node trie information. Occupies 5*sizeof(size_t).
Definition: nedtrie.h:231
#define NEDTRIE_INDEXBINS
Defines the number of top level bit bins to use. The default based on size_t is usually fine...
Definition: nedtrie.h:217
size_t smallestkey
Definition: nedtrie.h:1398
size_t tops
Definition: nedtrie.h:1398
#define NEDTRIE_HEAD2(name, type)
Definition: nedtrie.h:221
int trienobbleones(trietype *)
Definition: nedtrie.h:262
Definition: nedtrie.h:303
struct nedtries::testtrielinksize::foo1::@0 link
#define DEBUGINLINE
Defined to be INLINE when NDEBUG is defined, NOINLINE when DEBUG is defined, unset otherwise...
Definition: nedtrie.h:102
type * trieprev(const trietype *head, const type *r)
Definition: nedtrie.h:1004
type * trieminmax(const trietype *head, const unsigned dir)
Definition: nedtrie.h:893
size_t count
Definition: nedtrie.h:1398
type * triebranchprev(const type *r, const TrieLink_t< type > **rlinkaddr)
Definition: nedtrie.h:961
void trieinsert(trietype *head, type *r)
Definition: nedtrie.h:320
size_t rights
Definition: nedtrie.h:1398
type * trieNfind(const trietype *head, const type *r)
Definition: nedtrie.h:1212
type * trieCfind(const trietype *head, const type *r, int rounds)
Definition: nedtrie.h:728
int trieexactfind(const trietype *head, const type *r)
Definition: nedtrie.h:683
struct nedtries::TrieValidityState_t TrieValidityState
#define NEDTRIEFIELDOFFSET2(type, field)
Definition: nedtrie.h:314
int trienobbleequally(trietype *head)
Definition: nedtrie.h:266
#define RESTRICT
Defined to the restrict keyword or equivalent if available.
Definition: nedtrie.h:59
size_t lefts
Definition: nedtrie.h:1398
#define NEDTRIE_INIT(root)
Initialises a nedtrie for usage.
Definition: nedtrie.h:241
type * triebranchnext(const type *r, const TrieLink_t< type > **rlinkaddr)
Definition: nedtrie.h:1103
size_t n
Definition: nedtrie.h:303
TrieLink_t< foo2 > link
Definition: nedtrie.h:303