Skip to content

Commit 102d4e1

Browse files
committed
test: add ASCII tree visualization test
* new test validates ASCII tree printing output Added test/50-validation/ascii.c which creates a simple 3-node tree and tests the mulle__rbtree_node_ascii_fprintf function. Also reformatted source code following project style guidelines (K&R bracing, variable declarations ordered alphabetically, consistent spacing).
1 parent b1d1e0c commit 102d4e1

File tree

5 files changed

+152
-88
lines changed

5 files changed

+152
-88
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,4 @@ cmake-build-*/
7373
.mulle/etc/make/build-dir
7474
vgcore.*
7575
test*/**/*.test.*
76+
.graveyard

clib.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description" : "🍫 mulle-rbtree-debug organizes data in a red/black tree",
55
"keywords" : [],
66
"license" : "BSD-3-Clause",
7-
"repo" : "mulle-c/mulle-rbtree",
7+
"repo" : "mulle-core/mulle-rbtree-debug",
88
"src" : [
99
"src/generic/include.h",
1010
"src/mulle--rbtree-debug.c",

src/mulle--rbtree-debug.c

Lines changed: 95 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -41,40 +41,43 @@
4141
// Helper function to validate black-height property from a node to leaves
4242
// Returns NULL if the black-height property is satisfied, otherwise an error message.
4343
// Sets *black_height to the computed black height if valid.
44-
static char *_mulle__rbtree_validate_black_height(struct mulle__rbtree *a_tree,
45-
struct mulle_rbnode *node,
46-
int *black_height)
44+
static char *_mulle__rbtree_validate_black_height( struct mulle__rbtree *a_tree,
45+
struct mulle_rbnode *node,
46+
int *black_height)
4747
{
48+
char *left_err;
49+
char *right_err;
50+
int left_height;
51+
int right_height;
4852
struct mulle_rbnode *nil;
49-
char *left_err, *right_err;
50-
int left_height, right_height;
5153

52-
nil = _mulle__rbtree_get_nil_node(a_tree);
54+
nil = _mulle__rbtree_get_nil_node( a_tree);
5355

5456
// NIL nodes are black and have height 1
55-
if (node == nil)
57+
if( node == nil)
5658
{
5759
*black_height = 1;
58-
return NULL;
60+
return( NULL);
5961
}
6062

6163
// Recursively validate and compute black heights of left and right subtrees
6264
left_err = _mulle__rbtree_validate_black_height( a_tree, node->_left, &left_height);
6365
if( left_err != NULL)
64-
return left_err;
66+
return( left_err);
6567

6668
right_err = _mulle__rbtree_validate_black_height( a_tree, node->_right, &right_height);
6769
if( right_err != NULL)
68-
return right_err;
70+
return( right_err);
6971

7072
// Both subtrees must have the same black height
71-
if (left_height != right_height) {
72-
return "Black heights do not match between left and right subtrees";
73+
if( left_height != right_height)
74+
{
75+
return( "Black heights do not match between left and right subtrees");
7376
}
7477

7578
// Add 1 if current node is black
76-
*black_height = left_height + (_mulle_rbnode_is_black(node) ? 1 : 0);
77-
return NULL;
79+
*black_height = left_height + (_mulle_rbnode_is_black( node) ? 1 : 0);
80+
return( NULL);
7881
}
7982

8083

@@ -83,51 +86,59 @@ static char *_mulle__rbtree_validate_black_height(struct mulle__rbtree *a_tree,
8386
static char *_mulle__rbtree_validate_node( struct mulle__rbtree *a_tree,
8487
struct mulle_rbnode *node)
8588
{
89+
char *err;
8690
struct mulle_rbnode *nil;
87-
char *err;
8891

89-
nil = _mulle__rbtree_get_nil_node(a_tree);
92+
nil = _mulle__rbtree_get_nil_node( a_tree);
9093

9194
// NIL nodes are always valid
92-
if (node == nil) {
93-
return NULL;
95+
if( node == nil)
96+
{
97+
return( NULL);
9498
}
9599

96100
// Rule 4: Red nodes can't have red children
97-
if (_mulle_rbnode_is_red(node)) {
98-
if (node->_left != nil && _mulle_rbnode_is_red(node->_left)) {
99-
return "Red-red violation: Red node has red left child";
101+
if( _mulle_rbnode_is_red( node))
102+
{
103+
if( node->_left != nil && _mulle_rbnode_is_red( node->_left))
104+
{
105+
return( "Red-red violation: Red node has red left child");
100106
}
101-
if (node->_right != nil && _mulle_rbnode_is_red(node->_right)) {
102-
return "Red-red violation: Red node has red right child";
107+
if( node->_right != nil && _mulle_rbnode_is_red( node->_right))
108+
{
109+
return( "Red-red violation: Red node has red right child");
103110
}
104111
}
105112

106113
// Validate parent-child consistency
107-
if (node->_left != nil && node->_left->_parent != node) {
108-
return "Parent-child inconsistency: Left child's parent pointer is incorrect";
114+
if( node->_left != nil && node->_left->_parent != node)
115+
{
116+
return( "Parent-child inconsistency: Left child's parent pointer is incorrect");
109117
}
110-
if (node->_right != nil && node->_right->_parent != node) {
111-
return "Parent-child inconsistency: Right child's parent pointer is incorrect";
118+
if( node->_right != nil && node->_right->_parent != node)
119+
{
120+
return( "Parent-child inconsistency: Right child's parent pointer is incorrect");
112121
}
113122

114123
if( _mulle_rbnode_is_dirty( node) && ! _mulle_rbnode_is_dirty( node->_parent))
115124
{
116125
if( _mulle__rbtree_get_root_node( a_tree) != node)
117-
return "Dirty flag inconsistency: Parent is not marked dirty but child is";
126+
return( "Dirty flag inconsistency: Parent is not marked dirty but child is");
118127
}
119128

120129
// Recursively validate left and right subtrees
121130
err = _mulle__rbtree_validate_node( a_tree, node->_left);
122-
if (err != NULL) {
123-
return err;
131+
if( err != NULL)
132+
{
133+
return( err);
124134
}
125135
err = _mulle__rbtree_validate_node( a_tree, node->_right);
126-
if (err != NULL) {
127-
return err;
136+
if( err != NULL)
137+
{
138+
return( err);
128139
}
129140

130-
return NULL;
141+
return( NULL);
131142
}
132143

133144

@@ -144,47 +155,52 @@ static char *_mulle__rbtree_validate_node( struct mulle__rbtree *a_tree,
144155
* NULL - Tree is valid
145156
* error message string - Tree violates red-black properties (describes the violation)
146157
*/
147-
char *mulle__rbtree_validate(struct mulle__rbtree *a_tree)
158+
char *mulle__rbtree_validate( struct mulle__rbtree *a_tree)
148159
{
149-
struct mulle_rbnode *root;
150-
struct mulle_rbnode *nil;
151-
char *err;
152160
int black_height; // Unused, but needed for validation call
161+
char *err;
162+
struct mulle_rbnode *nil;
163+
struct mulle_rbnode *root;
153164

154165
if( ! a_tree)
155166
return( NULL);
156167

157-
nil = _mulle__rbtree_get_nil_node(a_tree);
158-
root = _mulle__rbtree_get_root_node(a_tree);
168+
nil = _mulle__rbtree_get_nil_node( a_tree);
169+
root = _mulle__rbtree_get_root_node( a_tree);
159170

160171
// Rule 3: NIL node must be black (sanity check)
161-
if (!_mulle_rbnode_is_black(nil)) {
162-
return "NIL node is not black";
172+
if( ! _mulle_rbnode_is_black( nil))
173+
{
174+
return( "NIL node is not black");
163175
}
164176

165177
// Empty tree is valid
166-
if (root == nil) {
167-
return NULL;
178+
if( root == nil)
179+
{
180+
return( NULL);
168181
}
169182

170183
// Rule 2: Root must be black
171-
if (!_mulle_rbnode_is_black(root)) {
172-
return "Root node is not black";
184+
if( ! _mulle_rbnode_is_black( root))
185+
{
186+
return( "Root node is not black");
173187
}
174188

175189
// Validate node properties and red-red violations (Rule 4)
176-
err = _mulle__rbtree_validate_node(a_tree, root);
177-
if (err != NULL) {
178-
return err;
190+
err = _mulle__rbtree_validate_node( a_tree, root);
191+
if( err != NULL)
192+
{
193+
return( err);
179194
}
180195

181196
// Rule 5: Validate black-height consistency
182-
err = _mulle__rbtree_validate_black_height(a_tree, root, &black_height);
183-
if (err != NULL) {
184-
return err;
197+
err = _mulle__rbtree_validate_black_height( a_tree, root, &black_height);
198+
if( err != NULL)
199+
{
200+
return( err);
185201
}
186202

187-
return NULL; // Tree is valid
203+
return( NULL); // Tree is valid
188204
}
189205

190206

@@ -195,12 +211,12 @@ _mulle__rbtree_node_dot_fprintf( FILE *fp,
195211
struct mulle__rbtree *a_tree,
196212
void (*print_value_fn)( FILE *fp, void *))
197213
{
198-
struct mulle_rbnode *nil;
199-
unsigned long left_id;
200-
unsigned long right_id;
201-
char *fillstyle;
202214
char *fillcolor;
215+
char *fillstyle;
203216
char *fontcolor;
217+
unsigned long left_id;
218+
struct mulle_rbnode *nil;
219+
unsigned long right_id;
204220

205221
nil = _mulle__rbtree_get_nil_node( a_tree);
206222

@@ -236,7 +252,7 @@ _mulle__rbtree_node_dot_fprintf( FILE *fp,
236252
}
237253
}
238254

239-
mulle_fprintf(fp, "\", style=\"%s,bold\", fillcolor=%s, fontcolor=%s];\n",
255+
mulle_fprintf( fp, "\", style=\"%s,bold\", fillcolor=%s, fontcolor=%s];\n",
240256
fillstyle, fillcolor, fontcolor);
241257

242258

@@ -289,29 +305,21 @@ void mulle__rbtree_node_dot_fprintf( FILE *fp,
289305

290306

291307

292-
// Structure for tree printing
293-
struct tree_line
294-
{
295-
char *buffer;
296-
int length;
297-
};
298-
299-
300308
struct tree_node_info
301309
{
302310
struct mulle_rbnode *node;
303311
int level;
304312
int x;
305-
int width;
313+
size_t width;
306314
};
307315

308316

309317
// Calculate tree height
310318
static int _tree_height( struct mulle_rbnode *node,
311319
struct mulle__rbtree *a_tree)
312320
{
313-
struct mulle_rbnode *nil;
314321
int left_height;
322+
struct mulle_rbnode *nil;
315323
int right_height;
316324

317325
nil = _mulle__rbtree_get_nil_node( a_tree);
@@ -378,15 +386,15 @@ static char * _node_label( struct mulle__rbtree *a_tree,
378386

379387

380388
// Calculate width needed for a node's string representation
381-
static int _node_width( struct mulle__rbtree *a_tree,
382-
struct mulle_rbnode *node,
383-
char *(*print_value_fn)( void *))
389+
static size_t _node_width( struct mulle__rbtree *a_tree,
390+
struct mulle_rbnode *node,
391+
char *(*print_value_fn)( void *))
384392
{
385393
size_t len;
386394
char *s;
387395

388-
s = _node_label( a_tree, node, print_value_fn);
389-
len = strlen( s);
396+
s = _node_label( a_tree, node, print_value_fn);
397+
len = strlen( s);
390398
mulle_free( s);
391399
return( len);
392400
}
@@ -401,11 +409,11 @@ static void _build_tree_positions( struct mulle_rbnode *node,
401409
int level,
402410
int *x_offset)
403411
{
404-
struct mulle_rbnode *nil;
405412
// int left_width = 0;
406-
// int right_width = 0;
407-
int node_width;
408413
int my_index;
414+
struct mulle_rbnode *nil;
415+
size_t node_width;
416+
// int right_width = 0;
409417

410418
nil = _mulle__rbtree_get_nil_node( a_tree);
411419
if( node == nil)
@@ -437,7 +445,7 @@ static void _build_tree_positions( struct mulle_rbnode *node,
437445
if( node->_left == nil && node->_right == nil)
438446
{
439447
// Leaf node
440-
nodes[ my_index].x = *x_offset + node_width / 2;
448+
nodes[ my_index].x = *x_offset + (int) node_width / 2;
441449
}
442450
else if( node->_left != nil && node->_right != nil)
443451
{
@@ -449,23 +457,23 @@ static void _build_tree_positions( struct mulle_rbnode *node,
449457
else if( node->_left != nil)
450458
{
451459
// Only left child
452-
nodes[ my_index].x = nodes[ my_index + 1].x + node_width / 2;
460+
nodes[ my_index].x = nodes[ my_index + 1].x + (int) node_width / 2;
453461
}
454462
else
455463
{
456464
// Only right child
457-
nodes[ my_index].x = nodes[ *index - 1].x - node_width / 2;
465+
nodes[ my_index].x = nodes[ *index - 1].x - (int) node_width / 2;
458466
}
459467

460468
// Ensure minimum spacing
461-
if( *x_offset < nodes[ my_index].x - node_width / 2)
462-
*x_offset = nodes[ my_index].x - node_width / 2;
469+
if( *x_offset < nodes[ my_index].x - (int) node_width / 2)
470+
*x_offset = nodes[ my_index].x - (int) node_width / 2;
463471

464472
nodes[ my_index].node = node;
465473
nodes[ my_index].level = level;
466474
nodes[ my_index].width = node_width;
467475

468-
*x_offset += node_width + 2;
476+
*x_offset += (int) node_width + 2;
469477
}
470478

471479
// Print tree using mulle_array and mulle_buffer
@@ -505,8 +513,8 @@ static void _print_bottom_up_tree( FILE *fp,
505513
// Find maximum width
506514
for( i = 0; i < node_count; i++)
507515
{
508-
if( (size_t) (nodes[ i].x + nodes[ i].width / 2) > max_width)
509-
max_width = nodes[ i].x + nodes[ i].width / 2;
516+
if( (size_t) (nodes[ i].x + (int) nodes[ i].width / 2) > max_width)
517+
max_width = nodes[ i].x + (int) nodes[ i].width / 2;
510518
}
511519
max_width += 2;
512520

@@ -547,7 +555,7 @@ static void _print_bottom_up_tree( FILE *fp,
547555
int start_pos;
548556

549557
node_str = _node_label( a_tree, nodes[ i].node, print_value_fn);
550-
start_pos = nodes[ i].x - strlen( node_str) / 2;
558+
start_pos = nodes[ i].x - (int) strlen( node_str) / 2;
551559

552560
if( start_pos >= 0 && start_pos + strlen( node_str) <= max_width)
553561
{
@@ -603,8 +611,8 @@ static void _print_bottom_up_tree( FILE *fp,
603611
// Print the tree
604612
for( i = 0; i < height; i++)
605613
{
606-
char *line;
607-
int len;
614+
char *line;
615+
size_t len;
608616

609617
line = (char *) mulle_array_get( lines, i);
610618

@@ -642,8 +650,8 @@ void mulle__rbtree_node_ascii_fprintf( FILE *fp,
642650
struct mulle__rbtree *a_tree,
643651
char *(*print_value_fn)( void *))
644652
{
645-
struct mulle_rbnode *root;
646653
struct mulle_rbnode *nil;
654+
struct mulle_rbnode *root;
647655

648656
if( ! a_tree)
649657
{

0 commit comments

Comments
 (0)