Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7641 views
1
#include "jsi.h"
2
3
/* Use an AA-tree to quickly look up interned strings. */
4
5
struct js_StringNode
6
{
7
js_StringNode *left, *right;
8
int level;
9
char string[1];
10
};
11
12
static js_StringNode jsS_sentinel = { &jsS_sentinel, &jsS_sentinel, 0, ""};
13
14
static js_StringNode *jsS_newstringnode(js_State *J, const char *string, const char **result)
15
{
16
int n = strlen(string);
17
js_StringNode *node = js_malloc(J, offsetof(js_StringNode, string) + n + 1);
18
node->left = node->right = &jsS_sentinel;
19
node->level = 1;
20
memcpy(node->string, string, n + 1);
21
return *result = node->string, node;
22
}
23
24
static js_StringNode *jsS_skew(js_StringNode *node)
25
{
26
if (node->left->level == node->level) {
27
js_StringNode *temp = node;
28
node = node->left;
29
temp->left = node->right;
30
node->right = temp;
31
}
32
return node;
33
}
34
35
static js_StringNode *jsS_split(js_StringNode *node)
36
{
37
if (node->right->right->level == node->level) {
38
js_StringNode *temp = node;
39
node = node->right;
40
temp->right = node->left;
41
node->left = temp;
42
++node->level;
43
}
44
return node;
45
}
46
47
static js_StringNode *jsS_insert(js_State *J, js_StringNode *node, const char *string, const char **result)
48
{
49
if (node != &jsS_sentinel) {
50
int c = strcmp(string, node->string);
51
if (c < 0)
52
node->left = jsS_insert(J, node->left, string, result);
53
else if (c > 0)
54
node->right = jsS_insert(J, node->right, string, result);
55
else
56
return *result = node->string, node;
57
node = jsS_skew(node);
58
node = jsS_split(node);
59
return node;
60
}
61
return jsS_newstringnode(J, string, result);
62
}
63
64
static void dumpstringnode(js_StringNode *node, int level)
65
{
66
int i;
67
if (node->left != &jsS_sentinel)
68
dumpstringnode(node->left, level + 1);
69
printf("%d: ", node->level);
70
for (i = 0; i < level; ++i)
71
putchar('\t');
72
printf("'%s'\n", node->string);
73
if (node->right != &jsS_sentinel)
74
dumpstringnode(node->right, level + 1);
75
}
76
77
void jsS_dumpstrings(js_State *J)
78
{
79
js_StringNode *root = J->strings;
80
printf("interned strings {\n");
81
if (root && root != &jsS_sentinel)
82
dumpstringnode(root, 1);
83
printf("}\n");
84
}
85
86
static void jsS_freestringnode(js_State *J, js_StringNode *node)
87
{
88
if (node->left != &jsS_sentinel) jsS_freestringnode(J, node->left);
89
if (node->right != &jsS_sentinel) jsS_freestringnode(J, node->right);
90
js_free(J, node);
91
}
92
93
void jsS_freestrings(js_State *J)
94
{
95
if (J->strings && J->strings != &jsS_sentinel)
96
jsS_freestringnode(J, J->strings);
97
}
98
99
const char *js_intern(js_State *J, const char *s)
100
{
101
const char *result;
102
if (!J->strings)
103
J->strings = &jsS_sentinel;
104
J->strings = jsS_insert(J, J->strings, s, &result);
105
return result;
106
}
107
108