| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- #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)
- {
- size_t n = strlen(string);
- if (n > JS_STRLIMIT)
- js_rangeerror(J, "invalid string length");
- 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;
- }
|