forked from KolibriOS/kolibrios
kosjs: replace libmujs.a with sources; if argc = 0, see "usage"
git-svn-id: svn://kolibrios.org@8456 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
135
programs/develop/kosjs/libmujs/jsintern.c
Executable file
135
programs/develop/kosjs/libmujs/jsintern.c
Executable file
@@ -0,0 +1,135 @@
|
||||
#include "jsi.h"
|
||||
|
||||
/* Dynamically grown string buffer */
|
||||
|
||||
void js_putc(js_State *J, js_Buffer **sbp, int c)
|
||||
{
|
||||
js_Buffer *sb = *sbp;
|
||||
if (!sb) {
|
||||
sb = js_malloc(J, sizeof *sb);
|
||||
sb->n = 0;
|
||||
sb->m = sizeof sb->s;
|
||||
*sbp = sb;
|
||||
} else if (sb->n == sb->m) {
|
||||
sb = js_realloc(J, sb, (sb->m *= 2) + soffsetof(js_Buffer, s));
|
||||
*sbp = sb;
|
||||
}
|
||||
sb->s[sb->n++] = c;
|
||||
}
|
||||
|
||||
void js_puts(js_State *J, js_Buffer **sb, const char *s)
|
||||
{
|
||||
while (*s)
|
||||
js_putc(J, sb, *s++);
|
||||
}
|
||||
|
||||
void js_putm(js_State *J, js_Buffer **sb, const char *s, const char *e)
|
||||
{
|
||||
while (s < e)
|
||||
js_putc(J, sb, *s++);
|
||||
}
|
||||
|
||||
/* Use an AA-tree to quickly look up interned strings. */
|
||||
|
||||
struct js_StringNode
|
||||
{
|
||||
js_StringNode *left, *right;
|
||||
int level;
|
||||
char string[1];
|
||||
};
|
||||
|
||||
static js_StringNode jsS_sentinel = { &jsS_sentinel, &jsS_sentinel, 0, ""};
|
||||
|
||||
static js_StringNode *jsS_newstringnode(js_State *J, const char *string, const char **result)
|
||||
{
|
||||
int n = strlen(string);
|
||||
js_StringNode *node = js_malloc(J, soffsetof(js_StringNode, string) + n + 1);
|
||||
node->left = node->right = &jsS_sentinel;
|
||||
node->level = 1;
|
||||
memcpy(node->string, string, n + 1);
|
||||
return *result = node->string, node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_skew(js_StringNode *node)
|
||||
{
|
||||
if (node->left->level == node->level) {
|
||||
js_StringNode *temp = node;
|
||||
node = node->left;
|
||||
temp->left = node->right;
|
||||
node->right = temp;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_split(js_StringNode *node)
|
||||
{
|
||||
if (node->right->right->level == node->level) {
|
||||
js_StringNode *temp = node;
|
||||
node = node->right;
|
||||
temp->right = node->left;
|
||||
node->left = temp;
|
||||
++node->level;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_insert(js_State *J, js_StringNode *node, const char *string, const char **result)
|
||||
{
|
||||
if (node != &jsS_sentinel) {
|
||||
int c = strcmp(string, node->string);
|
||||
if (c < 0)
|
||||
node->left = jsS_insert(J, node->left, string, result);
|
||||
else if (c > 0)
|
||||
node->right = jsS_insert(J, node->right, string, result);
|
||||
else
|
||||
return *result = node->string, node;
|
||||
node = jsS_skew(node);
|
||||
node = jsS_split(node);
|
||||
return node;
|
||||
}
|
||||
return jsS_newstringnode(J, string, result);
|
||||
}
|
||||
|
||||
static void dumpstringnode(js_StringNode *node, int level)
|
||||
{
|
||||
int i;
|
||||
if (node->left != &jsS_sentinel)
|
||||
dumpstringnode(node->left, level + 1);
|
||||
printf("%d: ", node->level);
|
||||
for (i = 0; i < level; ++i)
|
||||
putchar('\t');
|
||||
printf("'%s'\n", node->string);
|
||||
if (node->right != &jsS_sentinel)
|
||||
dumpstringnode(node->right, level + 1);
|
||||
}
|
||||
|
||||
void jsS_dumpstrings(js_State *J)
|
||||
{
|
||||
js_StringNode *root = J->strings;
|
||||
printf("interned strings {\n");
|
||||
if (root && root != &jsS_sentinel)
|
||||
dumpstringnode(root, 1);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static void jsS_freestringnode(js_State *J, js_StringNode *node)
|
||||
{
|
||||
if (node->left != &jsS_sentinel) jsS_freestringnode(J, node->left);
|
||||
if (node->right != &jsS_sentinel) jsS_freestringnode(J, node->right);
|
||||
js_free(J, node);
|
||||
}
|
||||
|
||||
void jsS_freestrings(js_State *J)
|
||||
{
|
||||
if (J->strings && J->strings != &jsS_sentinel)
|
||||
jsS_freestringnode(J, J->strings);
|
||||
}
|
||||
|
||||
const char *js_intern(js_State *J, const char *s)
|
||||
{
|
||||
const char *result;
|
||||
if (!J->strings)
|
||||
J->strings = &jsS_sentinel;
|
||||
J->strings = jsS_insert(J, J->strings, s, &result);
|
||||
return result;
|
||||
}
|
Reference in New Issue
Block a user