comparison mupdf-source/thirdparty/mujs/jsintern.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 #include "jsi.h"
2
3 /* Dynamically grown string buffer */
4
5 void js_putc(js_State *J, js_Buffer **sbp, int c)
6 {
7 js_Buffer *sb = *sbp;
8 if (!sb) {
9 sb = js_malloc(J, sizeof *sb);
10 sb->n = 0;
11 sb->m = sizeof sb->s;
12 *sbp = sb;
13 } else if (sb->n == sb->m) {
14 sb = js_realloc(J, sb, (sb->m *= 2) + soffsetof(js_Buffer, s));
15 *sbp = sb;
16 }
17 sb->s[sb->n++] = c;
18 }
19
20 void js_puts(js_State *J, js_Buffer **sb, const char *s)
21 {
22 while (*s)
23 js_putc(J, sb, *s++);
24 }
25
26 void js_putm(js_State *J, js_Buffer **sb, const char *s, const char *e)
27 {
28 while (s < e)
29 js_putc(J, sb, *s++);
30 }
31
32 /* Use an AA-tree to quickly look up interned strings. */
33
34 struct js_StringNode
35 {
36 js_StringNode *left, *right;
37 int level;
38 char string[1];
39 };
40
41 static js_StringNode jsS_sentinel = { &jsS_sentinel, &jsS_sentinel, 0, ""};
42
43 static js_StringNode *jsS_newstringnode(js_State *J, const char *string, const char **result)
44 {
45 size_t n = strlen(string);
46 if (n > JS_STRLIMIT)
47 js_rangeerror(J, "invalid string length");
48 js_StringNode *node = js_malloc(J, soffsetof(js_StringNode, string) + n + 1);
49 node->left = node->right = &jsS_sentinel;
50 node->level = 1;
51 memcpy(node->string, string, n + 1);
52 return *result = node->string, node;
53 }
54
55 static js_StringNode *jsS_skew(js_StringNode *node)
56 {
57 if (node->left->level == node->level) {
58 js_StringNode *temp = node;
59 node = node->left;
60 temp->left = node->right;
61 node->right = temp;
62 }
63 return node;
64 }
65
66 static js_StringNode *jsS_split(js_StringNode *node)
67 {
68 if (node->right->right->level == node->level) {
69 js_StringNode *temp = node;
70 node = node->right;
71 temp->right = node->left;
72 node->left = temp;
73 ++node->level;
74 }
75 return node;
76 }
77
78 static js_StringNode *jsS_insert(js_State *J, js_StringNode *node, const char *string, const char **result)
79 {
80 if (node != &jsS_sentinel) {
81 int c = strcmp(string, node->string);
82 if (c < 0)
83 node->left = jsS_insert(J, node->left, string, result);
84 else if (c > 0)
85 node->right = jsS_insert(J, node->right, string, result);
86 else
87 return *result = node->string, node;
88 node = jsS_skew(node);
89 node = jsS_split(node);
90 return node;
91 }
92 return jsS_newstringnode(J, string, result);
93 }
94
95 static void dumpstringnode(js_StringNode *node, int level)
96 {
97 int i;
98 if (node->left != &jsS_sentinel)
99 dumpstringnode(node->left, level + 1);
100 printf("%d: ", node->level);
101 for (i = 0; i < level; ++i)
102 putchar('\t');
103 printf("'%s'\n", node->string);
104 if (node->right != &jsS_sentinel)
105 dumpstringnode(node->right, level + 1);
106 }
107
108 void jsS_dumpstrings(js_State *J)
109 {
110 js_StringNode *root = J->strings;
111 printf("interned strings {\n");
112 if (root && root != &jsS_sentinel)
113 dumpstringnode(root, 1);
114 printf("}\n");
115 }
116
117 static void jsS_freestringnode(js_State *J, js_StringNode *node)
118 {
119 if (node->left != &jsS_sentinel) jsS_freestringnode(J, node->left);
120 if (node->right != &jsS_sentinel) jsS_freestringnode(J, node->right);
121 js_free(J, node);
122 }
123
124 void jsS_freestrings(js_State *J)
125 {
126 if (J->strings && J->strings != &jsS_sentinel)
127 jsS_freestringnode(J, J->strings);
128 }
129
130 const char *js_intern(js_State *J, const char *s)
131 {
132 const char *result;
133 if (!J->strings)
134 J->strings = &jsS_sentinel;
135 J->strings = jsS_insert(J, J->strings, s, &result);
136 return result;
137 }