-
Notifications
You must be signed in to change notification settings - Fork 3
/
tree_ops.c
149 lines (132 loc) · 4.18 KB
/
tree_ops.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "noheap/trees.c"
/* main stuct used for a dictionary-style tree entry.
'key' is a string, 'value' is a double, which can represent
either a number or a string pointer.
It is up to the user to supply checks and use the types
safely.
*/
struct tree_entry
{
char *key;
DCLANG_FLT value;
};
struct tree_entry *
make_tree_entry(char *key, DCLANG_FLT value)
{
struct tree_entry *new_tree =
(struct tree_entry *) dclang_malloc(sizeof(struct tree_entry));
if(!new_tree) {
printf("make_tree_entry malloc fail\n");
exit(1);
}
new_tree->key = dclang_strdup(key);
new_tree->value = value;
return new_tree;
}
void *tree_roots[NUM_TREE_ROOTS] = {NULL};
int tree_roots_idx = -1;
void treemakefunc()
{
tree_roots_idx += 1;
if (tree_roots_idx > (NUM_TREE_ROOTS - 1))
{
printf("tmake -- tree root limit reached!\n");
printf("You can change the limit when compiling via the NUM_TREE_ROOTS variable\n");
return;
}
push((DCLANG_PTR) tree_roots_idx);
}
int tree_compare_func(const void *l, const void *r)
{
if (l == NULL || r == NULL) return 0;
struct tree_entry *tree_l = (struct tree_entry *)l;
struct tree_entry *tree_r = (struct tree_entry *)r;
return strcmp(tree_l->key, tree_r->key);
}
void treegetfunc()
{
if (data_stack_ptr < 2)
{
printf("t@ -- stack underflow! Need <tree_root> <keystr> on the stack.\n");
printf("You can make a root node via 'tmake', and assign it to a variable ");
printf("so it can be referred to later.\n");
return;
}
// Pop args
char *search_key = (char *)(DCLANG_PTR) dclang_pop();
DCLANG_PTR tree_idx = (DCLANG_PTR) dclang_pop();
struct tree_entry dummy_tree;
dummy_tree.key = search_key;
dummy_tree.value = 0;
struct tree_entry *retval = tfind(&dummy_tree, &tree_roots[tree_idx], tree_compare_func);
if (retval == NULL)
{
push((DCLANG_PTR) 0);
return;
}
push((DCLANG_FLT)((*(struct tree_entry **)retval)->value));
}
void treesetfunc()
{
if (data_stack_ptr < 3)
{
printf("t! -- stack underflow! Need <tree_root> <keystr> <val> on the stack.\n");
printf("You can make a root node via 'tmake', and assign it to a variable ");
printf("so it can be referred to later.\n");
return;
}
// Pop args
DCLANG_FLT value = dclang_pop();
char *search_key = (char *)(DCLANG_PTR) dclang_pop();
DCLANG_PTR tree_idx = (DCLANG_PTR) dclang_pop();
struct tree_entry *te_del = make_tree_entry(dclang_strdup(search_key), value);
tdelete(te_del, &tree_roots[tree_idx], tree_compare_func);
struct tree_entry *te = make_tree_entry(dclang_strdup(search_key), value);
struct tree_entry *retval = tsearch(te, &tree_roots[tree_idx], tree_compare_func);
push((DCLANG_FLT)((*(struct tree_entry **)retval)->value));
}
// helper used by `treewalk`
void print_node(const void *node, const VISIT order, const int depth)
{
if (order == preorder || order == leaf ) {
printf(
"key=%s, value=%s\n",
(*(struct tree_entry **)node)->key,
(char *)(DCLANG_PTR)((*(struct tree_entry **)node)->value)
);
}
}
void treewalkfunc()
{
if (data_stack_ptr < 1) {
printf("twalk -- stack underflow! Need <tree_root> on the stack.\n");
return;
}
DCLANG_PTR tree_idx = (DCLANG_PTR) dclang_pop();
twalk(tree_roots[tree_idx], print_node);
}
void treedeletefunc()
{
if (data_stack_ptr < 2) {
printf("tdel -- stack underflow! Need <tree_root> <key> on the stack.\n");
return;
}
// Pop args
char *key = (char *)(DCLANG_PTR) dclang_pop();
DCLANG_PTR tree_idx = (DCLANG_PTR) dclang_pop();
struct tree_entry *te_del = make_tree_entry(dclang_strdup(key), 0);
tdelete(te_del, &tree_roots[tree_idx], tree_compare_func);
dclang_free(te_del);
}
#ifdef HAS_TREEDESTROY
void treedestroyfunc()
{
if (data_stack_ptr < 1) {
printf("tdestroy -- stack underflow! Need <tree_root> on the stack.\n");
return;
}
DCLANG_PTR tree_idx = (DCLANG_PTR) dclang_pop();
tdestroy(tree_roots[tree_idx], dclang_free);
tree_roots[tree_idx] = NULL;
}
#endif