stuff
[vg.git] / src / vg / vg_store.h
1 #ifndef VG_STORE_H
2 #define VG_STORE_H
3
4 #include "vg_stdint.h"
5 #include "vg_io.h"
6
7 /*
8 * Anderson tree implementation with extensions:
9 * parents are kept track of
10 * duplicates are allowed
11 * data is never allocated or destroyed here
12 */
13
14 typedef struct aatree aatree;
15 typedef struct aatree_node aatree_node;
16 typedef struct aatree_pool_node aatree_pool_node;
17
18 typedef u32 aatree_ptr;
19 #define AATREE_PTR_NIL 0xffffffff
20
21 struct aatree
22 {
23 u32 offset, stride; /* distance between elements */
24 void *base;
25
26 int (*p_cmp)( void *a, void *b );
27 };
28
29 #pragma pack(push,1)
30 struct aatree_node
31 {
32 aatree_ptr left, right, parent;
33 u32 level, count;
34 };
35
36 struct aatree_pool_node
37 {
38 aatree_ptr next_free;
39 };
40 #pragma pack(pop)
41
42 /* api
43 * ===========================================================================*/
44
45 /* return a pointer to the start of the data referenced by t */
46 static void *aatree_get_data( aatree *tree, aatree_ptr t );
47
48 /* link node x into the tree with root t */
49 static aatree_ptr aatree_insert( aatree *tree, aatree_ptr t, aatree_ptr x );
50
51 /* delete node x from tree, does not free memory */
52 static aatree_ptr aatree_del( aatree *tree, aatree_ptr x );
53
54 /* get pointer to element in tree with index k */
55 static aatree_ptr aatree_kth( aatree *tree, aatree_ptr t, u32 k );
56
57 /* get pointer to the element above x */
58 static aatree_ptr aatree_next( aatree *tree, aatree_ptr x );
59
60 /* get pointer by value, returns NIL if not found.
61 *
62 * if duplicates values are present then the result is undefined, but it will be
63 * AN node with that value, just maybe not the first lexicographically
64 */
65 static aatree_ptr aatree_find( aatree *tree, aatree_ptr t, void *value );
66
67 /* implementation
68 * ===========================================================================*/
69
70 static void *aatree_get_data( aatree *tree, aatree_ptr t )
71 {
72 return (u8 *)tree->base + tree->stride*t;
73 }
74
75 static u8 *aatree_node_base( aatree *tree, aatree_ptr t )
76 {
77 return (u8 *)tree->base + tree->stride*t + tree->offset;
78 }
79
80 static aatree_pool_node *aatree_get_pool_node( aatree *tree, aatree_ptr t )
81 {
82 return (aatree_pool_node *)aatree_node_base( tree, t );
83 }
84
85 static aatree_node *aatree_get_node( aatree *tree, aatree_ptr t )
86 {
87 return (aatree_node *)aatree_node_base( tree, t );
88 }
89
90 static void aatree_recount( aatree *tree, aatree_ptr n )
91 {
92 aatree_node *pnode = aatree_get_node( tree, n );
93 pnode->count = 1;
94
95 if( pnode->left != AATREE_PTR_NIL )
96 pnode->count += aatree_get_node( tree, pnode->left )->count;
97
98 if( pnode->right != AATREE_PTR_NIL )
99 pnode->count += aatree_get_node( tree, pnode->right )->count;
100 }
101
102 /* . .
103 * | |
104 * L <- T L -> T
105 * / \ \ -> / / \
106 * A B R A B R
107 */
108 static aatree_ptr aatree_skew( aatree *tree, u32 t )
109 {
110 if( t == AATREE_PTR_NIL ) return t;
111
112 aatree_node *ptnode = aatree_get_node( tree, t );
113 if( ptnode->left == AATREE_PTR_NIL ) return t;
114
115 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
116 if( plnode->level == ptnode->level )
117 {
118 aatree_ptr l = ptnode->left;
119 ptnode->left = plnode->right;
120 plnode->right = t;
121
122 aatree_recount( tree, t );
123 aatree_recount( tree, l );
124
125 plnode->parent = ptnode->parent;
126 ptnode->parent = l;
127 if( ptnode->left != AATREE_PTR_NIL )
128 aatree_get_node( tree, ptnode->left )->parent = t;
129
130 return l;
131 }
132
133 return t;
134 }
135
136 /* . .
137 * | |
138 * T -> R -> X -> R
139 * / / / \
140 * A B T X
141 * / \
142 * A B
143 */
144 static aatree_ptr aatree_split( aatree *tree, aatree_ptr t )
145 {
146 if( t == AATREE_PTR_NIL ) return t;
147
148 aatree_node *ptnode = aatree_get_node( tree, t );
149 if( ptnode->right == AATREE_PTR_NIL ) return t;
150
151 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
152 if( prnode->right == AATREE_PTR_NIL ) return t;
153
154 aatree_node *prrnode = aatree_get_node( tree, prnode->right );
155 if( ptnode->level == prrnode->level )
156 {
157 aatree_ptr r = ptnode->right;
158 ptnode->right = prnode->left;
159 prnode->left = t;
160 prnode->level ++;
161
162 aatree_recount( tree, t );
163 aatree_recount( tree, r );
164
165 prnode->parent = ptnode->parent;
166 ptnode->parent = r;
167 if( ptnode->right != AATREE_PTR_NIL )
168 aatree_get_node( tree, ptnode->right )->parent = t;
169
170 return r;
171 }
172
173 return t;
174 }
175
176 static aatree_ptr aatree_insert( aatree *tree, aatree_ptr t, aatree_ptr x )
177 {
178 aatree_node *pxnode = aatree_get_node( tree, x );
179
180 if( t == AATREE_PTR_NIL )
181 {
182 pxnode->left = AATREE_PTR_NIL;
183 pxnode->right = AATREE_PTR_NIL;
184 pxnode->parent = AATREE_PTR_NIL;
185 pxnode->level = 0;
186 pxnode->count = 1;
187 return x;
188 }
189
190 aatree_node *ptnode = aatree_get_node( tree, t );
191 int cmp_result = tree->p_cmp( aatree_get_data( tree, t ),
192 aatree_get_data( tree, x ) );
193
194 ptnode->count ++;
195
196 if( cmp_result <= 0 )
197 {
198 ptnode->left = aatree_insert( tree, ptnode->left, x );
199 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
200 plnode->parent = t;
201 }
202 else
203 {
204 ptnode->right = aatree_insert( tree, ptnode->right, x );
205 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
206 prnode->parent = t;
207 }
208
209 t = aatree_skew( tree, t );
210 t = aatree_split( tree, t );
211 return t;
212 }
213
214 static void aatree_link_down( aatree *tree, aatree_ptr p, aatree_ptr *pl,
215 aatree_ptr l )
216 {
217 *pl = l;
218
219 if( *pl != AATREE_PTR_NIL )
220 aatree_get_node( tree, *pl )->parent = p;
221 }
222
223 static aatree_ptr aatree_copy_links( aatree *tree, aatree_ptr root,
224 aatree_ptr src, aatree_ptr dst )
225 {
226 aatree_node *pdst = aatree_get_node( tree, dst ),
227 *psrc = aatree_get_node( tree, src );
228
229 pdst->count = psrc->count;
230 pdst->level = psrc->level;
231 pdst->parent = psrc->parent;
232
233 aatree_link_down( tree, dst, &pdst->left, psrc->left );
234 aatree_link_down( tree, dst, &pdst->right, psrc->right );
235
236 if( pdst->parent != AATREE_PTR_NIL )
237 {
238 aatree_node *parent = aatree_get_node( tree, pdst->parent );
239
240 if( parent->left == src )
241 parent->left = dst;
242 else if( parent->right == src )
243 parent->right = dst;
244 }
245 else
246 return dst;
247
248 return root;
249 }
250
251 static aatree_ptr aatree_del( aatree *tree, aatree_ptr x )
252 {
253 aatree_ptr it = x,
254 up[32];
255
256 int count = 1, dir = 0;
257
258 /* TODO: maybe be a better way to do this, without counting back up */
259 for( aatree_node *s = aatree_get_node( tree, x );
260 s->parent != AATREE_PTR_NIL;
261 count ++ )
262 s = aatree_get_node( tree, s->parent );
263
264 int top=0;
265 while(1)
266 {
267 int index = count - (++top);
268
269 up[ index ] = it;
270 aatree_node *itnode = aatree_get_node( tree, it );
271 if( itnode->parent == AATREE_PTR_NIL )
272 break;
273 else
274 it = itnode->parent;
275 }
276
277 aatree_ptr _ptrswap_src = AATREE_PTR_NIL,
278 _ptrswap_dst = AATREE_PTR_NIL;
279
280 aatree_node *pxnode = aatree_get_node( tree, x );
281 aatree_ptr root = up[ count-1 ];
282 if( pxnode->left == AATREE_PTR_NIL || pxnode->right == AATREE_PTR_NIL )
283 {
284 if( --top != 0 )
285 {
286 aatree_node *pnode = aatree_get_node( tree, up[top-1] ),
287 *parent = aatree_get_node( tree, pxnode->parent );
288
289 aatree_ptr next = pxnode->left == AATREE_PTR_NIL?
290 pxnode->right:
291 pxnode->left;
292
293 if( parent->left == x ) pnode->left = next;
294 else pnode->right = next;
295
296 if( next != AATREE_PTR_NIL )
297 {
298 aatree_node *pnext = aatree_get_node( tree, next );
299 pnext->parent = up[top-1];
300 }
301 }
302 else
303 {
304 if( pxnode->right != AATREE_PTR_NIL ) root = pxnode->right;
305 else if( pxnode->left != AATREE_PTR_NIL ) root = pxnode->left;
306 else return AATREE_PTR_NIL;
307
308 aatree_node *newroot = aatree_get_node( tree, root );
309 newroot->parent = AATREE_PTR_NIL;
310 }
311 }
312 else
313 {
314 aatree_ptr heir = pxnode->right,
315 prev = x;
316
317 aatree_node *pheir = aatree_get_node( tree, heir );
318
319 while( pheir->left != AATREE_PTR_NIL )
320 {
321 up[top++] = prev = heir;
322 heir = pheir->left;
323 pheir = aatree_get_node( tree, heir );
324 }
325
326 _ptrswap_dst = heir;
327 _ptrswap_src = x;
328
329 aatree_node *pprev = aatree_get_node( tree, prev );
330
331 if( prev == x )
332 aatree_link_down( tree, prev, &pprev->right, pheir->right );
333 else
334 aatree_link_down( tree, prev, &pprev->left, pheir->right );
335 }
336
337 /* Tail */
338 while( --top >= 0 )
339 {
340 if( top != 0 )
341 {
342 aatree_node *above = aatree_get_node( tree, up[top-1] );
343 dir = above->right == up[top];
344 }
345
346 aatree_recount( tree, up[top] );
347 aatree_node *pntop = aatree_get_node( tree, up[top] );
348
349 if( !(pntop->left == AATREE_PTR_NIL || pntop->right == AATREE_PTR_NIL) )
350 {
351 aatree_node *pnl = aatree_get_node( tree, pntop->left ),
352 *pnr = aatree_get_node( tree, pntop->right );
353
354 if( pnl->level < pntop->level-1 || pnr->level < pntop->level-1 )
355 {
356 if( pnr->level > --pntop->level )
357 pnr->level = pntop->level;
358
359 up[top] = aatree_skew( tree, up[top] );
360
361 aatree_node *ut = aatree_get_node( tree, up[top] );
362 ut->right = aatree_skew( tree, ut->right );
363
364 aatree_node *utr = aatree_get_node( tree, ut->right );
365 utr->right = aatree_skew( tree, utr->right );
366
367 up[top] = aatree_split( tree, up[top] );
368 ut = aatree_get_node( tree, up[top] );
369
370 ut->right = aatree_split( tree, ut->right );
371 }
372 }
373
374 if( top != 0 )
375 {
376 aatree_node *ut1 = aatree_get_node( tree, up[top-1] );
377
378 if( dir == 1 )
379 aatree_link_down( tree, up[top-1], &ut1->right, up[top] );
380 else
381 aatree_link_down( tree, up[top-1], &ut1->left, up[top] );
382 }
383 else
384 {
385 root = up[top];
386 aatree_get_node( tree, root )->parent = AATREE_PTR_NIL;
387 }
388 }
389
390 /* This is our extension to the original non-recursive delete, so no data
391 * has to be moved */
392 if( _ptrswap_dst != AATREE_PTR_NIL )
393 root = aatree_copy_links( tree, root, _ptrswap_src, _ptrswap_dst );
394
395 return root;
396 }
397
398 static aatree_ptr aatree_kth( aatree *tree, aatree_ptr t, u32 k )
399 {
400 u32 i = 0;
401
402 while( t != AATREE_PTR_NIL )
403 {
404 aatree_node *ptnode = aatree_get_node( tree, t );
405
406 u32 j = i;
407 if( ptnode->left != AATREE_PTR_NIL )
408 j += aatree_get_node( tree, ptnode->left )->count;
409
410 if( j < k )
411 {
412 i = j+1;
413 t = ptnode->right;
414 }
415 else
416 {
417 if( j > k )
418 {
419 t = ptnode->left;
420 }
421 else
422 {
423 return t;
424 }
425 }
426 }
427
428 return AATREE_PTR_NIL;
429 }
430
431 static aatree_ptr aatree_next( aatree *tree, aatree_ptr x )
432 {
433 /* if can go left, go left then all the way right,
434 * else go up, if it was right link accept
435 */
436
437 aatree_node *pnode = aatree_get_node( tree, x );
438 if( pnode->right != AATREE_PTR_NIL )
439 {
440 aatree_ptr next = pnode->right;
441
442 while(1)
443 {
444 aatree_node *pnext = aatree_get_node( tree, next );
445
446 if( pnext->left != AATREE_PTR_NIL )
447 next = pnext->left;
448 else
449 return next;
450 }
451 }
452 else
453 {
454 aatree_ptr next = x;
455
456 while(1)
457 {
458 aatree_node *pnode = aatree_get_node( tree, next );
459
460 if( pnode->parent == AATREE_PTR_NIL )
461 return AATREE_PTR_NIL;
462
463 aatree_node *pabove = aatree_get_node( tree, pnode->parent );
464 if( pabove->left == next )
465 return pnode->parent;
466 else
467 next = pnode->parent;
468 }
469 }
470 }
471
472 static aatree_ptr aatree_find( aatree *tree, aatree_ptr t, void *value )
473 {
474 while( t != AATREE_PTR_NIL )
475 {
476 int cmp_result = tree->p_cmp( aatree_get_data( tree, t ), value );
477
478 if( cmp_result == 0 )
479 return t;
480 else
481 {
482 aatree_node *ptnode = aatree_get_node( tree, t );
483
484 if( cmp_result < 0 )
485 t = ptnode->left;
486 else
487 t = ptnode->right;
488 }
489 }
490 return t;
491 }
492
493 /*
494 * Debugging stuff, everything below is scaffholding and will be removed
495 * =============================================================================
496 */
497
498 static int aatree_verify_split( aatree *tree, aatree_ptr t )
499 {
500 if( t == AATREE_PTR_NIL ) return 1;
501
502 aatree_node *ptnode = aatree_get_node( tree, t );
503 if( ptnode->right == AATREE_PTR_NIL ) return 1;
504
505 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
506 if( prnode->right == AATREE_PTR_NIL ) return 1;
507
508 aatree_node *prrnode = aatree_get_node( tree, prnode->right );
509 if( ptnode->level == prrnode->level )
510 return 0;
511
512 return 1;
513 }
514
515 static int aatree_verify_skew( aatree *tree, aatree_ptr t )
516 {
517 if( t == AATREE_PTR_NIL ) return 1;
518
519 aatree_node *ptnode = aatree_get_node( tree, t );
520 if( ptnode->left == AATREE_PTR_NIL ) return 1;
521
522 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
523 if( plnode->level == ptnode->level )
524 return 0;
525
526 return 1;
527 }
528
529 static int aatree_verify( aatree *tree, aatree_ptr t )
530 {
531 aatree_node *ptnode = aatree_get_node( tree, t );
532 if( ptnode->parent != AATREE_PTR_NIL )
533 {
534 aatree_node *parent = aatree_get_node( tree, ptnode->parent );
535 if( !(parent->left == t || parent->right == t) )
536 return 0;
537 }
538
539 if( ptnode->left != AATREE_PTR_NIL )
540 if( aatree_get_node( tree, ptnode->left )->parent != t )
541 return 0;
542 if( ptnode->right != AATREE_PTR_NIL )
543 if( aatree_get_node( tree, ptnode->right )->parent != t )
544 return 0;
545
546 return aatree_verify_skew( tree, t ) &&
547 aatree_verify_split( tree, t );
548 }
549
550
551 static void aatree_show_r( aatree *tree, aatree_ptr t, int lvl,
552 void(*p_show)(void *data) )
553 {
554 if( t != AATREE_PTR_NIL )
555 {
556 aatree_node *ptnode = aatree_get_node( tree, t );
557 aatree_show_r( tree, ptnode->left, lvl+1, p_show );
558
559 void *data = aatree_get_data( tree, t );
560
561 for( int i=0; i<lvl; i++ )
562 {
563 vg_log( " " );
564 }
565 p_show( data );
566 vg_log( " (%d) \n", t );
567
568 aatree_show_r( tree, ptnode->right, lvl+1, p_show );
569 }
570 }
571
572 static void aatree_show( aatree *tree, aatree_ptr t, void(*p_show)(void *data))
573 {
574 if( t != AATREE_PTR_NIL )
575 {
576 aatree_node *ptnode = aatree_get_node( tree, t );
577 aatree_show( tree, ptnode->left, p_show );
578 void *data = aatree_get_data( tree, t );
579
580 for( int i=0; i<ptnode->level; i++ )
581 {
582 vg_log( " " );
583 }
584 p_show( data );
585 vg_log( " (%d) \n", t );
586
587 aatree_show( tree, ptnode->right, p_show );
588 }
589 }
590
591 static void aatree_show_counts( aatree *tree, aatree_ptr t, int lvl, int *ln,
592 int *err,
593 void(*p_show)(void *data), int show )
594 {
595 if( lvl > 20 )
596 return;
597 if( t == AATREE_PTR_NIL ) return;
598
599 aatree_node *ptnode = aatree_get_node( tree, t );
600 void *data = aatree_get_data( tree, t );
601
602 aatree_show_counts( tree, ptnode->left, lvl+1, ln, err, p_show, show );
603
604 if( show ) vg_log( "%03d| ", *ln );
605 *ln = *ln +1;
606
607 if( show )
608 for( int i=0; i<lvl; i++ )
609 printf( " " );
610
611 if( show )
612 {
613 p_show( data );
614
615 if( ptnode->left != AATREE_PTR_NIL && ptnode->right != AATREE_PTR_NIL )
616 printf( "|" );
617 if( ptnode->left != AATREE_PTR_NIL && ptnode->right == AATREE_PTR_NIL )
618 printf( "/" );
619 if( ptnode->left == AATREE_PTR_NIL && ptnode->right != AATREE_PTR_NIL )
620 printf( "\\" );
621
622 printf( " (%d, %d, parent: %d. V: %d, level: %d) \n", t,
623 ptnode->count, ptnode->parent,
624 aatree_verify( tree, t ), ptnode->level);
625 }
626
627 if( !aatree_verify( tree, t ) )
628 {
629 if( show )
630 vg_log( "error\n" );
631 *err = 1;
632 }
633
634 aatree_show_counts( tree, ptnode->right, lvl+1, ln, err, p_show, show );
635 }
636
637 /*
638 * Pool allocator utility which can be placed in a union with regular aa nodes.
639 */
640
641 static aatree_ptr aatree_init_pool( aatree *info, u32 item_count )
642 {
643 for( aatree_ptr i=0; i<item_count; i++ )
644 {
645 aatree_pool_node *pn = aatree_get_pool_node( info, i );
646
647 if( i==item_count-1 )
648 pn->next_free = AATREE_PTR_NIL;
649 else
650 pn->next_free = i+1;
651 }
652
653 return 0;
654 }
655
656 static aatree_ptr aatree_pool_alloc( aatree *info, aatree_ptr *head )
657 {
658 if( *head == AATREE_PTR_NIL )
659 {
660 vg_error( "No nodes free in pool allocator!\n" );
661 return AATREE_PTR_NIL;
662 }
663 else
664 {
665 aatree_ptr gap = *head;
666 *head = aatree_get_pool_node( info, *head )->next_free;
667 return gap;
668 }
669 }
670
671 static void aatree_pool_free( aatree *info, aatree_ptr node, aatree_ptr *head )
672 {
673 aatree_pool_node *pn = aatree_get_pool_node( info, node );
674 pn->next_free = *head;
675 *head = node;
676 }
677
678 #endif /* VG_STORE_H */