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