2 stringbucket.c - MaLa stringbucket handling
4 Copyright (C) 2004, 2005, 2006, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
25 #include "stringbucket.h"
29 /* fast simple low quality prng, low bits are random, 2^31-1 cycle */
30 static inline uint32_t mala_fast_prng ()
32 static uint32_t rnd
=0xbabeface;
33 return rnd
= rnd
<<1 ^ ((rnd
>> 30) & 1) ^ ((rnd
>>2) & 1);
37 mala_stringbucket_acogc_mark (void * p
)
41 MalaStringBucket bucket
= p
;
42 acogc_object_lastmark (bucket
->tree
);
43 //acogc_object_mark (bucket->tree);
48 mala_stringbucket_acogc_initize (void * p
)
52 MalaStringBucket self
= p
;
57 mala_stringbucketnode_acogc_mark (void * p
)
61 MalaStringBucketNode node
= p
;
62 acogc_object_mark (node
->left
);
63 acogc_object_lastmark (node
->right
);
64 //acogc_object_mark (node->right);
66 // TODO simpleremove if weakref is empty
72 mala_stringbucketnode_acogc_initize (void * p
)
76 MalaStringBucketNode node
= p
;
79 acogc_weakref_init (&node
->weak_string
);
83 mala_stringbucketnode_acogc_finalize (void * p
)
87 MalaStringBucketNode node
= p
;
88 acogc_weakref_unlink (&node
->weak_string
);
91 #ifdef EBUG_ACOGC //TODO
93 mala_stringbucketnode_dump_ (FILE* g
, MalaStringBucketNode_ref n
, unsigned depth
)
99 fprintf(g
, "\t\"%p:%s\":sw -> \"%p:%s\":n;\n",
101 mala_string_cstr ((MalaString
)acogc_weakref_get (&(*n
)->weak_string
)),
103 mala_string_cstr ((MalaString
)acogc_weakref_get (&(*n
)->left
->weak_string
)));
104 mala_stringbucketnode_dump_ (g
, &(*n
)->left
, depth
-1);
109 fprintf(g
, "\t\"%p:%s\":se -> \"%p:%s\":n;\n",
111 mala_string_cstr ((MalaString
)acogc_weakref_get (&(*n
)->weak_string
)),
113 mala_string_cstr ((MalaString
)acogc_weakref_get (&(*n
)->right
->weak_string
)));
114 mala_stringbucketnode_dump_ (g
, &(*n
)->right
, depth
-1);
120 mala_stringbucketnode_dump (const char* name
, MalaStringBucketNode_ref n
, unsigned depth
)
124 sprintf(cmd
,"dot -Tps >/var/tmp/dbg_%d.ps; gv /var/tmp/dbg_%d.ps", cnt
, cnt
);
125 FILE * graph
= popen(cmd
, "w");
127 fprintf(graph
, "digraph \"%s\" { center=true; size=\"6,6\"; node [color=lightblue2, style=filled];", name
);
130 fprintf(graph
, "\t\"root\":s -> \"%p:%s\":n;\n",
132 mala_string_cstr ((MalaString
)acogc_weakref_get (&(*n
)->weak_string
)));
134 mala_stringbucketnode_dump_ (graph
, n
, depth
-1);
143 inline static MalaStringBucketNode
144 mala_stringbucketnode_new (const char * cstr
,
145 mala_stringbucket_mode mode
,
147 MalaStringBucketNode p
,
148 MalaStringBucket bucket
)
150 TRACE (mala_stringbucket
);
152 ACOGC_STACK_ENTER (bucket
->gcroot
);
153 ACOGC_STACK_PTR (MalaStringBucketNode
, n
);
154 ACOGC_STACK_PTR (MalaString
, s
);
156 n
.ptr
= acogc_factory_alloc (bucket
->gcfactory_splaynodes
);
160 s
.ptr
= acogc_factory_alloc (bucket
->gcfactory_strings
);
162 s
.ptr
->len
= strlen (cstr
);
163 s
.ptr
->str_alloc_type
= ACOGC_ALLOC
;
167 case MALA_STRINGBUCKET_SEARCH
:
169 acogc_alloc (&s
.ptr
->str
, s
.ptr
->len
+ 1, bucket
->gcroot
);
170 strcpy ((char*)s
.ptr
->str
, cstr
);
172 case MALA_STRINGBUCKET_REFERENCE
:
173 s
.ptr
->str_alloc_type
= ACOGC_STATIC
;
175 case MALA_STRINGBUCKET_ATTACH
:
178 case MALA_STRINGBUCKET_FIND
: // not used, just avoid a gcc warning
182 acogc_weakref_link (&n
.ptr
->weak_string
, s
.ptr
);
185 bucket
->tree
= n
.ptr
;
188 ASSERT (c
, "c is 0");
195 INFO_DBG (mala_stringbucket
, "create %p", n
.ptr
);
197 ASSERT (n
.ptr
->parent
? (n
.ptr
->parent
->left
== n
.ptr
|| n
.ptr
->parent
->right
== n
.ptr
): bucket
->tree
==n
.ptr
, "PARENT ERROR");
203 mala_stringbucketnode_simpleremove (MalaStringBucketNode_ref n
, MalaStringBucket bucket
)
205 TRACE (mala_stringbucket
);
207 //mala_stringbucketnode_dump ("remove before", &bucket->tree, 40);
208 INFO_DBG (mala_stringbucket
, "removing %p",*n
);
209 ASSERT ((*n
)->parent
? ((*n
)->parent
->left
== *n
|| (*n
)->parent
->right
== *n
): bucket
->tree
==*n
, "PARENT ERROR");
211 MalaStringBucketNode p
= (*n
)->parent
;
214 if (p
&& p
->left
== *n
)
222 else if (!(*n
)->right
)
227 MalaStringBucketNode i
;
228 if (mala_fast_prng()&1) /* 50% probability removing left or right wards */
231 TRACE_DBG (mala_stringbucket
, "left right");
233 //for (i = (*n)->left; i->right; assert(i->right->parent == i),i = i->right);
234 TODO ("reinst asserts");
235 for (i
= (*n
)->left
; i
->right
; i
= i
->right
);
237 i
->right
= (*n
)->right
;
240 i
->parent
->right
= i
->left
;
242 i
->left
->parent
= i
->parent
;
243 i
->left
= (*n
)->left
;
249 TRACE_DBG (mala_stringbucket
, "right left");
251 TODO ("reinst asserts");
252 //for (i = (*n)->right; i->left; assert(i->left->parent == i),i = i->left);
253 for (i
= (*n
)->right
; i
->left
; i
= i
->left
);
255 i
->left
= (*n
)->left
;
258 i
->parent
->left
= i
->right
;
260 i
->right
->parent
= i
->parent
;
261 i
->right
= (*n
)->right
;
281 (*n
)->left
->parent
= *n
;
283 (*n
)->right
->parent
= *n
;
289 mala_stringbucket_node_find (MalaStringBucket bucket
,
291 mala_stringbucket_mode mode
)
293 TRACE (mala_stringbucket
);
295 MalaStringBucketNode p
= NULL
;
296 MalaStringBucketNode n
= bucket
->tree
;
302 if (mode
== MALA_STRINGBUCKET_FIND
)
305 n
= mala_stringbucketnode_new (cstr
, mode
, c
, p
, bucket
);
306 mala_stringbucketnode_splay (n
, bucket
);
307 ASSERT (n
->parent
? (n
->parent
->left
== n
|| n
->parent
->right
== n
): bucket
->tree
==n
, "PARENT ERROR");
311 MalaString s
= acogc_weakref_get (&n
->weak_string
);
314 // really freed nodes are removed from the tree
315 mala_stringbucketnode_simpleremove (&n
, bucket
);
319 c
= strcmp (cstr
, mala_string_cstr (s
));
332 if (mode
== MALA_STRINGBUCKET_ATTACH
)
333 // string already exists, so we can free the supplied string
336 mala_stringbucketnode_splay (n
, bucket
);
337 ASSERT (n
->parent
? (n
->parent
->left
== n
|| n
->parent
->right
== n
): bucket
->tree
==n
, "PARENT ERROR");
344 mala_stringbucketnode_splay (MalaStringBucketNode n
, MalaStringBucket bucket
)
346 TRACE (mala_stringbucket
);
350 MalaStringBucketNode p
= n
->parent
;
351 MalaStringBucketNode g
= p
?p
->parent
:NULL
;
353 TRACE_DBG (mala_stringbucket
, "splaying n %p, p %p, g %p",n
,p
,g
);
362 TRACE_DBG (mala_stringbucket
, "zig zig %p",n
);
363 if ((mala_fast_prng()&0xF) < mala_global_stringbucket_splay_zigzig
)
367 if (g
->left
) g
->left
->parent
= g
;
371 if (p
->left
) p
->left
->parent
= p
;
374 n
->parent
= g
->parent
;
379 TRACE_DBG (mala_stringbucket
, "zig zag %p",n
);
380 if ((mala_fast_prng()&0xF) < mala_global_stringbucket_splay_zigzag
)
384 if (p
->right
) p
->right
->parent
= p
;
388 if (g
->left
) g
->left
->parent
= g
;
391 n
->parent
= g
->parent
;
400 TRACE_DBG (mala_stringbucket
, "zag zig %p", n
);
401 if ((mala_fast_prng()&0xF) < mala_global_stringbucket_splay_zigzag
)
405 if (p
->left
) p
->left
->parent
= p
;
409 if (g
->right
) g
->right
->parent
= g
;
412 n
->parent
= g
->parent
;
417 TRACE_DBG (mala_stringbucket
, "zag zag %p", n
);
418 if ((mala_fast_prng()&0xF) < mala_global_stringbucket_splay_zigzig
)
422 if (g
->right
) g
->right
->parent
= g
;
426 if (p
->right
) p
->right
->parent
= p
;
429 n
->parent
= g
->parent
;
437 if (n
->parent
->left
== g
)
440 n
->parent
->right
= n
;
452 if ((mala_fast_prng()&0xF) < mala_global_stringbucket_splay_zig
)
458 TRACE_DBG (mala_stringbucket
, "zig %p", n
);
460 if (p
->left
) p
->left
->parent
= p
;
466 TRACE_DBG (mala_stringbucket
, "zag %p", n
);
468 if (p
->right
) p
->right
->parent
= p
;
475 return; // simple zig and zag are end-cases
482 mala_stringbucket_new (mala_string_cmp_fn cmpfn
,
483 AcogcFactory bucketfactory
,
484 AcogcFactory gcfactory_strings
,
485 AcogcFactory gcfactory_splaynodes
)
487 TRACE (mala_stringbucket
);
489 ACOGC_STACK_ENTER (bucketfactory
->root
);
490 ACOGC_STACK_PTR (MalaStringBucket
, self
);
492 self
.ptr
= acogc_factory_alloc (bucketfactory
);
493 mala_stringbucket_init (self
.ptr
, cmpfn
, bucketfactory
->root
, gcfactory_strings
, gcfactory_splaynodes
);
501 mala_stringbucket_init (MalaStringBucket bucket
,
502 mala_string_cmp_fn cmpfn
,
504 AcogcFactory gcfactory_strings
,
505 AcogcFactory gcfactory_splaynodes
)
507 TRACE (mala_stringbucket
);
510 bucket
->cmpfn
= cmpfn
;
511 bucket
->gcroot
= gcroot
;
512 bucket
->gcfactory_strings
= gcfactory_strings
,
513 bucket
->gcfactory_splaynodes
= gcfactory_splaynodes
;
520 // c-file-style: "gnu"
522 // arch-tag: 84fbd8ab-4e90-4d04-ab70-d9b955dde41c