File Coverage

nedtrie.h
Criterion Covered Total %
statement 3 3 100.0
branch 1 2 50.0
condition n/a
subroutine n/a
pod n/a
total 4 5 80.0


line stmt bran cond sub pod time code
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
31             #include
32             #include
33             #include /* for memset */
34             #include /* 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              
45             /*! \def RESTRICT
46             \brief Defined to the restrict keyword or equivalent if available */
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              
63             /*! \def INLINE
64             \brief Defined to the inline keyword or equivalent if available */
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              
81             /*! \def NOINLINE
82             \brief Defined to whatever compiler magic inhibits inlining if available */
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              
93             /*! \def DEBUGINLINE
94             \brief Defined to be INLINE when NDEBUG is defined, NOINLINE when DEBUG is defined, unset otherwise.
95             */
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              
106             /*! \def NEDTRIEUSEMACROS
107             \brief Define to 1 to force usage of the macro implementation of nedtries. This is always 1 when
108             compiling in C, but defaults to 0 when compiling in C++ as a template function implementation offers
109             much more scope to the optimiser and is much easier to debug.
110             */
111             #ifndef NEDTRIEUSEMACROS
112             #ifdef __cplusplus
113             #define NEDTRIEUSEMACROS 0
114             #else
115             #define NEDTRIEUSEMACROS 1
116             #endif
117             #endif
118              
119             /*! \def NEDTRIEDEBUG
120             \brief Define to 1 if you wish a full trie validation to be performed every time you modify the trie.
121             Requires assert() to work, so disables itself if NDEBUG is defined.
122             */
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
138             #endif
139              
140             #ifdef __cplusplus
141             #include
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 T &move(T &a) { return a; }
147             template T &move(const T &a) { return const_cast(a); }
148             template T &forward(A &a) { return a; }
149             }
150             #endif
151             namespace {
152             #endif
153 355           static INLINE unsigned nedtriebitscanr(size_t value)
154             {
155 355 50         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 355           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              
214             /*! \def NEDTRIE_INDEXBINS
215             \brief Defines the number of top level bit bins to use. The default based on size_t is usually fine.
216             */
217             #define NEDTRIE_INDEXBINS (8*sizeof(void *))
218             /*! \def NEDTRIE_HEAD
219             \brief Substitutes the type used to store the head of the trie.
220             */
221             #define NEDTRIE_HEAD2(name, type) \
222             struct name { \
223             size_t count; \
224             type *triebins[NEDTRIE_INDEXBINS]; /* each containing (1<
225             int nobbledir; \
226             }
227             #define NEDTRIE_HEAD(name, type) NEDTRIE_HEAD2(name, struct type)
228             /*! \def NEDTRIE_ENTRY
229             \brief Substitutes the type used to store the per-node trie information. Occupies 5*sizeof(size_t).
230             */
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             /*! \def NEDTRIE_INIT
239             \brief Initialises a nedtrie for usage.
240             */
241             #define NEDTRIE_INIT(root) do { memset((root), 0, sizeof(*(root))); } while(0)
242             /*! \def NEDTRIE_EMPTY
243             \brief Returns whether a nedtrie is empty.
244             */
245             #define NEDTRIE_EMPTY(head) (!(head)->count)
246             /*! \def NEDTRIE_COUNT
247             \brief Returns the number of items in a nedtrie.
248             */
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 int trienobblezeros(trietype *)
259             {
260             return 0;
261             }
262             template int trienobbleones(trietype *)
263             {
264             return 1;
265             }
266             template int trienobbleequally(trietype *head)
267             {
268             return (head->nobbledir=!head->nobbledir);
269             }
270             /*! \def NEDTRIE_NOBBLEZEROS
271             \brief A nobble function which preferentially nobbles zeros.
272             */
273             #define NEDTRIE_NOBBLEZEROS(name) nedtries::trienobblezeros
274             /*! \def NEDTRIE_NOBBLEONES
275             \brief A nobble function which preferentially nobbles ones.
276             */
277             #define NEDTRIE_NOBBLEONES(name) nedtries::trienobbleones
278             /*! \def NEDTRIE_NOBBLEEQUALLY
279             \brief A nobble function which alternates between nobbling zeros and ones.
280             */
281             #define NEDTRIE_NOBBLEEQUALLY(name) nedtries::trienobbleequally
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 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 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 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 DEBUGINLINE void trieinsert(trietype *RESTRICT head, type *RESTRICT r)
321             {
322             type *RESTRICT node, *RESTRICT childnode;
323             TrieLink_t *RESTRICT nodelink, *RESTRICT rlink;
324             size_t rkey=keyfunct(r), keybit, nodekey;
325             unsigned bitidx;
326             int keybitset;
327              
328             rlink=(TrieLink_t *RESTRICT)((size_t) r + fieldoffset);
329             memset(rlink, 0, sizeof(TrieLink_t));
330             bitidx=nedtriebitscanr(rkey);
331             assert(bitidx
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<
340             for(;;node=childnode)
341             {
342             nodelink=(TrieLink_t *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 *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(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
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<
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(head, r); \
421             }
422             #endif /* NEDTRIEUSEMACROS */
423              
424             #ifdef __cplusplus
425             namespace nedtries {
426             template DEBUGINLINE void trieremove(trietype *RESTRICT head, type *RESTRICT r)
427             {
428             type *RESTRICT node, **myaddrinparent=0;
429             TrieLink_t *RESTRICT nodelink, *RESTRICT childlink, *RESTRICT rlink;
430             unsigned bitidx;
431              
432             rlink=(TrieLink_t *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 *RESTRICT)((size_t) node + fieldoffset);
439             nodelink->trie_next=rlink->trie_next;
440             if(rlink->trie_next)
441             {
442             nodelink=(TrieLink_t *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 *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 *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 *RESTRICT)((size_t) *childaddrinparent + fieldoffset))->trie_child[nobbledir]))
485             || *(newchildaddrinparent=&(((TrieLink_t *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 *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 *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 *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(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(head, r); \
603             }
604             #endif /* NEDTRIEUSEMACROS */
605              
606             #ifdef __cplusplus
607             namespace nedtries {
608             template DEBUGINLINE type *triefind(const trietype *RESTRICT head, const type *RESTRICT r)
609             {
610             const type *RESTRICT node, *RESTRICT childnode;
611             const TrieLink_t *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 *RESTRICT)((size_t) r + fieldoffset);
618             bitidx=nedtriebitscanr(rkey);
619             assert(bitidx
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<
624             for(;;node=childnode)
625             {
626             nodelink=(const TrieLink_t *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
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<
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(head, r); \
678             }
679             #endif /* NEDTRIEUSEMACROS */
680              
681             #ifdef __cplusplus
682             namespace nedtries {
683             template DEBUGINLINE int trieexactfind(const trietype *RESTRICT head, const type *RESTRICT r)
684             {
685             const type *RESTRICT node;
686             const TrieLink_t *RESTRICT nodelink;
687              
688             if(!head->count) return 0;
689             if(!(node=triefind(head, r))) return 0;
690             nodelink=(const TrieLink_t *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 *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(head, r); \
723             }
724             #endif /* NEDTRIEUSEMACROS */
725              
726             #ifdef __cplusplus
727             namespace nedtries {
728             template 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 *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 *RESTRICT)((size_t) r + fieldoffset);
738             binbitidx=nedtriebitscanr(rkey);
739             assert(binbitidx
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(binbitidxtriebins[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<
752             nodelink=(const TrieLink_t *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
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 *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
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
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 *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
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(binbitidxtriebins[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<
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
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
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
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(head, r, rounds); \
888             }
889             #endif /* NEDTRIEUSEMACROS */
890              
891             #ifdef __cplusplus
892             namespace nedtries {
893             template DEBUGINLINE type *trieminmax(const trietype *RESTRICT head, const unsigned dir)
894             {
895             const type *RESTRICT node=0, *RESTRICT child;
896             const TrieLink_t *RESTRICT nodelink;
897             unsigned bitidx;
898             if(!head->count) return 0;
899             if(!dir)
900             { /* He wants min */
901             for(bitidx=0; bitidxtriebins[bitidx]); bitidx++);
902             assert(node);
903             return (type *) node;
904             }
905             /* He wants max */
906             for(bitidx=NEDTRIE_INDEXBINS-1; bitidxtriebins[bitidx]); bitidx--);
907             assert(node);
908             nodelink=(const TrieLink_t *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 *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 *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; bitidxtriebins[bitidx]); bitidx++); \
934             assert(node); \
935             return node; \
936             } \
937             /* He wants max */ \
938             for(bitidx=NEDTRIE_INDEXBINS-1; bitidxtriebins[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(head, dir); \
956             }
957             #endif /* NEDTRIEUSEMACROS */
958              
959             #ifdef __cplusplus
960             namespace nedtries {
961             template DEBUGINLINE type *triebranchprev(const type *RESTRICT r, const TrieLink_t *RESTRICT *rlinkaddr)
962             {
963             const type *RESTRICT node=0, *RESTRICT child;
964             const TrieLink_t *RESTRICT nodelink, *RESTRICT rlink;
965              
966             rlink=(TrieLink_t *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 *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 *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 *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 *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 DEBUGINLINE type *trieprev(const trietype *RESTRICT head, const type *RESTRICT r)
1005             {
1006             const type *RESTRICT node=0, *RESTRICT child;
1007             const TrieLink_t *RESTRICT nodelink, *RESTRICT rlink=0;
1008             unsigned bitidx;
1009              
1010             if((node=triebranchprev(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--; bitidxtriebins[bitidx]); bitidx--);
1015             if(bitidx>=NEDTRIE_INDEXBINS) return 0;
1016             nodelink=(const TrieLink_t *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 *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 *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--; bitidxtriebins[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(head, r); \
1098             }
1099             #endif /* NEDTRIEUSEMACROS */
1100              
1101             #ifdef __cplusplus
1102             namespace nedtries {
1103             template DEBUGINLINE type *triebranchnext(const type *RESTRICT r, const TrieLink_t *RESTRICT *rlinkaddr)
1104             {
1105             const type *RESTRICT node;
1106             const TrieLink_t *RESTRICT nodelink, *RESTRICT rlink;
1107              
1108             rlink=(const TrieLink_t *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 *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 *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 *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 DEBUGINLINE type *trienext(const trietype *RESTRICT head, const type *RESTRICT r)
1143             {
1144             const type *RESTRICT node;
1145             const TrieLink_t *RESTRICT rlink=0;
1146             unsigned bitidx;
1147              
1148             if((node=triebranchnext(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++; bitidxtriebins[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++; bitidxtriebins[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(head, r); \
1207             }
1208             #endif /* NEDTRIEUSEMACROS */
1209              
1210             #ifdef __cplusplus
1211             namespace nedtries {
1212             template DEBUGINLINE type *trieNfind(const trietype *RESTRICT head, const type *RESTRICT r)
1213             {
1214             const type *RESTRICT node=0, *RESTRICT ret=trieCfind(head, r, INT_MAX), *RESTRICT stop;
1215             const TrieLink_t *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 *RESTRICT)((size_t) ret + fieldoffset);
1226             stop=rlink->trie_parent;
1227             for(node=triebranchnext(ret, 0); node && node!=stop; node=triebranchnext(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
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
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(head, r); \
1273             }
1274             #endif /* NEDTRIEUSEMACROS */
1275              
1276              
1277             /*! \def NEDTRIE_GENERATE
1278             \brief Substitutes a set of nedtrie implementation function definitions specialised according to type.
1279             */
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              
1294             /*! \def NEDTRIE_INSERT
1295             \brief Inserts item y into nedtrie x.
1296             */
1297             #define NEDTRIE_INSERT(name, x, y) name##_NEDTRIE_INSERT(x, y)
1298             /*! \def NEDTRIE_REMOVE
1299             \brief Removes item y from nedtrie x.
1300             */
1301             #define NEDTRIE_REMOVE(name, x, y) name##_NEDTRIE_REMOVE(x, y)
1302             /*! \def NEDTRIE_FIND
1303             \brief Finds the item with the same key as y in nedtrie x.
1304             */
1305             #define NEDTRIE_FIND(name, x, y) name##_NEDTRIE_FIND(x, y)
1306             /*! \def NEDTRIE_EXACTFIND
1307             \brief Returns true if there is an item with the same key and address as y in nedtrie x.
1308             */
1309             #define NEDTRIE_EXACTFIND(name, x, y) name##_NEDTRIE_EXACTFIND(x, y)
1310             /*! \def NEDTRIE_CFIND
1311             \brief Performs \em rounds number of attempts to find an item with an equal key to y in nedtrie x, and
1312             if none equal then the closest item with a larger key. Always returns a larger key if there is a larger
1313             key in the trie, if there isn't it returns zero. Think of rounds as how closely you want the find to fit
1314             the requested key, so \c INT_MAX means "as close as possible". Note that Cfind does NOT guarantee that
1315             the item returned is the next largest keyed item, use Nfind for that.
1316             */
1317             #define NEDTRIE_CFIND(name, x, y, rounds) name##_NEDTRIE_CFIND(x, y, rounds)
1318             /*! \def NEDTRIE_NFIND
1319             \brief Finds an item with an equal key to y in nedtrie x, and if none equal then the item with the next
1320             largest key. If the key is not equal, the returned item is guaranteed to be the next largest keyed item.
1321             */
1322             #define NEDTRIE_NFIND(name, x, y) name##_NEDTRIE_NFIND(x, y)
1323             /*! \def NEDTRIE_PREV
1324             \brief Returns the item preceding y in nedtrie x.
1325             */
1326             #define NEDTRIE_PREV(name, x, y) name##_NEDTRIE_PREV(x, y)
1327             /*! \def NEDTRIE_NEXT
1328             \brief Returns the item following y in nedtrie x.
1329             */
1330             #define NEDTRIE_NEXT(name, x, y) name##_NEDTRIE_NEXT(x, y)
1331             /*! \def NEDTRIE_PREVLEAF
1332             \brief Returns the item with an identical key preceding y in nedtrie x.
1333             */
1334             #define NEDTRIE_PREVLEAF(name, x) name##_NEDTRIE_PREVLEAF(x)
1335             /*! \def NEDTRIE_NEXTLEAF
1336             \brief Returns the item with an identical key following y in nedtrie x.
1337             */
1338             #define NEDTRIE_NEXTLEAF(name, x) name##_NEDTRIE_NEXTLEAF(x)
1339             /*! \def NEDTRIE_MIN
1340             \brief Returns the lowest item in nedtrie x. This item will approximately have the smallest key.
1341             */
1342             #define NEDTRIE_MIN(name, x) name##_NEDTRIE_MINMAX(x, 0)
1343             /*! \def NEDTRIE_MAX
1344             \brief Returns the highest item in nedtrie x. This item will approximately have the biggest key.
1345             */
1346             #define NEDTRIE_MAX(name, x) name##_NEDTRIE_MINMAX(x, 1)
1347              
1348             /*! \def NEDTRIE_FOREACH
1349             \brief Substitutes a for loop which forward iterates into x all items in nedtrie head. Order of
1350             items is mostly in key order (enough that a bubble sort is efficient).
1351             */
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              
1357             /*! \def NEDTRIE_FOREACH_SAFE
1358             \brief Substitutes a for loop which forward iterates into x all items in
1359             nedtrie head and is safe against removal of x. Order of items is mostly
1360             in key order (enough that a bubble sort is efficient).
1361             */
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              
1367             /*! \def NEDTRIE_FOREACH_REVERSE
1368             \brief Substitutes a for loop which reverse iterates into x all items in nedtrie head. Order of
1369             items is mostly inverse to key order (enough that a bubble sort is efficient).
1370             */
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              
1376             /*! \def NEDTRIE_FOREACH_REVERSE_SAFE
1377             \brief Substitutes a for loop which reverse iterates into x all items in nedtrie head and is
1378             safe against removal of x. Order of items is mostly inverse to key order (enough that a bubble
1379             sort is efficient).
1380             */
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              
1386             /*! \def NEDTRIE_HASNODEHEADER
1387             \brief Returns true if this item's node header is active. Useful as a quick check for whether a node is in some trie.
1388             */
1389             #define NEDTRIE_HASNODEHEADER(treevar, node, link) ((node)->link.trie_parent || (node)->link.trie_prev)
1390              
1391             #ifdef __cplusplus
1392             #include
1393             namespace nedtries {
1394              
1395             #ifndef NDEBUG
1396             typedef struct TrieValidityState_t
1397             {
1398             size_t count, smallestkey, largestkey, tops, lefts, rights, leafs;
1399             } TrieValidityState;
1400              
1401             template DEBUGINLINE
1402             void triecheckvaliditybranch(trietype *head, type *RESTRICT node, unsigned bitidx, TrieValidityState &state)
1403             {
1404             type *RESTRICT child;
1405             TrieLink_t *RESTRICT nodelink, *RESTRICT childlink;
1406             size_t nodekey=keyfunct(node);
1407              
1408             if(nodekey
1409             if(nodekey>state.largestkey) state.largestkey=nodekey;
1410             nodelink=(TrieLink_t *RESTRICT)((size_t) node + fieldoffset);
1411             assert(nodelink->trie_parent);
1412             child=nodelink->trie_parent;
1413             childlink=(TrieLink_t *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<
1416             assert(!nodelink->trie_prev);
1417             while((child=nodelink->trie_next))
1418             {
1419             state.leafs++;
1420             childlink=(TrieLink_t *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 *RESTRICT)((size_t) childlink->trie_next + fieldoffset))->trie_prev);
1426             nodelink=childlink;
1427             state.count++;
1428             }
1429             nodelink=(TrieLink_t *RESTRICT)((size_t) node + fieldoffset);
1430             state.count++;
1431             if(nodelink->trie_child[0])
1432             {
1433             state.lefts++;
1434             triecheckvaliditybranch(head, nodelink->trie_child[0], bitidx-1, state);
1435             }
1436             if(nodelink->trie_child[1])
1437             {
1438             state.rights++;
1439             triecheckvaliditybranch(head, nodelink->trie_child[1], bitidx-1, state);
1440             }
1441             }
1442             #endif
1443             template DEBUGINLINE void triecheckvalidity(trietype *head)
1444             {
1445             #ifndef NDEBUG
1446             type *RESTRICT node, *RESTRICT child;
1447             TrieLink_t *RESTRICT nodelink, *RESTRICT childlink;
1448             unsigned n, bitidx;
1449             TrieValidityState state={0};
1450             for(n=0; n
1451             {
1452             if((node=head->triebins[n]))
1453             {
1454             size_t nodekey=keyfunct(node);
1455             state.tops++;
1456             nodelink=(TrieLink_t *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)<
1461             assert(!nodelink->trie_prev);
1462             while((child=nodelink->trie_next))
1463             {
1464             state.leafs++;
1465             childlink=(TrieLink_t *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 *RESTRICT)((size_t) childlink->trie_next + fieldoffset))->trie_prev);
1471             nodelink=childlink;
1472             state.count++;
1473             }
1474             nodelink=(TrieLink_t *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(head, nodelink->trie_child[0], bitidx-1, state);
1482             assert(!state.smallestkey || state.smallestkey>=(size_t)1<
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(head, nodelink->trie_child[1], bitidx-1, state);
1491             assert(state.smallestkey>=(size_t)1<
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(head, 0); node; (node=trienext(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(head, 1); node; (node=trieprev(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             /*! \def HAVE_CPP0XRVALUEREFS
1530             \ingroup C++
1531             \brief Enables rvalue references
1532              
1533             Define to enable the usage of rvalue references which enables move semantics and
1534             other things. Automatically defined if __cplusplus indicates a C++0x compiler,
1535             otherwise you'll need to set it yourself.
1536             */
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              
1544             /*! \brief The policy namespace in which all nedtries policies live. */
1545             namespace nedpolicy
1546             {
1547             /*! \class nobblezeros
1548             \brief A policy nobbling zeros
1549             */
1550             template class nobblezeros
1551             {
1552             protected:
1553             template static int trie_nobblefunction(trietype *)
1554             {
1555             return 0;
1556             }
1557             };
1558             /*! \class nobbleones
1559             \brief A policy nobbling ones
1560             */
1561             template class nobbleones
1562             {
1563             protected:
1564             template static int trie_nobblefunction(trietype *)
1565             {
1566             return 1;
1567             }
1568             };
1569             /*! \class nobbleequally
1570             \brief A policy nobbling zeros and ones equally
1571             */
1572             template class nobbleequally
1573             {
1574             protected:
1575             template static int trie_nobblefunction(trietype *head)
1576             {
1577             return (head->nobbledir=!head->nobbledir);
1578             }
1579             };
1580             } // namspace
1581             template NEDTRIE_HEAD2(trie_map_head, type);
1582             template struct trie_maptype;
1583             /*! \struct trie_keyfunct
1584             \ingroup C++
1585             \brief Calculates the key for a given instance of type
1586              
1587             You only really need to use this if you are using trie_multimap or trie_map without the operator[]
1588             override. If using with trie_map, make sure you force the use of trie_keyfunct in its template
1589             parameters as it defaults to an internal thunk type used to indirect access to an embedded key store.
1590              
1591             Specialise this as follows for your type:
1592             \code
1593             namespace nedtries {
1594             template<> struct trie_keyfunct : public std::unary_function
1595             {
1596             size_t operator()(const yourtype *RESTRICT v) const
1597             {
1598             return v->yourtypekeyvalue;
1599             }
1600             };
1601             }
1602             \endcode
1603             */
1604             template struct trie_keyfunct : public std::unary_function
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 struct trie_maptype_keyfunct : public std::unary_function
1617             {
1618             template keytype operator()(const maptype &v) const
1619             {
1620             return v.trie_keyvalue;
1621             }
1622             };
1623             namespace intern {
1624             template struct noconstiteratortype : public type { };
1625             template size_t to_Ckeyfunct(const mapvaluetype *RESTRICT v)
1626             {
1627             return keyfunct_()(*v);
1628             }
1629             }
1630             template class nobblepolicy, class stlcontainer,
1631             class iteratortype, int dir, class mapvaluetype, class constiteratortype=intern::noconstiteratortype > class trie_iterator;
1632             template,
1633             class allocator=std::allocator::iterator> >,
1634             template class nobblepolicy=nedpolicy::nobblezeros,
1635             class stlcontainer=std::list::iterator>, allocator> > class trie_map;
1636             template,
1637             class allocator=std::allocator::iterator> >,
1638             template class nobblepolicy=nedpolicy::nobblezeros,
1639             class stlcontainer=std::list::iterator>, allocator> > class trie_multimap;
1640             /*! \struct trie_maptype
1641             \ingroup C++
1642             \brief Encapsulates the nedtrie metadata with the given type
1643              
1644             Note that the nedtrie metadata is kept \em after the typed value - this prevents the nedtrie metadata interfering
1645             with any special data alignment you might be using from a specialised STL allocator.
1646             */
1647             namespace fake {
1648             template struct trie_maptype
1649             {
1650             template friend struct trie_keyfunct;
1651             template class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1652             template class nobblepolicy, class stlcontainer> friend class trie_map;
1653             template 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 trie_link;
1661             };
1662             }
1663             template struct trie_maptype
1664             {
1665             private: // ENSURE the fake type above mirrors this one
1666             template friend struct trie_keyfunct;
1667             template class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1668             template class nobblepolicy, class stlcontainer> friend class trie_map;
1669             template 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 fakemirrorofme_type;
1675             type trie_value;
1676             iteratortype trie_iterator;
1677             TrieLink_t 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 trie_maptype(const trie_maptype &o) : trie_value(o.trie_value) { }
1685             #ifdef HAVE_CPP0XRVALUEREFS
1686             template trie_maptype(trie_maptype &&o) : trie_value(std::move(o.trie_value)) { }
1687             #endif
1688             //! Silent const lvalue converter for type
1689             operator const type &() const { return trie_value; }
1690             };
1691             namespace fake {
1692             template struct trie_maptype2
1693             {
1694             template friend struct trie_keyfunct;
1695             template class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1696             template class nobblepolicy, class stlcontainer> friend class trie_map;
1697             template class nobblepolicy, class stlcontainer> friend class trie_multimap;
1698             template friend struct trie_maptype_keyfunct;
1699             typedef keytype trie_key_type;
1700             typedef type trie_value_type;
1701             typedef trie_maptype_keyfunct 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 trie_link;
1707             };
1708             }
1709             template struct trie_maptype, iteratortype>
1710             {
1711             private: // ENSURE the fake type above mirrors this one
1712             template friend struct trie_keyfunct;
1713             template class nobblepolicy, class stlcontainer, class iteratortype_, int dir, class mapvaluetype, class constiteratortype> friend class trie_iterator;
1714             template class nobblepolicy, class stlcontainer> friend class trie_map;
1715             template class nobblepolicy, class stlcontainer> friend class trie_multimap;
1716             template friend struct trie_maptype_keyfunct;
1717             typedef keytype trie_key_type;
1718             typedef type trie_value_type;
1719             typedef trie_maptype_keyfunct trie_keyfunct_type;
1720             typedef iteratortype trie_iterator_type;
1721             typedef fake::trie_maptype2 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 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 trie_maptype(const trie_maptype, iteratortype_> &o) : trie_value(o.trie_value), trie_keyvalue(o.trie_keyvalue) { }
1733             #ifdef HAVE_CPP0XRVALUEREFS
1734             template trie_maptype(trie_maptype, iteratortype_> &&o) : trie_value(std::move(o.trie_value)), trie_keyvalue(std::move(o.trie_keyvalue)) { }
1735             #endif
1736             //! Silent const lvalue converter for type
1737             operator const type &() const { return trie_value; }
1738             };
1739              
1740             /*! \class trie_iterator
1741             \ingroup C++
1742             \brief Iterator for the trie_map and trie_multimap containers
1743             */
1744             template class nobblepolicy, class stlcontainer, class iteratortype, int dir, class mapvaluetype, class constiteratortype> class trie_iterator : protected iteratortype
1745             {
1746             trie_map *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(*this)); }
1755              
1756             trie_iterator() : parent(0) { }
1757             trie_iterator(const trie_map *parent_, const iteratortype &o) : iteratortype(o), parent(const_cast *>(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, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct >(&parent->triehead, (mapvaluetype *)(&**this)) :
1776             trieprev, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct >(&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, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct >(&parent->triehead, (mapvaluetype *)(&**this)) :
1788             trieprev, mapvaluetype, mapvaluetype::trie_link_offset, intern::to_Ckeyfunct >(&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(*this)==static_cast(o); }
1797             bool operator!=(const trie_iterator &o) const { return static_cast(*this)!=static_cast(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 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 struct findkeyfunct_t : public std::unary_function
1808             {
1809             size_t operator()(const mapvaluetype &v) const
1810             {
1811             keystore_t *r=(keystore_t *)(void *)(&v);
1812             // NOTE: This line triggers a "conditional jump or move depends on unintialized value(s)" in valgrind if
1813             // sizeof(type)
1814             if(r->magic==*(size_t *)"TRIEFINDKEYSTORE")
1815             return r->key;
1816             return keyfunct()(v);
1817             }
1818             };
1819             }
1820              
1821             /*! \class trie_map
1822             \ingroup C++
1823             \brief A STL container wrapper using nedtries to map keys to values.
1824            
1825             \note Enable this by defining `NEDTRIE_ENABLE_STL_CONTAINERS`.
1826              
1827             This class can be used to wrap any arbitrary STL container with nedtrie associativity. For example, if you
1828             had a std::vector<> list of items, you could add nedtrie's fast nearly constant time algorithm for accessing them -
1829             though one would expect that a std::list<> would be the most common combination. There is no strict reason why
1830             one could not wrap std::unordered_map<>, though what one would gain is hard to imagine!
1831              
1832             Usage in the simplest sense is like this as the default template parameters use std::list<> as the underlying
1833             container:
1834             \code
1835             trie_map fooMap;
1836             fooMap[5]=Foo();
1837             fooMap.erase(fooMap.find(5));
1838             \endcode
1839              
1840             Unlike a proper STL container implementation, this wrapper is very much a hack in the sense that it's a very quick
1841             and dirty way of implementing lots of nedtrie based STL containers at once. In this sense it does require its user
1842             to not be stupid, and to know what they're doing. STL containers go out of their way to enforce correctness - well,
1843             this wrapper most certainly does not. If you want to blow off your own foot, this implementation won't stop you!
1844              
1845             For example, despite the protected STL container inheritance, all common STL functions are made public so you
1846             can if you want easily corrupt the internal state. Equally, if you know what you are doing you can pass in the
1847             wrapper as a const version of its underlying STL container by reintrpret_cast<>-ing it. Despite this, the wrapper
1848             is fairly typesafe in that its design won't introduce subtle bugs or cause existing code to magically break itself.
1849              
1850             If you would like a more proper bitwise trie STL container class implemented, or would like to be advised on any
1851             algorithmic problems from which your IT project may be suffering, my consulting company
1852             href="http://www.nedproductions.biz/">ned Productions Consulting Ltd would be happy to advise. In particular
1853             I would love to see a full bitwise trie implementation submitted to the Boost C++ libraries but I don't have the
1854             unpaid time to devote to such an endeavour sadly.
1855              
1856             \warning If you use std::vector<> as the STL container, make SURE you resize() it to its maximum size before use.
1857             Otherwise the iterators trie_map uses to link nedtrie items into the STL items will become invalidated on storage
1858             expansion.
1859             */
1860             template class nobblepolicy, class stlcontainer> class trie_map : protected stlcontainer, protected nobblepolicy >
1861             {
1862             typedef nobblepolicy > nobblepolicytype;
1863             typedef typename stlcontainer::value_type mapvaluetype;
1864             static const size_t trie_fieldoffset=mapvaluetype::trie_link_offset;
1865             template 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 const_iterator;
1869             typedef typename stlcontainer::const_pointer const_pointer;
1870             typedef typename stlcontainer::const_reference const_reference;
1871             typedef trie_iterator const_reverse_iterator;
1872             typedef typename stlcontainer::difference_type difference_type;
1873             typedef trie_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 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 triehead;
1883             static typename mapvaluetype::trie_iterator_type &from_iterator(iterator &it)
1884             {
1885             void *_it=(void *) ⁢
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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&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(*(size_t *)"TRIEFINDKEYSTORE", key);
1902             return triefind, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct > >(&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(*(size_t *)"TRIEFINDKEYSTORE", key);
1908             return trieNfind, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct > >(&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(*(size_t *)"TRIEFINDKEYSTORE", key);
1914             return trieCfind, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct > >(&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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*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;
1954             //! Returns the number of items with the key \em key
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 equal_range(const key_type &key);
1970             //std::pair equal_range(const key_type &key) const;
1971             //! Removes the item specified by \em it from the container
1972             iterator erase(iterator it)
1973             {
1974             //int (*nobblefunct)(trietype *head)
1975             trieremove, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct,
1976             // Need to give MSVC a little bit of help
1977             #ifdef _MSC_VER
1978             nobblepolicytype::trie_nobblefunction >
1979             #else
1980             nobblepolicytype::trie_nobblefunction
1981             #endif
1982             >(&triehead, &(*it));
1983             return iterator(this, stlcontainer::erase((typename stlcontainer::iterator &) it));
1984             }
1985             //! Removes the items between \em first and \em last from the container
1986             iterator erase(iterator first, iterator last)
1987             {
1988             iterator ret(last); ++ret;
1989             for(iterator it=first; it!=last; ++it)
1990             {
1991             trieremove, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct,
1992             #ifdef _MSC_VER
1993             nobblepolicytype::trie_nobblefunction >
1994             #else
1995             nobblepolicytype::trie_nobblefunction
1996             #endif
1997             >(&triehead, &(*it));
1998             stlcontainer::erase((typename stlcontainer::iterator &) it);
1999             }
2000             return ret;
2001             }
2002             //! Finds the item with key \em key
2003             iterator find(const key_type &key) { const_iterator it=static_cast(this)->find(key); void *_it=(void *) ⁢ return *(iterator *)_it; }
2004             //! Finds the item with key \em key
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             }
2010             //! Finds the nearest item with key \em key
2011             iterator nfind(const key_type &key) { const_iterator it=static_cast(this)->nfind(key); void *_it=(void *) ⁢ return *(iterator *)_it; }
2012             //! Finds the nearest item with key \em key
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             }
2018             //! Finds the closest item with key \em key trying up to \em rounds times
2019             iterator cfind(const key_type &key, int rounds=INT_MAX) { const_iterator it=static_cast(this)->cfind(key, rounds); void *_it=(void *) ⁢ return *(iterator *)_it; }
2020             //! Finds the closest item with key \em key trying up to \em rounds times
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;
2027             //! Inserts the item \em val
2028             std::pair insert(const value_type &val)
2029             {
2030             mapvaluetype *r=const_cast(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             }
2038             //! Inserts the item \em val at position \em at
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 >(&triehead, &(*it));
2044             return it;
2045             }
2046             //! Inserts the items between \em first and \em last
2047             template 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 >(&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;
2070             //! Returns an lvalue reference to the item with key \em key
2071             mapped_type &operator[](const keytype &key)
2072             {
2073             mapvaluetype *r=const_cast(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 nobblepolicy_, class stlcontainer_> friend bool operator!=(const trie_map &a, const trie_map &b);
2085             template class nobblepolicy_, class stlcontainer_> friend bool operator<(const trie_map &a, const trie_map &b);
2086             template class nobblepolicy_, class stlcontainer_> friend bool operator<=(const trie_map &a, const trie_map &b);
2087             template class nobblepolicy_, class stlcontainer_> friend bool operator==(const trie_map &a, const trie_map &b);
2088             template class nobblepolicy_, class stlcontainer_> friend bool operator>(const trie_map &a, const trie_map &b);
2089             template class nobblepolicy_, class stlcontainer_> friend bool operator>=(const trie_map &a, const trie_map &b);
2090              
2091             //! Constructs a trie_map. Has all the typical STL overloads
2092             trie_map() : stlcontainer() { NEDTRIE_INIT(&triehead); }
2093             explicit trie_map(const allocator &a) : stlcontainer(a) { NEDTRIE_INIT(&triehead); }
2094             template trie_map(const trie_map &o) : stlcontainer(o) { triehead_reindex(); }
2095             template trie_map &operator=(const trie_map &o) { *static_cast(this)=static_cast(o); triehead_reindex(); return *this; }
2096             #ifdef HAVE_CPP0XRVALUEREFS
2097             template trie_map(trie_map &&o) : stlcontainer(std::move(o))
2098             {
2099             memcpy(&triehead, &o.triehead, sizeof(triehead));
2100             }
2101             template trie_map &operator=(trie_map &&o)
2102             {
2103             *static_cast(this)=std::move(static_cast(o));
2104             memcpy(&triehead, &o.triehead, sizeof(triehead));
2105             return *this;
2106             }
2107             #endif
2108             template trie_map(inputiterator s, inputiterator e) : stlcontainer(s, e) { triehead_reindex(); }
2109             template trie_map(inputiterator s, inputiterator e, const allocator &a) : stlcontainer(s, e, a) { triehead_reindex(); }
2110             };
2111             template class nobblepolicy, class stlcontainer> bool operator!=(const trie_map &a, const trie_map &b)
2112             {
2113             return static_cast(a)!=static_cast(b);
2114             }
2115             template class nobblepolicy, class stlcontainer> bool operator<(const trie_map &a, const trie_map &b)
2116             {
2117             return static_cast(a)(b);
2118             }
2119             template class nobblepolicy, class stlcontainer> bool operator<=(const trie_map &a, const trie_map &b)
2120             {
2121             return static_cast(a)<=static_cast(b);
2122             }
2123             template class nobblepolicy, class stlcontainer> bool operator==(const trie_map &a, const trie_map &b)
2124             {
2125             return static_cast(a)==static_cast(b);
2126             }
2127             template class nobblepolicy, class stlcontainer> bool operator>(const trie_map &a, const trie_map &b)
2128             {
2129             return static_cast(a)>static_cast(b);
2130             }
2131             template class nobblepolicy, class stlcontainer> bool operator>=(const trie_map &a, const trie_map &b)
2132             {
2133             return static_cast(a)>=static_cast(b);
2134             }
2135              
2136             /*! \class trie_multimap
2137             \ingroup C++
2138             \brief A STL container wrapper using nedtries to map keys to values.
2139              
2140             \note Enable this by defining `NEDTRIE_ENABLE_STL_CONTAINERS`.
2141              
2142             This class can be used to wrap any arbitrary STL container with nedtrie associativity. For example, if you
2143             had a std::vector<> list of items, you could add nedtrie's fast nearly constant time algorithm for accessing them -
2144             though one would expect that a std::list<> would be the most common combination. There is no strict reason why
2145             one could not wrap std::unordered_map<>, though what one would gain is hard to imagine!
2146              
2147             Usage in the simplest sense is like this as the default template parameters use std::list<> as the underlying
2148             container:
2149             \code
2150             trie_multimap fooMap;
2151             fooMap[5]=Foo();
2152             fooMap.erase(fooMap.find(5));
2153             \endcode
2154              
2155             Unlike a proper STL container implementation, this wrapper is very much a hack in the sense that it's a very quick
2156             and dirty way of implementing lots of nedtrie based STL containers at once. In this sense it does require its user
2157             to not be stupid, and to know what they're doing. STL containers go out of their way to enforce correctness - well,
2158             this wrapper most certainly does not. If you want to blow off your own foot, this implementation won't stop you!
2159              
2160             For example, despite the protected STL container inheritance, all common STL functions are made public so you
2161             can if you want easily corrupt the internal state. Equally, if you know what you are doing you can pass in the
2162             wrapper as a const version of its underlying STL container by reintrpret_cast<>-ing it. Despite this, the wrapper
2163             is fairly typesafe in that its design won't introduce subtle bugs or cause existing code to magically break itself.
2164              
2165             If you would like a more proper bitwise trie STL container class implemented, or would like to be advised on any
2166             algorithmic problems from which your IT project may be suffering, my consulting company
2167             href="http://www.nedproductions.biz/">ned Productions Consulting Ltd would be happy to advise. In particular
2168             I would love to see a full bitwise trie implementation submitted to the Boost C++ libraries but I don't have the
2169             unpaid time to devote to such an endeavour sadly.
2170              
2171             \warning If you use std::vector<> as the STL container, make SURE you resize() it to its maximum size before use.
2172             Otherwise the iterators trie_multimap uses to link nedtrie items into the STL items will become invalidated on storage
2173             expansion.
2174             */
2175             template class nobblepolicy, class stlcontainer> class trie_multimap : protected stlcontainer, protected nobblepolicy >
2176             {
2177             typedef nobblepolicy > nobblepolicytype;
2178             typedef typename stlcontainer::value_type mapvaluetype;
2179             static const size_t trie_fieldoffset=mapvaluetype::trie_link_offset;
2180             template 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 const_iterator;
2184             typedef typename stlcontainer::const_pointer const_pointer;
2185             typedef typename stlcontainer::const_reference const_reference;
2186             typedef trie_iterator const_reverse_iterator;
2187             typedef typename stlcontainer::difference_type difference_type;
2188             typedef trie_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 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 triehead;
2198             static typename mapvaluetype::trie_iterator_type &from_iterator(iterator &it)
2199             {
2200             void *_it=(void *) ⁢
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, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&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(*(size_t *)"TRIEFINDKEYSTORE", key);
2217             return triefind, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct > >(&triehead, (mapvaluetype *) buffer);
2218             }
2219             iterator triehead_insert(const value_type &val)
2220             {
2221             iterator it=iterator((trie_map *) this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
2222             it->trie_iterator=from_iterator(it);
2223             trieinsert, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*it)));
2224             return it;
2225             }
2226             #ifdef HAVE_CPP0XRVALUEREFS
2227             iterator triehead_insert(value_type &&val)
2228             {
2229             iterator it=iterator((trie_map *) this, stlcontainer::insert(stlcontainer::end(), std::move(val)));
2230             it->trie_iterator=from_iterator(it);
2231             trieinsert, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct >(&triehead, const_cast(&(*it)));
2232             return it;
2233             }
2234             #endif
2235             public:
2236             iterator begin() { return iterator((trie_map *) this, stlcontainer::begin()); }
2237             const_iterator begin() const { return const_iterator((trie_map *) this, stlcontainer::begin()); }
2238             using stlcontainer::clear;
2239             //! Returns the number of items with the key \em key
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 *) this, stlcontainer::end()); }
2253             const_iterator end() const { return const_iterator((trie_map *) this, stlcontainer::end()); }
2254             //std::pair equal_range(const key_type &key);
2255             //std::pair equal_range(const key_type &key) const;
2256             //! Removes the item specified by \em it from the container
2257             iterator erase(iterator it)
2258             {
2259             //int (*nobblefunct)(trietype *head)
2260             trieremove, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct,
2261             // Need to give MSVC a little bit of help
2262             #ifdef _MSC_VER
2263             nobblepolicytype::trie_nobblefunction >
2264             #else
2265             nobblepolicytype::trie_nobblefunction
2266             #endif
2267             >(&triehead, &(*it));
2268             return iterator((trie_map *) this, stlcontainer::erase((typename stlcontainer::iterator &) it));
2269             }
2270             //! Removes the items between \em first and \em last from the container
2271             iterator erase(iterator first, iterator last)
2272             {
2273             iterator ret(last); ++ret;
2274             for(iterator it=first; it!=last; ++it)
2275             {
2276             trieremove, mapvaluetype, trie_fieldoffset, intern::to_Ckeyfunct,
2277             #ifdef _MSC_VER
2278             nobblepolicytype::trie_nobblefunction >
2279             #else
2280             nobblepolicytype::trie_nobblefunction
2281             #endif
2282             >(&triehead, &(*it));
2283             stlcontainer::erase((typename stlcontainer::iterator &) it);
2284             }
2285             return ret;
2286             }
2287             //! Finds the item with key \em key
2288             iterator find(const key_type &key) { const_iterator it=static_cast(this)->find(key); void *_it=(void *) ⁢ return *(iterator *)_it; }
2289             //! Finds the item with key \em key
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 *) this, (const typename stlcontainer::const_iterator &) r->trie_iterator);
2294             }
2295             //! Finds the nearest item with key \em key
2296             iterator nfind(const key_type &key) { const_iterator it=static_cast(this)->nfind(key); void *_it=(void *) ⁢ return *(iterator *)_it; }
2297             //! Finds the nearest item with key \em key
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             }
2303             //! Finds the closest item with key \em key trying up to \em rounds times
2304             iterator cfind(const key_type &key, int rounds=INT_MAX) { const_iterator it=static_cast(this)->cfind(key, rounds); void *_it=(void *) ⁢ return *(iterator *)_it; }
2305             //! Finds the closest item with key \em key trying up to \em rounds times
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;
2312             //! Inserts the item \em val
2313             iterator insert(const value_type &val)
2314             {
2315             return triehead_insert(std::move(val));
2316             }
2317             //! Inserts the item \em val at position \em at
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 >(&triehead, &(*it));
2323             return it;
2324             }
2325             //! Inserts the items between \em first and \em last
2326             template 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 >(&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 *) this, stlcontainer::begin()); }
2341             const_reverse_iterator rbegin() const { return const_reverse_iterator((trie_map *) this, stlcontainer::begin()); }
2342             reverse_iterator rend() { return reverse_iterator((trie_map *) this, stlcontainer::end()); }
2343             const_reverse_iterator rend() const { return const_reverse_iterator((trie_map *) 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 nobblepolicy_, class stlcontainer_> friend bool operator!=(const trie_multimap &a, const trie_multimap &b);
2351             template class nobblepolicy_, class stlcontainer_> friend bool operator<(const trie_multimap &a, const trie_multimap &b);
2352             template class nobblepolicy_, class stlcontainer_> friend bool operator<=(const trie_multimap &a, const trie_multimap &b);
2353             template class nobblepolicy_, class stlcontainer_> friend bool operator==(const trie_multimap &a, const trie_multimap &b);
2354             template class nobblepolicy_, class stlcontainer_> friend bool operator>(const trie_multimap &a, const trie_multimap &b);
2355             template class nobblepolicy_, class stlcontainer_> friend bool operator>=(const trie_multimap &a, const trie_multimap &b);
2356              
2357             //! Constructs a trie_multimap. Has all the typical STL overloads
2358             trie_multimap() : stlcontainer() { NEDTRIE_INIT(&triehead); }
2359             explicit trie_multimap(const allocator &a) : stlcontainer(a) { NEDTRIE_INIT(&triehead); }
2360             template trie_multimap(const trie_multimap &o) : stlcontainer(o) { triehead_reindex(); }
2361             template trie_multimap &operator=(const trie_multimap &o) { *static_cast(this)=static_cast(o); triehead_reindex(); return *this; }
2362             #ifdef HAVE_CPP0XRVALUEREFS
2363             template trie_multimap(trie_multimap &&o) : stlcontainer(std::move(o))
2364             {
2365             memcpy(&triehead, &o.triehead, sizeof(triehead));
2366             }
2367             template trie_multimap &operator=(trie_multimap &&o)
2368             {
2369             *static_cast(this)=std::move(static_cast(o));
2370             memcpy(&triehead, &o.triehead, sizeof(triehead));
2371             return *this;
2372             }
2373             #endif
2374             template trie_multimap(inputiterator s, inputiterator e) : stlcontainer(s, e) { triehead_reindex(); }
2375             template trie_multimap(inputiterator s, inputiterator e, const allocator &a) : stlcontainer(s, e, a) { triehead_reindex(); }
2376             };
2377             template class nobblepolicy, class stlcontainer> bool operator!=(const trie_multimap &a, const trie_multimap &b)
2378             {
2379             return static_cast(a)!=static_cast(b);
2380             }
2381             template class nobblepolicy, class stlcontainer> bool operator<(const trie_multimap &a, const trie_multimap &b)
2382             {
2383             return static_cast(a)(b);
2384             }
2385             template class nobblepolicy, class stlcontainer> bool operator<=(const trie_multimap &a, const trie_multimap &b)
2386             {
2387             return static_cast(a)<=static_cast(b);
2388             }
2389             template class nobblepolicy, class stlcontainer> bool operator==(const trie_multimap &a, const trie_multimap &b)
2390             {
2391             return static_cast(a)==static_cast(b);
2392             }
2393             template class nobblepolicy, class stlcontainer> bool operator>(const trie_multimap &a, const trie_multimap &b)
2394             {
2395             return static_cast(a)>static_cast(b);
2396             }
2397             template class nobblepolicy, class stlcontainer> bool operator>=(const trie_multimap &a, const trie_multimap &b)
2398             {
2399             return static_cast(a)>=static_cast(b);
2400             }
2401              
2402             #endif
2403              
2404             } /* namespace */
2405              
2406             #ifdef _MSC_VER
2407             #pragma warning(pop)
2408             #endif
2409             #endif