@zappdev/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +55 -0
  2. package/dist/zapp-cli.js +9471 -0
  3. package/native/src/app/app.zc +490 -0
  4. package/native/src/event/event.zc +24 -0
  5. package/native/src/event/events.zc +70 -0
  6. package/native/src/platform/darwin/backend.zc +923 -0
  7. package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
  8. package/native/src/platform/darwin/bootstrap.zc +9 -0
  9. package/native/src/platform/darwin/engine_jsc.zc +86 -0
  10. package/native/src/platform/darwin/engine_qjs.zc +92 -0
  11. package/native/src/platform/darwin/platform.zc +156 -0
  12. package/native/src/platform/darwin/webview.zc +550 -0
  13. package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
  14. package/native/src/platform/darwin/window.zc +1223 -0
  15. package/native/src/platform/darwin/worker/common.zc +223 -0
  16. package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
  17. package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
  18. package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
  19. package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
  20. package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
  21. package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
  22. package/native/src/platform/darwin/worker/dispatch.zc +55 -0
  23. package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
  24. package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
  25. package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
  26. package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
  27. package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
  28. package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
  29. package/native/src/platform/darwin/worker/jsc.zc +670 -0
  30. package/native/src/platform/darwin/worker/mod.zc +30 -0
  31. package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
  32. package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
  33. package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
  34. package/native/src/platform/darwin/worker/qjs.zc +1053 -0
  35. package/native/src/platform/darwin/worker/timers.zc +149 -0
  36. package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
  37. package/native/src/platform/platform.zc +64 -0
  38. package/native/src/platform/shared/log.zc +156 -0
  39. package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
  40. package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
  41. package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
  42. package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
  43. package/native/src/platform/shared/worker_registry.zc +206 -0
  44. package/native/src/platform/window.zc +446 -0
  45. package/native/src/platform/windows/backend.zc +452 -0
  46. package/native/src/platform/windows/backend_bootstrap.zc +9 -0
  47. package/native/src/platform/windows/bootstrap.zc +9 -0
  48. package/native/src/platform/windows/engine_qjs.zc +60 -0
  49. package/native/src/platform/windows/platform.zc +387 -0
  50. package/native/src/platform/windows/webview.zc +1175 -0
  51. package/native/src/platform/windows/webview_bootstrap.zc +9 -0
  52. package/native/src/platform/windows/window.zc +1271 -0
  53. package/native/src/platform/windows/worker/common.zc +409 -0
  54. package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
  55. package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
  56. package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
  57. package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
  58. package/native/src/platform/windows/worker/core/url_core.zc +216 -0
  59. package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
  60. package/native/src/platform/windows/worker/dispatch.zc +34 -0
  61. package/native/src/platform/windows/worker/mod.zc +46 -0
  62. package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
  63. package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
  64. package/native/src/platform/windows/worker/qjs.zc +1049 -0
  65. package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
  66. package/native/src/platform/worker.zc +8 -0
  67. package/native/src/service/service.zc +228 -0
  68. package/native/vendor/quickjs-ng/.gitattributes +4 -0
  69. package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
  70. package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
  71. package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
  72. package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
  73. package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
  74. package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
  75. package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
  76. package/native/vendor/quickjs-ng/.gitmodules +5 -0
  77. package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
  78. package/native/vendor/quickjs-ng/LICENSE +24 -0
  79. package/native/vendor/quickjs-ng/Makefile +149 -0
  80. package/native/vendor/quickjs-ng/amalgam.js +53 -0
  81. package/native/vendor/quickjs-ng/api-test.c +927 -0
  82. package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
  83. package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
  84. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
  85. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
  86. package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
  87. package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
  88. package/native/vendor/quickjs-ng/ctest.c +17 -0
  89. package/native/vendor/quickjs-ng/cutils.h +2013 -0
  90. package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
  91. package/native/vendor/quickjs-ng/dtoa.c +1619 -0
  92. package/native/vendor/quickjs-ng/dtoa.h +87 -0
  93. package/native/vendor/quickjs-ng/examples/fib.c +67 -0
  94. package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
  95. package/native/vendor/quickjs-ng/examples/hello.js +1 -0
  96. package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
  97. package/native/vendor/quickjs-ng/examples/meson.build +17 -0
  98. package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
  99. package/native/vendor/quickjs-ng/examples/point.c +154 -0
  100. package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
  101. package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
  102. package/native/vendor/quickjs-ng/fuzz.c +51 -0
  103. package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
  104. package/native/vendor/quickjs-ng/gen/hello.c +53 -0
  105. package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
  106. package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
  107. package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
  108. package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
  109. package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
  110. package/native/vendor/quickjs-ng/libregexp.c +2687 -0
  111. package/native/vendor/quickjs-ng/libregexp.h +98 -0
  112. package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
  113. package/native/vendor/quickjs-ng/libunicode.c +1746 -0
  114. package/native/vendor/quickjs-ng/libunicode.h +126 -0
  115. package/native/vendor/quickjs-ng/list.h +107 -0
  116. package/native/vendor/quickjs-ng/lre-test.c +73 -0
  117. package/native/vendor/quickjs-ng/meson.build +684 -0
  118. package/native/vendor/quickjs-ng/meson_options.txt +6 -0
  119. package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
  120. package/native/vendor/quickjs-ng/qjs.c +748 -0
  121. package/native/vendor/quickjs-ng/qjsc.c +673 -0
  122. package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
  123. package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
  124. package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
  125. package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
  126. package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
  127. package/native/vendor/quickjs-ng/quickjs.c +60259 -0
  128. package/native/vendor/quickjs-ng/quickjs.h +1419 -0
  129. package/native/vendor/quickjs-ng/repl.js +1927 -0
  130. package/native/vendor/quickjs-ng/run-test262.c +2417 -0
  131. package/native/vendor/quickjs-ng/standalone.js +129 -0
  132. package/native/vendor/quickjs-ng/tests/assert.js +49 -0
  133. package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
  134. package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
  135. package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
  136. package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
  137. package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
  138. package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
  139. package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
  140. package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
  141. package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
  142. package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
  143. package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
  144. package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
  145. package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
  146. package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
  147. package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
  148. package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
  149. package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
  150. package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
  151. package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
  152. package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
  153. package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
  154. package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
  155. package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
  156. package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
  157. package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
  158. package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
  159. package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
  160. package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
  161. package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
  162. package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
  163. package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
  164. package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
  165. package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
  166. package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
  167. package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
  168. package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
  169. package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
  170. package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
  171. package/native/vendor/quickjs-ng/tests/empty.js +0 -0
  172. package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
  173. package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
  174. package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
  175. package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
  176. package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
  177. package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
  178. package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
  179. package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
  180. package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
  181. package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
  182. package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
  183. package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
  184. package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
  185. package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
  186. package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
  187. package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
  188. package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
  189. package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
  190. package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
  191. package/native/vendor/quickjs-ng/tests.conf +14 -0
  192. package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
  193. package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
  194. package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
  195. package/native/vendor/quickjs-ng/update-version.sh +32 -0
  196. package/native/vendor/webview2/include/WebView2.h +60636 -0
  197. package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
  198. package/package.json +33 -0
  199. package/src/backend.ts +139 -0
  200. package/src/build-config.ts +87 -0
  201. package/src/build.ts +276 -0
  202. package/src/common.ts +195 -0
  203. package/src/config.ts +89 -0
  204. package/src/dev.ts +164 -0
  205. package/src/generate.ts +200 -0
  206. package/src/icons.ts +116 -0
  207. package/src/init.ts +190 -0
  208. package/src/package.ts +150 -0
  209. package/src/zapp-cli.ts +263 -0
@@ -0,0 +1,2013 @@
1
+ /*
2
+ * C utilities
3
+ *
4
+ * Copyright (c) 2017 Fabrice Bellard
5
+ * Copyright (c) 2018 Charlie Gordon
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #ifndef CUTILS_H
26
+ #define CUTILS_H
27
+
28
+ #include <assert.h>
29
+ #include <stdio.h>
30
+ #include <stdarg.h>
31
+ #include <time.h>
32
+ #if !defined(_MSC_VER)
33
+ #include <sys/time.h>
34
+ #endif
35
+ #if defined(__APPLE__)
36
+ #include <mach-o/dyld.h>
37
+ #endif
38
+ #include <stdbool.h>
39
+ #include <stdlib.h>
40
+ #include <string.h>
41
+ #include <inttypes.h>
42
+ #include <math.h>
43
+
44
+ #ifdef __cplusplus
45
+ extern "C" {
46
+ #endif
47
+
48
+ #if defined(_MSC_VER)
49
+ #include <malloc.h>
50
+ #define alloca _alloca
51
+ #define ssize_t ptrdiff_t
52
+ #endif
53
+ #if defined(__APPLE__)
54
+ #include <malloc/malloc.h>
55
+ #elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__GLIBC__)
56
+ #include <malloc.h>
57
+ #elif defined(__FreeBSD__)
58
+ #include <malloc_np.h>
59
+ #elif defined(_WIN32)
60
+ #include <winsock2.h>
61
+ #include <windows.h>
62
+ #include <process.h> // _beginthread
63
+ #endif
64
+ #if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(__DJGPP)
65
+ #include <errno.h>
66
+ #include <pthread.h>
67
+ #endif
68
+ #if !defined(_WIN32)
69
+ #include <limits.h>
70
+ #include <unistd.h>
71
+ #endif
72
+
73
+ #if defined(__sun)
74
+ #undef __maybe_unused
75
+ #endif
76
+
77
+ #if defined(_MSC_VER) && !defined(__clang__)
78
+ # define likely(x) (x)
79
+ # define unlikely(x) (x)
80
+ # define no_inline __declspec(noinline)
81
+ # define __maybe_unused
82
+ # define __attribute__(x)
83
+ # define __attribute(x)
84
+ #else
85
+ # define likely(x) __builtin_expect(!!(x), 1)
86
+ # define unlikely(x) __builtin_expect(!!(x), 0)
87
+ # define no_inline __attribute__((noinline))
88
+ # define __maybe_unused __attribute__((unused))
89
+ #endif
90
+
91
+ #ifndef offsetof
92
+ #define offsetof(type, field) ((size_t) &((type *)0)->field)
93
+ #endif
94
+ #ifndef countof
95
+ #define countof(x) (sizeof(x) / sizeof((x)[0]))
96
+ #ifndef endof
97
+ #define endof(x) ((x) + countof(x))
98
+ #endif
99
+ #endif
100
+ #ifndef container_of
101
+ /* return the pointer of type 'type *' containing 'ptr' as field 'member' */
102
+ #define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
103
+ #endif
104
+
105
+ #if defined(_MSC_VER) || defined(__cplusplus)
106
+ #define minimum_length(n) n
107
+ #else
108
+ #define minimum_length(n) static n
109
+ #endif
110
+
111
+ /* Borrowed from Folly */
112
+ #ifndef JS_PRINTF_FORMAT
113
+ #ifdef _MSC_VER
114
+ #include <sal.h>
115
+ #define JS_PRINTF_FORMAT _Printf_format_string_
116
+ #define JS_PRINTF_FORMAT_ATTR(format_param, dots_param)
117
+ #else
118
+ #define JS_PRINTF_FORMAT
119
+ #if !defined(__clang__) && defined(__GNUC__)
120
+ #define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
121
+ __attribute__((format(gnu_printf, format_param, dots_param)))
122
+ #else
123
+ #define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
124
+ __attribute__((format(printf, format_param, dots_param)))
125
+ #endif
126
+ #endif
127
+ #endif
128
+
129
+ #if defined(PATH_MAX)
130
+ # define JS__PATH_MAX PATH_MAX
131
+ #elif defined(_WIN32)
132
+ # define JS__PATH_MAX 32767
133
+ #else
134
+ # define JS__PATH_MAX 8192
135
+ #endif
136
+
137
+ static inline void js__pstrcpy(char *buf, int buf_size, const char *str);
138
+ static inline char *js__pstrcat(char *buf, int buf_size, const char *s);
139
+ static inline int js__strstart(const char *str, const char *val, const char **ptr);
140
+ static inline int js__has_suffix(const char *str, const char *suffix);
141
+
142
+ static inline uint8_t is_be(void) {
143
+ union {
144
+ uint16_t a;
145
+ uint8_t b;
146
+ } u = { 0x100 };
147
+ return u.b;
148
+ }
149
+
150
+ static inline int max_int(int a, int b)
151
+ {
152
+ if (a > b)
153
+ return a;
154
+ else
155
+ return b;
156
+ }
157
+
158
+ static inline int min_int(int a, int b)
159
+ {
160
+ if (a < b)
161
+ return a;
162
+ else
163
+ return b;
164
+ }
165
+
166
+ static inline uint32_t max_uint32(uint32_t a, uint32_t b)
167
+ {
168
+ if (a > b)
169
+ return a;
170
+ else
171
+ return b;
172
+ }
173
+
174
+ static inline uint32_t min_uint32(uint32_t a, uint32_t b)
175
+ {
176
+ if (a < b)
177
+ return a;
178
+ else
179
+ return b;
180
+ }
181
+
182
+ static inline int64_t max_int64(int64_t a, int64_t b)
183
+ {
184
+ if (a > b)
185
+ return a;
186
+ else
187
+ return b;
188
+ }
189
+
190
+ static inline int64_t min_int64(int64_t a, int64_t b)
191
+ {
192
+ if (a < b)
193
+ return a;
194
+ else
195
+ return b;
196
+ }
197
+
198
+ /* WARNING: undefined if a = 0 */
199
+ static inline int clz32(unsigned int a)
200
+ {
201
+ #if defined(_MSC_VER) && !defined(__clang__)
202
+ unsigned long index;
203
+ _BitScanReverse(&index, a);
204
+ return 31 - index;
205
+ #else
206
+ return __builtin_clz(a);
207
+ #endif
208
+ }
209
+
210
+ /* WARNING: undefined if a = 0 */
211
+ static inline int clz64(uint64_t a)
212
+ {
213
+ #if defined(_MSC_VER) && !defined(__clang__)
214
+ #if INTPTR_MAX == INT64_MAX
215
+ unsigned long index;
216
+ _BitScanReverse64(&index, a);
217
+ return 63 - index;
218
+ #else
219
+ if (a >> 32)
220
+ return clz32((unsigned)(a >> 32));
221
+ else
222
+ return clz32((unsigned)a) + 32;
223
+ #endif
224
+ #else
225
+ return __builtin_clzll(a);
226
+ #endif
227
+ }
228
+
229
+ /* WARNING: undefined if a = 0 */
230
+ static inline int ctz32(unsigned int a)
231
+ {
232
+ #if defined(_MSC_VER) && !defined(__clang__)
233
+ unsigned long index;
234
+ _BitScanForward(&index, a);
235
+ return index;
236
+ #else
237
+ return __builtin_ctz(a);
238
+ #endif
239
+ }
240
+
241
+ /* WARNING: undefined if a = 0 */
242
+ static inline int ctz64(uint64_t a)
243
+ {
244
+ #if defined(_MSC_VER) && !defined(__clang__)
245
+ unsigned long index;
246
+ _BitScanForward64(&index, a);
247
+ return index;
248
+ #else
249
+ return __builtin_ctzll(a);
250
+ #endif
251
+ }
252
+
253
+ static inline uint64_t get_u64(const uint8_t *tab)
254
+ {
255
+ uint64_t v;
256
+ memcpy(&v, tab, sizeof(v));
257
+ return v;
258
+ }
259
+
260
+ static inline int64_t get_i64(const uint8_t *tab)
261
+ {
262
+ int64_t v;
263
+ memcpy(&v, tab, sizeof(v));
264
+ return v;
265
+ }
266
+
267
+ static inline void put_u64(uint8_t *tab, uint64_t val)
268
+ {
269
+ memcpy(tab, &val, sizeof(val));
270
+ }
271
+
272
+ static inline uint32_t get_u32(const uint8_t *tab)
273
+ {
274
+ uint32_t v;
275
+ memcpy(&v, tab, sizeof(v));
276
+ return v;
277
+ }
278
+
279
+ static inline uint32_t get_u32_le(const uint8_t *tab)
280
+ {
281
+ uint32_t a, b, c, d;
282
+
283
+ a = (uint32_t)tab[0];
284
+ b = (uint32_t)tab[1];
285
+ c = (uint32_t)tab[2];
286
+ d = (uint32_t)tab[3];
287
+ return a | b<<8 | c<<16 | d<<24;
288
+ }
289
+
290
+ static inline int32_t get_i32(const uint8_t *tab)
291
+ {
292
+ int32_t v;
293
+ memcpy(&v, tab, sizeof(v));
294
+ return v;
295
+ }
296
+
297
+ static inline void put_u32(uint8_t *tab, uint32_t val)
298
+ {
299
+ memcpy(tab, &val, sizeof(val));
300
+ }
301
+
302
+ static inline void put_u32_le(uint8_t *tab, uint32_t val)
303
+ {
304
+ tab[0] = val >> 0;
305
+ tab[1] = val >> 8;
306
+ tab[2] = val >> 16;
307
+ tab[3] = val >> 24;
308
+ }
309
+
310
+ static inline uint32_t get_u16(const uint8_t *tab)
311
+ {
312
+ uint16_t v;
313
+ memcpy(&v, tab, sizeof(v));
314
+ return v;
315
+ }
316
+
317
+ static inline int32_t get_i16(const uint8_t *tab)
318
+ {
319
+ int16_t v;
320
+ memcpy(&v, tab, sizeof(v));
321
+ return v;
322
+ }
323
+
324
+ static inline void put_u16(uint8_t *tab, uint16_t val)
325
+ {
326
+ memcpy(tab, &val, sizeof(val));
327
+ }
328
+
329
+ static inline uint32_t get_u8(const uint8_t *tab)
330
+ {
331
+ return *tab;
332
+ }
333
+
334
+ static inline int32_t get_i8(const uint8_t *tab)
335
+ {
336
+ return (int8_t)*tab;
337
+ }
338
+
339
+ static inline void put_u8(uint8_t *tab, uint8_t val)
340
+ {
341
+ *tab = val;
342
+ }
343
+
344
+ #ifndef bswap16
345
+ static inline uint16_t bswap16(uint16_t x)
346
+ {
347
+ return (x >> 8) | (x << 8);
348
+ }
349
+ #endif
350
+
351
+ #ifndef bswap32
352
+ static inline uint32_t bswap32(uint32_t v)
353
+ {
354
+ return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
355
+ ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
356
+ }
357
+ #endif
358
+
359
+ #ifndef bswap64
360
+ static inline uint64_t bswap64(uint64_t v)
361
+ {
362
+ return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
363
+ ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
364
+ ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
365
+ ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
366
+ ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
367
+ ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
368
+ ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
369
+ ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
370
+ }
371
+ #endif
372
+
373
+ static inline void inplace_bswap16(uint8_t *tab) {
374
+ put_u16(tab, bswap16(get_u16(tab)));
375
+ }
376
+
377
+ static inline void inplace_bswap32(uint8_t *tab) {
378
+ put_u32(tab, bswap32(get_u32(tab)));
379
+ }
380
+
381
+ static inline double fromfp16(uint16_t v) {
382
+ double d, s;
383
+ int e;
384
+ if ((v & 0x7C00) == 0x7C00) {
385
+ d = (v & 0x3FF) ? NAN : INFINITY;
386
+ } else {
387
+ d = (v & 0x3FF) / 1024.;
388
+ e = (v & 0x7C00) >> 10;
389
+ if (e == 0) {
390
+ e = -14;
391
+ } else {
392
+ d += 1;
393
+ e -= 15;
394
+ }
395
+ d = scalbn(d, e);
396
+ }
397
+ s = (v & 0x8000) ? -1.0 : 1.0;
398
+ return d * s;
399
+ }
400
+
401
+ static inline uint16_t tofp16(double d) {
402
+ uint16_t f, s;
403
+ double t;
404
+ int e;
405
+ s = 0;
406
+ if (copysign(1, d) < 0) { // preserve sign when |d| is negative zero
407
+ d = -d;
408
+ s = 0x8000;
409
+ }
410
+ if (isinf(d))
411
+ return s | 0x7C00;
412
+ if (isnan(d))
413
+ return s | 0x7C01;
414
+ if (d == 0)
415
+ return s | 0;
416
+ d = 2 * frexp(d, &e);
417
+ e--;
418
+ if (e > 15)
419
+ return s | 0x7C00; // out of range, return +/-infinity
420
+ if (e < -25) {
421
+ d = 0;
422
+ e = 0;
423
+ } else if (e < -14) {
424
+ d = scalbn(d, e + 14);
425
+ e = 0;
426
+ } else {
427
+ d -= 1;
428
+ e += 15;
429
+ }
430
+ d *= 1024.;
431
+ f = (uint16_t)d;
432
+ t = d - f;
433
+ if (t < 0.5)
434
+ goto done;
435
+ if (t == 0.5)
436
+ if ((f & 1) == 0)
437
+ goto done;
438
+ // adjust for rounding
439
+ if (++f == 1024) {
440
+ f = 0;
441
+ if (++e == 31)
442
+ return s | 0x7C00; // out of range, return +/-infinity
443
+ }
444
+ done:
445
+ return s | (e << 10) | f;
446
+ }
447
+
448
+ static inline int isfp16nan(uint16_t v) {
449
+ return (v & 0x7FFF) > 0x7C00;
450
+ }
451
+
452
+ static inline int isfp16zero(uint16_t v) {
453
+ return (v & 0x7FFF) == 0;
454
+ }
455
+
456
+ /* XXX: should take an extra argument to pass slack information to the caller */
457
+ typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
458
+
459
+ typedef struct DynBuf {
460
+ uint8_t *buf;
461
+ size_t size;
462
+ size_t allocated_size;
463
+ bool error; /* true if a memory allocation error occurred */
464
+ DynBufReallocFunc *realloc_func;
465
+ void *opaque; /* for realloc_func */
466
+ } DynBuf;
467
+
468
+ static inline void dbuf_init(DynBuf *s);
469
+ static inline void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
470
+ static inline int dbuf_claim(DynBuf *s, size_t len);
471
+ static inline int dbuf_put(DynBuf *s, const void *data, size_t len);
472
+ static inline int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
473
+ static inline int __dbuf_putc(DynBuf *s, uint8_t c);
474
+ static inline int __dbuf_put_u16(DynBuf *s, uint16_t val);
475
+ static inline int __dbuf_put_u32(DynBuf *s, uint32_t val);
476
+ static inline int __dbuf_put_u64(DynBuf *s, uint64_t val);
477
+ static inline int dbuf_putstr(DynBuf *s, const char *str);
478
+ static inline int dbuf_putc(DynBuf *s, uint8_t val)
479
+ {
480
+ if (unlikely((s->allocated_size - s->size) < 1))
481
+ return __dbuf_putc(s, val);
482
+ s->buf[s->size++] = val;
483
+ return 0;
484
+ }
485
+ static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
486
+ {
487
+ if (unlikely((s->allocated_size - s->size) < 2))
488
+ return __dbuf_put_u16(s, val);
489
+ put_u16(s->buf + s->size, val);
490
+ s->size += 2;
491
+ return 0;
492
+ }
493
+ static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
494
+ {
495
+ if (unlikely((s->allocated_size - s->size) < 4))
496
+ return __dbuf_put_u32(s, val);
497
+ put_u32(s->buf + s->size, val);
498
+ s->size += 4;
499
+ return 0;
500
+ }
501
+ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
502
+ {
503
+ if (unlikely((s->allocated_size - s->size) < 8))
504
+ return __dbuf_put_u64(s, val);
505
+ put_u64(s->buf + s->size, val);
506
+ s->size += 8;
507
+ return 0;
508
+ }
509
+ static inline int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...);
510
+ static inline void dbuf_free(DynBuf *s);
511
+ static inline bool dbuf_error(DynBuf *s) {
512
+ return s->error;
513
+ }
514
+ static inline void dbuf_set_error(DynBuf *s)
515
+ {
516
+ s->error = true;
517
+ }
518
+
519
+ /*---- UTF-8 and UTF-16 handling ----*/
520
+
521
+ #define UTF8_CHAR_LEN_MAX 4
522
+
523
+ enum {
524
+ UTF8_PLAIN_ASCII = 0, // 7-bit ASCII plain text
525
+ UTF8_NON_ASCII = 1, // has non ASCII code points (8-bit or more)
526
+ UTF8_HAS_16BIT = 2, // has 16-bit code points
527
+ UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs
528
+ UTF8_HAS_ERRORS = 8, // has encoding errors
529
+ };
530
+ static inline int utf8_scan(const char *buf, size_t len, size_t *plen);
531
+ static inline size_t utf8_encode_len(uint32_t c);
532
+ static inline size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c);
533
+ static inline uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp);
534
+ static inline uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp);
535
+ static inline size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len);
536
+ static inline size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len);
537
+ static inline size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len);
538
+ static inline size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len);
539
+
540
+ static inline bool is_surrogate(uint32_t c)
541
+ {
542
+ return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
543
+ }
544
+
545
+ static inline bool is_hi_surrogate(uint32_t c)
546
+ {
547
+ return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
548
+ }
549
+
550
+ static inline bool is_lo_surrogate(uint32_t c)
551
+ {
552
+ return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
553
+ }
554
+
555
+ static inline uint32_t get_hi_surrogate(uint32_t c)
556
+ {
557
+ return (c >> 10) - (0x10000 >> 10) + 0xD800;
558
+ }
559
+
560
+ static inline uint32_t get_lo_surrogate(uint32_t c)
561
+ {
562
+ return (c & 0x3FF) | 0xDC00;
563
+ }
564
+
565
+ static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
566
+ {
567
+ return 65536 + 1024 * (hi & 1023) + (lo & 1023);
568
+ }
569
+
570
+ static inline int from_hex(int c)
571
+ {
572
+ if (c >= '0' && c <= '9')
573
+ return c - '0';
574
+ else if (c >= 'A' && c <= 'F')
575
+ return c - 'A' + 10;
576
+ else if (c >= 'a' && c <= 'f')
577
+ return c - 'a' + 10;
578
+ else
579
+ return -1;
580
+ }
581
+
582
+ static inline uint8_t is_upper_ascii(uint8_t c) {
583
+ return c >= 'A' && c <= 'Z';
584
+ }
585
+
586
+ static inline uint8_t to_upper_ascii(uint8_t c) {
587
+ return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
588
+ }
589
+
590
+ static inline void rqsort(void *base, size_t nmemb, size_t size,
591
+ int (*cmp)(const void *, const void *, void *),
592
+ void *arg);
593
+
594
+ static inline uint64_t float64_as_uint64(double d)
595
+ {
596
+ union {
597
+ double d;
598
+ uint64_t u64;
599
+ } u;
600
+ u.d = d;
601
+ return u.u64;
602
+ }
603
+
604
+ static inline double uint64_as_float64(uint64_t u64)
605
+ {
606
+ union {
607
+ double d;
608
+ uint64_t u64;
609
+ } u;
610
+ u.u64 = u64;
611
+ return u.d;
612
+ }
613
+
614
+ static inline int64_t js__gettimeofday_us(void);
615
+ static inline uint64_t js__hrtime_ns(void);
616
+
617
+ static inline size_t js__malloc_usable_size(const void *ptr)
618
+ {
619
+ #if defined(__APPLE__)
620
+ return malloc_size(ptr);
621
+ #elif defined(_WIN32)
622
+ return _msize((void *)ptr);
623
+ #elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__GLIBC__)
624
+ return malloc_usable_size((void *)ptr);
625
+ #else
626
+ return 0;
627
+ #endif
628
+ }
629
+
630
+ static inline int js_exepath(char* buffer, size_t* size);
631
+
632
+ /* Cross-platform threading APIs. */
633
+
634
+ #if defined(EMSCRIPTEN) || defined(__wasi__) || defined(__DJGPP)
635
+
636
+ #define JS_HAVE_THREADS 0
637
+
638
+ #else
639
+
640
+ #define JS_HAVE_THREADS 1
641
+
642
+ #if defined(_WIN32)
643
+ #define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
644
+ typedef INIT_ONCE js_once_t;
645
+ typedef CRITICAL_SECTION js_mutex_t;
646
+ typedef CONDITION_VARIABLE js_cond_t;
647
+ typedef HANDLE js_thread_t;
648
+ #else
649
+ #define JS_ONCE_INIT PTHREAD_ONCE_INIT
650
+ typedef pthread_once_t js_once_t;
651
+ typedef pthread_mutex_t js_mutex_t;
652
+ typedef pthread_cond_t js_cond_t;
653
+ typedef pthread_t js_thread_t;
654
+ #endif
655
+
656
+ static inline void js_once(js_once_t *guard, void (*callback)(void));
657
+
658
+ static inline void js_mutex_init(js_mutex_t *mutex);
659
+ static inline void js_mutex_destroy(js_mutex_t *mutex);
660
+ static inline void js_mutex_lock(js_mutex_t *mutex);
661
+ static inline void js_mutex_unlock(js_mutex_t *mutex);
662
+
663
+ static inline void js_cond_init(js_cond_t *cond);
664
+ static inline void js_cond_destroy(js_cond_t *cond);
665
+ static inline void js_cond_signal(js_cond_t *cond);
666
+ static inline void js_cond_broadcast(js_cond_t *cond);
667
+ static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
668
+ static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
669
+
670
+ enum {
671
+ JS_THREAD_CREATE_DETACHED = 1,
672
+ };
673
+
674
+ // creates threads with 2 MB stacks (glibc default)
675
+ static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
676
+ int flags);
677
+ static inline int js_thread_join(js_thread_t thrd);
678
+
679
+ #endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
680
+
681
+ // JS requires strict rounding behavior. Turn on 64-bits double precision
682
+ // and disable x87 80-bits extended precision for intermediate floating-point
683
+ // results. 0x300 is extended precision, 0x200 is double precision.
684
+ // Note that `*&cw` in the asm constraints looks redundant but isn't.
685
+ #if defined(__i386__) && !defined(_MSC_VER)
686
+ #define JS_X87_FPCW_SAVE_AND_ADJUST(cw) \
687
+ unsigned short cw; \
688
+ __asm__ __volatile__("fnstcw %0" : "=m"(*&cw)); \
689
+ do { \
690
+ unsigned short t = 0x200 | (cw & ~0x300); \
691
+ __asm__ __volatile__("fldcw %0" : /*empty*/ : "m"(*&t)); \
692
+ } while (0)
693
+ #define JS_X87_FPCW_RESTORE(cw) \
694
+ __asm__ __volatile__("fldcw %0" : /*empty*/ : "m"(*&cw))
695
+ #else
696
+ #define JS_X87_FPCW_SAVE_AND_ADJUST(cw)
697
+ #define JS_X87_FPCW_RESTORE(cw)
698
+ #endif
699
+
700
+ #undef NANOSEC
701
+ #define NANOSEC ((uint64_t) 1e9)
702
+
703
+ static inline void js__pstrcpy(char *buf, int buf_size, const char *str)
704
+ {
705
+ int c;
706
+ char *q = buf;
707
+
708
+ if (buf_size <= 0)
709
+ return;
710
+
711
+ for(;;) {
712
+ c = *str++;
713
+ if (c == 0 || q >= buf + buf_size - 1)
714
+ break;
715
+ *q++ = c;
716
+ }
717
+ *q = '\0';
718
+ }
719
+
720
+ /* strcat and truncate. */
721
+ static inline char *js__pstrcat(char *buf, int buf_size, const char *s)
722
+ {
723
+ int len;
724
+ len = strlen(buf);
725
+ if (len < buf_size)
726
+ js__pstrcpy(buf + len, buf_size - len, s);
727
+ return buf;
728
+ }
729
+
730
+ static inline int js__strstart(const char *str, const char *val, const char **ptr)
731
+ {
732
+ const char *p, *q;
733
+ p = str;
734
+ q = val;
735
+ while (*q != '\0') {
736
+ if (*p != *q)
737
+ return 0;
738
+ p++;
739
+ q++;
740
+ }
741
+ if (ptr)
742
+ *ptr = p;
743
+ return 1;
744
+ }
745
+
746
+ static inline int js__has_suffix(const char *str, const char *suffix)
747
+ {
748
+ size_t len = strlen(str);
749
+ size_t slen = strlen(suffix);
750
+ return (len >= slen && !memcmp(str + len - slen, suffix, slen));
751
+ }
752
+
753
+ /* Dynamic buffer package */
754
+
755
+ static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
756
+ {
757
+ if (unlikely(size == 0)) {
758
+ free(ptr);
759
+ return NULL;
760
+ }
761
+ return realloc(ptr, size);
762
+ }
763
+
764
+ static inline void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
765
+ {
766
+ memset(s, 0, sizeof(*s));
767
+ if (!realloc_func)
768
+ realloc_func = dbuf_default_realloc;
769
+ s->opaque = opaque;
770
+ s->realloc_func = realloc_func;
771
+ }
772
+
773
+ static inline void dbuf_init(DynBuf *s)
774
+ {
775
+ dbuf_init2(s, NULL, NULL);
776
+ }
777
+
778
+ /* Try to allocate 'len' more bytes. return < 0 if error */
779
+ static inline int dbuf_claim(DynBuf *s, size_t len)
780
+ {
781
+ size_t new_size, size, new_allocated_size;
782
+ uint8_t *new_buf;
783
+ new_size = s->size + len;
784
+ if (new_size < len)
785
+ return -1; /* overflow */
786
+ if (new_size > s->allocated_size) {
787
+ if (s->error)
788
+ return -1;
789
+ size = s->allocated_size + (s->allocated_size / 2);
790
+ if (size < new_size || size < s->allocated_size) /* overflow test */
791
+ new_allocated_size = new_size;
792
+ else
793
+ new_allocated_size = size;
794
+ new_buf = s->realloc_func(s->opaque, s->buf, new_allocated_size);
795
+ if (!new_buf) {
796
+ s->error = true;
797
+ return -1;
798
+ }
799
+ s->buf = new_buf;
800
+ s->allocated_size = new_allocated_size;
801
+ }
802
+ return 0;
803
+ }
804
+
805
+ static inline int dbuf_put(DynBuf *s, const void *data, size_t len)
806
+ {
807
+ if (unlikely((s->size + len) > s->allocated_size)) {
808
+ if (dbuf_claim(s, len))
809
+ return -1;
810
+ }
811
+ if (len > 0) {
812
+ memcpy(s->buf + s->size, data, len);
813
+ s->size += len;
814
+ }
815
+ return 0;
816
+ }
817
+
818
+ static inline int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
819
+ {
820
+ if (unlikely((s->size + len) > s->allocated_size)) {
821
+ if (dbuf_claim(s, len))
822
+ return -1;
823
+ }
824
+ if (len > 0) {
825
+ memcpy(s->buf + s->size, s->buf + offset, len);
826
+ s->size += len;
827
+ }
828
+ return 0;
829
+ }
830
+
831
+ static inline int __dbuf_putc(DynBuf *s, uint8_t c)
832
+ {
833
+ return dbuf_put(s, &c, 1);
834
+ }
835
+
836
+ static inline int __dbuf_put_u16(DynBuf *s, uint16_t val)
837
+ {
838
+ return dbuf_put(s, (uint8_t *)&val, 2);
839
+ }
840
+
841
+ static inline int __dbuf_put_u32(DynBuf *s, uint32_t val)
842
+ {
843
+ return dbuf_put(s, (uint8_t *)&val, 4);
844
+ }
845
+
846
+ static inline int __dbuf_put_u64(DynBuf *s, uint64_t val)
847
+ {
848
+ return dbuf_put(s, (uint8_t *)&val, 8);
849
+ }
850
+
851
+ static inline int dbuf_putstr(DynBuf *s, const char *str)
852
+ {
853
+ return dbuf_put(s, (const uint8_t *)str, strlen(str));
854
+ }
855
+
856
+ static inline int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...)
857
+ {
858
+ va_list ap;
859
+ char buf[128];
860
+ int len;
861
+
862
+ va_start(ap, fmt);
863
+ len = vsnprintf(buf, sizeof(buf), fmt, ap);
864
+ va_end(ap);
865
+ if (len < (int)sizeof(buf)) {
866
+ /* fast case */
867
+ return dbuf_put(s, (uint8_t *)buf, len);
868
+ } else {
869
+ if (dbuf_claim(s, len + 1))
870
+ return -1;
871
+ va_start(ap, fmt);
872
+ vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
873
+ fmt, ap);
874
+ va_end(ap);
875
+ s->size += len;
876
+ }
877
+ return 0;
878
+ }
879
+
880
+ static inline void dbuf_free(DynBuf *s)
881
+ {
882
+ /* we test s->buf as a fail safe to avoid crashing if dbuf_free()
883
+ is called twice */
884
+ if (s->buf) {
885
+ s->realloc_func(s->opaque, s->buf, 0);
886
+ }
887
+ memset(s, 0, sizeof(*s));
888
+ }
889
+
890
+ /*--- UTF-8 utility functions --*/
891
+
892
+ /* Note: only encode valid codepoints (0x0000..0x10FFFF).
893
+ At most UTF8_CHAR_LEN_MAX bytes are output. */
894
+
895
+ /* Compute the number of bytes of the UTF-8 encoding for a codepoint
896
+ `c` is a code-point.
897
+ Returns the number of bytes. If a codepoint is beyond 0x10FFFF the
898
+ return value is 3 as the codepoint would be encoded as 0xFFFD.
899
+ */
900
+ static inline size_t utf8_encode_len(uint32_t c)
901
+ {
902
+ if (c < 0x80)
903
+ return 1;
904
+ if (c < 0x800)
905
+ return 2;
906
+ if (c < 0x10000)
907
+ return 3;
908
+ if (c < 0x110000)
909
+ return 4;
910
+ return 3;
911
+ }
912
+
913
+ /* Encode a codepoint in UTF-8
914
+ `buf` points to an array of at least `UTF8_CHAR_LEN_MAX` bytes
915
+ `c` is a code-point.
916
+ Returns the number of bytes. If a codepoint is beyond 0x10FFFF the
917
+ return value is 3 and the codepoint is encoded as 0xFFFD.
918
+ No null byte is stored after the encoded bytes.
919
+ Return value is in range 1..4
920
+ */
921
+ static inline size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c)
922
+ {
923
+ if (c < 0x80) {
924
+ buf[0] = c;
925
+ return 1;
926
+ }
927
+ if (c < 0x800) {
928
+ buf[0] = (c >> 6) | 0xC0;
929
+ buf[1] = (c & 0x3F) | 0x80;
930
+ return 2;
931
+ }
932
+ if (c < 0x10000) {
933
+ buf[0] = (c >> 12) | 0xE0;
934
+ buf[1] = ((c >> 6) & 0x3F) | 0x80;
935
+ buf[2] = (c & 0x3F) | 0x80;
936
+ return 3;
937
+ }
938
+ if (c < 0x110000) {
939
+ buf[0] = (c >> 18) | 0xF0;
940
+ buf[1] = ((c >> 12) & 0x3F) | 0x80;
941
+ buf[2] = ((c >> 6) & 0x3F) | 0x80;
942
+ buf[3] = (c & 0x3F) | 0x80;
943
+ return 4;
944
+ }
945
+ buf[0] = (0xFFFD >> 12) | 0xE0;
946
+ buf[1] = ((0xFFFD >> 6) & 0x3F) | 0x80;
947
+ buf[2] = (0xFFFD & 0x3F) | 0x80;
948
+ return 3;
949
+ }
950
+
951
+ /* Decode a single code point from a UTF-8 encoded array of bytes
952
+ `p` is a valid pointer to an array of bytes
953
+ `pp` is a valid pointer to a `const uint8_t *` to store a pointer
954
+ to the byte following the current sequence.
955
+ Return the code point at `p`, in the range `0..0x10FFFF`
956
+ Return 0xFFFD on error. Only a single byte is consumed in this case
957
+ The maximum length for a UTF-8 byte sequence is 4 bytes.
958
+ This implements the algorithm specified in whatwg.org, except it accepts
959
+ UTF-8 encoded surrogates as JavaScript allows them in strings.
960
+ The source string is assumed to have at least UTF8_CHAR_LEN_MAX bytes
961
+ or be null terminated.
962
+ If `p[0]` is '\0', the return value is `0` and the byte is consumed.
963
+ cf: https://encoding.spec.whatwg.org/#utf-8-encoder
964
+ */
965
+ static inline uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp)
966
+ {
967
+ uint32_t c;
968
+ uint8_t lower, upper;
969
+
970
+ c = *p++;
971
+ if (c < 0x80) {
972
+ *pp = p;
973
+ return c;
974
+ }
975
+ switch(c) {
976
+ case 0xC2: case 0xC3:
977
+ case 0xC4: case 0xC5: case 0xC6: case 0xC7:
978
+ case 0xC8: case 0xC9: case 0xCA: case 0xCB:
979
+ case 0xCC: case 0xCD: case 0xCE: case 0xCF:
980
+ case 0xD0: case 0xD1: case 0xD2: case 0xD3:
981
+ case 0xD4: case 0xD5: case 0xD6: case 0xD7:
982
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
983
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
984
+ if (*p >= 0x80 && *p <= 0xBF) {
985
+ *pp = p + 1;
986
+ return ((c - 0xC0) << 6) + (*p - 0x80);
987
+ }
988
+ // otherwise encoding error
989
+ break;
990
+ case 0xE0:
991
+ lower = 0xA0; /* reject invalid encoding */
992
+ goto need2;
993
+ case 0xE1: case 0xE2: case 0xE3:
994
+ case 0xE4: case 0xE5: case 0xE6: case 0xE7:
995
+ case 0xE8: case 0xE9: case 0xEA: case 0xEB:
996
+ case 0xEC: case 0xED: case 0xEE: case 0xEF:
997
+ lower = 0x80;
998
+ need2:
999
+ if (*p >= lower && *p <= 0xBF && p[1] >= 0x80 && p[1] <= 0xBF) {
1000
+ *pp = p + 2;
1001
+ return ((c - 0xE0) << 12) + ((*p - 0x80) << 6) + (p[1] - 0x80);
1002
+ }
1003
+ // otherwise encoding error
1004
+ break;
1005
+ case 0xF0:
1006
+ lower = 0x90; /* reject invalid encoding */
1007
+ upper = 0xBF;
1008
+ goto need3;
1009
+ case 0xF4:
1010
+ lower = 0x80;
1011
+ upper = 0x8F; /* reject values above 0x10FFFF */
1012
+ goto need3;
1013
+ case 0xF1: case 0xF2: case 0xF3:
1014
+ lower = 0x80;
1015
+ upper = 0xBF;
1016
+ need3:
1017
+ if (*p >= lower && *p <= upper && p[1] >= 0x80 && p[1] <= 0xBF
1018
+ && p[2] >= 0x80 && p[2] <= 0xBF) {
1019
+ *pp = p + 3;
1020
+ return ((c - 0xF0) << 18) + ((*p - 0x80) << 12) +
1021
+ ((p[1] - 0x80) << 6) + (p[2] - 0x80);
1022
+ }
1023
+ // otherwise encoding error
1024
+ break;
1025
+ default:
1026
+ // invalid lead byte
1027
+ break;
1028
+ }
1029
+ *pp = p;
1030
+ return 0xFFFD;
1031
+ }
1032
+
1033
+ static inline uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp) {
1034
+ switch (max_len) {
1035
+ case 0:
1036
+ *pp = p;
1037
+ return 0xFFFD;
1038
+ case 1:
1039
+ if (*p < 0x80)
1040
+ goto good;
1041
+ break;
1042
+ case 2:
1043
+ if (*p < 0xE0)
1044
+ goto good;
1045
+ break;
1046
+ case 3:
1047
+ if (*p < 0xF0)
1048
+ goto good;
1049
+ break;
1050
+ default:
1051
+ good:
1052
+ return utf8_decode(p, pp);
1053
+ }
1054
+ *pp = p + 1;
1055
+ return 0xFFFD;
1056
+ }
1057
+
1058
+ /* Scan a UTF-8 encoded buffer for content type
1059
+ `buf` is a valid pointer to a UTF-8 encoded string
1060
+ `len` is the number of bytes to scan
1061
+ `plen` points to a `size_t` variable to receive the number of units
1062
+ Return value is a mask of bits.
1063
+ - `UTF8_PLAIN_ASCII`: return value for 7-bit ASCII plain text
1064
+ - `UTF8_NON_ASCII`: bit for non ASCII code points (8-bit or more)
1065
+ - `UTF8_HAS_16BIT`: bit for 16-bit code points
1066
+ - `UTF8_HAS_NON_BMP1`: bit for non-BMP1 code points, needs UTF-16 surrogate pairs
1067
+ - `UTF8_HAS_ERRORS`: bit for encoding errors
1068
+ */
1069
+ static inline int utf8_scan(const char *buf, size_t buf_len, size_t *plen)
1070
+ {
1071
+ const uint8_t *p, *p_end, *p_next;
1072
+ size_t i, len;
1073
+ int kind;
1074
+ uint8_t cbits;
1075
+
1076
+ kind = UTF8_PLAIN_ASCII;
1077
+ cbits = 0;
1078
+ len = buf_len;
1079
+ // TODO: handle more than 1 byte at a time
1080
+ for (i = 0; i < buf_len; i++)
1081
+ cbits |= buf[i];
1082
+ if (cbits >= 0x80) {
1083
+ p = (const uint8_t *)buf;
1084
+ p_end = p + buf_len;
1085
+ kind = UTF8_NON_ASCII;
1086
+ len = 0;
1087
+ while (p < p_end) {
1088
+ len++;
1089
+ if (*p++ >= 0x80) {
1090
+ /* parse UTF-8 sequence, check for encoding error */
1091
+ uint32_t c = utf8_decode_len(p - 1, p_end - (p - 1), &p_next);
1092
+ if (p_next == p)
1093
+ kind |= UTF8_HAS_ERRORS;
1094
+ p = p_next;
1095
+ if (c > 0xFF) {
1096
+ kind |= UTF8_HAS_16BIT;
1097
+ if (c > 0xFFFF) {
1098
+ len++;
1099
+ kind |= UTF8_HAS_NON_BMP1;
1100
+ }
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ *plen = len;
1106
+ return kind;
1107
+ }
1108
+
1109
+ /* Decode a string encoded in UTF-8 into an array of bytes
1110
+ `src` points to the source string. It is assumed to be correctly encoded
1111
+ and only contains code points below 0x800
1112
+ `src_len` is the length of the source string
1113
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
1114
+ `dest_len` is the length of the destination array. A null
1115
+ terminator is stored at the end of the array unless `dest_len` is `0`.
1116
+ */
1117
+ static inline size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len)
1118
+ {
1119
+ const uint8_t *p, *p_end;
1120
+ size_t i;
1121
+
1122
+ p = (const uint8_t *)src;
1123
+ p_end = p + src_len;
1124
+ for (i = 0; p < p_end; i++) {
1125
+ uint32_t c = *p++;
1126
+ if (c >= 0xC0)
1127
+ c = (c << 6) + *p++ - ((0xC0 << 6) + 0x80);
1128
+ if (i < dest_len)
1129
+ dest[i] = c;
1130
+ }
1131
+ if (i < dest_len)
1132
+ dest[i] = '\0';
1133
+ else if (dest_len > 0)
1134
+ dest[dest_len - 1] = '\0';
1135
+ return i;
1136
+ }
1137
+
1138
+ /* Decode a string encoded in UTF-8 into an array of 16-bit words
1139
+ `src` points to the source string. It is assumed to be correctly encoded.
1140
+ `src_len` is the length of the source string
1141
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
1142
+ `dest_len` is the length of the destination array. No null terminator is
1143
+ stored at the end of the array.
1144
+ */
1145
+ static inline size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len)
1146
+ {
1147
+ const uint8_t *p, *p_end;
1148
+ size_t i;
1149
+
1150
+ p = (const uint8_t *)src;
1151
+ p_end = p + src_len;
1152
+ for (i = 0; p < p_end; i++) {
1153
+ uint32_t c = *p++;
1154
+ if (c >= 0x80) {
1155
+ /* parse utf-8 sequence */
1156
+ c = utf8_decode_len(p - 1, p_end - (p - 1), &p);
1157
+ /* encoding errors are converted as 0xFFFD and use a single byte */
1158
+ if (c > 0xFFFF) {
1159
+ if (i < dest_len)
1160
+ dest[i] = get_hi_surrogate(c);
1161
+ i++;
1162
+ c = get_lo_surrogate(c);
1163
+ }
1164
+ }
1165
+ if (i < dest_len)
1166
+ dest[i] = c;
1167
+ }
1168
+ return i;
1169
+ }
1170
+
1171
+ /* Encode a buffer of 8-bit bytes as a UTF-8 encoded string
1172
+ `src` points to the source buffer.
1173
+ `src_len` is the length of the source buffer
1174
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
1175
+ `dest_len` is the length in bytes of the destination array. A null
1176
+ terminator is stored at the end of the array unless `dest_len` is `0`.
1177
+ */
1178
+ static inline size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len)
1179
+ {
1180
+ size_t i, j;
1181
+ uint32_t c;
1182
+
1183
+ for (i = j = 0; i < src_len; i++) {
1184
+ c = src[i];
1185
+ if (c < 0x80) {
1186
+ if (j + 1 >= dest_len)
1187
+ goto overflow;
1188
+ dest[j++] = c;
1189
+ } else {
1190
+ if (j + 2 >= dest_len)
1191
+ goto overflow;
1192
+ dest[j++] = (c >> 6) | 0xC0;
1193
+ dest[j++] = (c & 0x3F) | 0x80;
1194
+ }
1195
+ }
1196
+ if (j < dest_len)
1197
+ dest[j] = '\0';
1198
+ return j;
1199
+
1200
+ overflow:
1201
+ if (j < dest_len)
1202
+ dest[j] = '\0';
1203
+ while (i < src_len)
1204
+ j += 1 + (src[i++] >= 0x80);
1205
+ return j;
1206
+ }
1207
+
1208
+ /* Encode a buffer of 16-bit code points as a UTF-8 encoded string
1209
+ `src` points to the source buffer.
1210
+ `src_len` is the length of the source buffer
1211
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
1212
+ `dest_len` is the length in bytes of the destination array. A null
1213
+ terminator is stored at the end of the array unless `dest_len` is `0`.
1214
+ */
1215
+ static inline size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len)
1216
+ {
1217
+ size_t i, j;
1218
+ uint32_t c;
1219
+
1220
+ for (i = j = 0; i < src_len;) {
1221
+ c = src[i++];
1222
+ if (c < 0x80) {
1223
+ if (j + 1 >= dest_len)
1224
+ goto overflow;
1225
+ dest[j++] = c;
1226
+ } else {
1227
+ if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i]))
1228
+ c = from_surrogate(c, src[i++]);
1229
+ if (j + utf8_encode_len(c) >= dest_len)
1230
+ goto overflow;
1231
+ j += utf8_encode((uint8_t *)dest + j, c);
1232
+ }
1233
+ }
1234
+ if (j < dest_len)
1235
+ dest[j] = '\0';
1236
+ return j;
1237
+
1238
+ overflow:
1239
+ i -= 1 + (c > 0xFFFF);
1240
+ if (j < dest_len)
1241
+ dest[j] = '\0';
1242
+ while (i < src_len) {
1243
+ c = src[i++];
1244
+ if (c < 0x80) {
1245
+ j++;
1246
+ } else {
1247
+ if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i]))
1248
+ c = from_surrogate(c, src[i++]);
1249
+ j += utf8_encode_len(c);
1250
+ }
1251
+ }
1252
+ return j;
1253
+ }
1254
+
1255
+ /*---- sorting with opaque argument ----*/
1256
+
1257
+ typedef void (*exchange_f)(void *a, void *b, size_t size);
1258
+ typedef int (*cmp_f)(const void *, const void *, void *opaque);
1259
+
1260
+ static void exchange_bytes(void *a, void *b, size_t size) {
1261
+ uint8_t *ap = (uint8_t *)a;
1262
+ uint8_t *bp = (uint8_t *)b;
1263
+
1264
+ while (size-- != 0) {
1265
+ uint8_t t = *ap;
1266
+ *ap++ = *bp;
1267
+ *bp++ = t;
1268
+ }
1269
+ }
1270
+
1271
+ static void exchange_one_byte(void *a, void *b, size_t size) {
1272
+ uint8_t *ap = (uint8_t *)a;
1273
+ uint8_t *bp = (uint8_t *)b;
1274
+ uint8_t t = *ap;
1275
+ *ap = *bp;
1276
+ *bp = t;
1277
+ }
1278
+
1279
+ static void exchange_int16s(void *a, void *b, size_t size) {
1280
+ uint16_t *ap = (uint16_t *)a;
1281
+ uint16_t *bp = (uint16_t *)b;
1282
+
1283
+ for (size /= sizeof(uint16_t); size-- != 0;) {
1284
+ uint16_t t = *ap;
1285
+ *ap++ = *bp;
1286
+ *bp++ = t;
1287
+ }
1288
+ }
1289
+
1290
+ static void exchange_one_int16(void *a, void *b, size_t size) {
1291
+ uint16_t *ap = (uint16_t *)a;
1292
+ uint16_t *bp = (uint16_t *)b;
1293
+ uint16_t t = *ap;
1294
+ *ap = *bp;
1295
+ *bp = t;
1296
+ }
1297
+
1298
+ static void exchange_int32s(void *a, void *b, size_t size) {
1299
+ uint32_t *ap = (uint32_t *)a;
1300
+ uint32_t *bp = (uint32_t *)b;
1301
+
1302
+ for (size /= sizeof(uint32_t); size-- != 0;) {
1303
+ uint32_t t = *ap;
1304
+ *ap++ = *bp;
1305
+ *bp++ = t;
1306
+ }
1307
+ }
1308
+
1309
+ static void exchange_one_int32(void *a, void *b, size_t size) {
1310
+ uint32_t *ap = (uint32_t *)a;
1311
+ uint32_t *bp = (uint32_t *)b;
1312
+ uint32_t t = *ap;
1313
+ *ap = *bp;
1314
+ *bp = t;
1315
+ }
1316
+
1317
+ static void exchange_int64s(void *a, void *b, size_t size) {
1318
+ uint64_t *ap = (uint64_t *)a;
1319
+ uint64_t *bp = (uint64_t *)b;
1320
+
1321
+ for (size /= sizeof(uint64_t); size-- != 0;) {
1322
+ uint64_t t = *ap;
1323
+ *ap++ = *bp;
1324
+ *bp++ = t;
1325
+ }
1326
+ }
1327
+
1328
+ static void exchange_one_int64(void *a, void *b, size_t size) {
1329
+ uint64_t *ap = (uint64_t *)a;
1330
+ uint64_t *bp = (uint64_t *)b;
1331
+ uint64_t t = *ap;
1332
+ *ap = *bp;
1333
+ *bp = t;
1334
+ }
1335
+
1336
+ static void exchange_int128s(void *a, void *b, size_t size) {
1337
+ uint64_t *ap = (uint64_t *)a;
1338
+ uint64_t *bp = (uint64_t *)b;
1339
+
1340
+ for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
1341
+ uint64_t t = ap[0];
1342
+ uint64_t u = ap[1];
1343
+ ap[0] = bp[0];
1344
+ ap[1] = bp[1];
1345
+ bp[0] = t;
1346
+ bp[1] = u;
1347
+ }
1348
+ }
1349
+
1350
+ static void exchange_one_int128(void *a, void *b, size_t size) {
1351
+ uint64_t *ap = (uint64_t *)a;
1352
+ uint64_t *bp = (uint64_t *)b;
1353
+ uint64_t t = ap[0];
1354
+ uint64_t u = ap[1];
1355
+ ap[0] = bp[0];
1356
+ ap[1] = bp[1];
1357
+ bp[0] = t;
1358
+ bp[1] = u;
1359
+ }
1360
+
1361
+ static inline exchange_f exchange_func(const void *base, size_t size) {
1362
+ switch (((uintptr_t)base | (uintptr_t)size) & 15) {
1363
+ case 0:
1364
+ if (size == sizeof(uint64_t) * 2)
1365
+ return exchange_one_int128;
1366
+ else
1367
+ return exchange_int128s;
1368
+ case 8:
1369
+ if (size == sizeof(uint64_t))
1370
+ return exchange_one_int64;
1371
+ else
1372
+ return exchange_int64s;
1373
+ case 4:
1374
+ case 12:
1375
+ if (size == sizeof(uint32_t))
1376
+ return exchange_one_int32;
1377
+ else
1378
+ return exchange_int32s;
1379
+ case 2:
1380
+ case 6:
1381
+ case 10:
1382
+ case 14:
1383
+ if (size == sizeof(uint16_t))
1384
+ return exchange_one_int16;
1385
+ else
1386
+ return exchange_int16s;
1387
+ default:
1388
+ if (size == 1)
1389
+ return exchange_one_byte;
1390
+ else
1391
+ return exchange_bytes;
1392
+ }
1393
+ }
1394
+
1395
+ static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
1396
+ {
1397
+ uint8_t *basep = (uint8_t *)base;
1398
+ size_t i, n, c, r;
1399
+ exchange_f swap = exchange_func(base, size);
1400
+
1401
+ if (nmemb > 1) {
1402
+ i = (nmemb / 2) * size;
1403
+ n = nmemb * size;
1404
+
1405
+ while (i > 0) {
1406
+ i -= size;
1407
+ for (r = i; (c = r * 2 + size) < n; r = c) {
1408
+ if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
1409
+ c += size;
1410
+ if (cmp(basep + r, basep + c, opaque) > 0)
1411
+ break;
1412
+ swap(basep + r, basep + c, size);
1413
+ }
1414
+ }
1415
+ for (i = n - size; i > 0; i -= size) {
1416
+ swap(basep, basep + i, size);
1417
+
1418
+ for (r = 0; (c = r * 2 + size) < i; r = c) {
1419
+ if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
1420
+ c += size;
1421
+ if (cmp(basep + r, basep + c, opaque) > 0)
1422
+ break;
1423
+ swap(basep + r, basep + c, size);
1424
+ }
1425
+ }
1426
+ }
1427
+ }
1428
+
1429
+ static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
1430
+ {
1431
+ return cmp(a, b, opaque) < 0 ?
1432
+ (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
1433
+ (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
1434
+ }
1435
+
1436
+ /* pointer based version with local stack and insertion sort threshhold */
1437
+ static inline void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
1438
+ {
1439
+ struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
1440
+ uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
1441
+ size_t m4, i, lt, gt, span, span2;
1442
+ int c, depth;
1443
+ exchange_f swap = exchange_func(base, size);
1444
+ exchange_f swap_block = exchange_func(base, size | 128);
1445
+
1446
+ if (nmemb < 2 || size <= 0)
1447
+ return;
1448
+
1449
+ sp->base = (uint8_t *)base;
1450
+ sp->count = nmemb;
1451
+ sp->depth = 0;
1452
+ sp++;
1453
+
1454
+ while (sp > stack) {
1455
+ sp--;
1456
+ ptr = sp->base;
1457
+ nmemb = sp->count;
1458
+ depth = sp->depth;
1459
+
1460
+ while (nmemb > 6) {
1461
+ if (++depth > 50) {
1462
+ /* depth check to ensure worst case logarithmic time */
1463
+ heapsortx(ptr, nmemb, size, cmp, opaque);
1464
+ nmemb = 0;
1465
+ break;
1466
+ }
1467
+ /* select median of 3 from 1/4, 1/2, 3/4 positions */
1468
+ /* should use median of 5 or 9? */
1469
+ m4 = (nmemb >> 2) * size;
1470
+ m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
1471
+ swap(ptr, m, size); /* move the pivot to the start or the array */
1472
+ i = lt = 1;
1473
+ pi = plt = ptr + size;
1474
+ gt = nmemb;
1475
+ pj = pgt = top = ptr + nmemb * size;
1476
+ for (;;) {
1477
+ while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
1478
+ if (c == 0) {
1479
+ swap(plt, pi, size);
1480
+ lt++;
1481
+ plt += size;
1482
+ }
1483
+ i++;
1484
+ pi += size;
1485
+ }
1486
+ while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
1487
+ if (c == 0) {
1488
+ gt--;
1489
+ pgt -= size;
1490
+ swap(pgt, pj, size);
1491
+ }
1492
+ }
1493
+ if (pi >= pj)
1494
+ break;
1495
+ swap(pi, pj, size);
1496
+ i++;
1497
+ pi += size;
1498
+ }
1499
+ /* array has 4 parts:
1500
+ * from 0 to lt excluded: elements identical to pivot
1501
+ * from lt to pi excluded: elements smaller than pivot
1502
+ * from pi to gt excluded: elements greater than pivot
1503
+ * from gt to n excluded: elements identical to pivot
1504
+ */
1505
+ /* move elements identical to pivot in the middle of the array: */
1506
+ /* swap values in ranges [0..lt[ and [i-lt..i[
1507
+ swapping the smallest span between lt and i-lt is sufficient
1508
+ */
1509
+ span = plt - ptr;
1510
+ span2 = pi - plt;
1511
+ lt = i - lt;
1512
+ if (span > span2)
1513
+ span = span2;
1514
+ swap_block(ptr, pi - span, span);
1515
+ /* swap values in ranges [gt..top[ and [i..top-(top-gt)[
1516
+ swapping the smallest span between top-gt and gt-i is sufficient
1517
+ */
1518
+ span = top - pgt;
1519
+ span2 = pgt - pi;
1520
+ pgt = top - span2;
1521
+ gt = nmemb - (gt - i);
1522
+ if (span > span2)
1523
+ span = span2;
1524
+ swap_block(pi, top - span, span);
1525
+
1526
+ /* now array has 3 parts:
1527
+ * from 0 to lt excluded: elements smaller than pivot
1528
+ * from lt to gt excluded: elements identical to pivot
1529
+ * from gt to n excluded: elements greater than pivot
1530
+ */
1531
+ /* stack the larger segment and keep processing the smaller one
1532
+ to minimize stack use for pathological distributions */
1533
+ if (lt > nmemb - gt) {
1534
+ sp->base = ptr;
1535
+ sp->count = lt;
1536
+ sp->depth = depth;
1537
+ sp++;
1538
+ ptr = pgt;
1539
+ nmemb -= gt;
1540
+ } else {
1541
+ sp->base = pgt;
1542
+ sp->count = nmemb - gt;
1543
+ sp->depth = depth;
1544
+ sp++;
1545
+ nmemb = lt;
1546
+ }
1547
+ }
1548
+ /* Use insertion sort for small fragments */
1549
+ for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
1550
+ for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
1551
+ swap(pj, pj - size, size);
1552
+ }
1553
+ }
1554
+ }
1555
+
1556
+ /*---- Portable time functions ----*/
1557
+
1558
+ #ifdef _WIN32
1559
+ // From: https://stackoverflow.com/a/26085827
1560
+ static int gettimeofday_msvc(struct timeval *tp)
1561
+ {
1562
+ static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
1563
+
1564
+ SYSTEMTIME system_time;
1565
+ FILETIME file_time;
1566
+ uint64_t time;
1567
+
1568
+ GetSystemTime(&system_time);
1569
+ SystemTimeToFileTime(&system_time, &file_time);
1570
+ time = ((uint64_t)file_time.dwLowDateTime);
1571
+ time += ((uint64_t)file_time.dwHighDateTime) << 32;
1572
+
1573
+ tp->tv_sec = (long)((time - EPOCH) / 10000000L);
1574
+ tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
1575
+
1576
+ return 0;
1577
+ }
1578
+
1579
+ static inline uint64_t js__hrtime_ns(void) {
1580
+ LARGE_INTEGER counter, frequency;
1581
+ double scaled_freq;
1582
+ double result;
1583
+
1584
+ if (!QueryPerformanceFrequency(&frequency))
1585
+ abort();
1586
+ assert(frequency.QuadPart != 0);
1587
+
1588
+ if (!QueryPerformanceCounter(&counter))
1589
+ abort();
1590
+ assert(counter.QuadPart != 0);
1591
+
1592
+ /* Because we have no guarantee about the order of magnitude of the
1593
+ * performance counter interval, integer math could cause this computation
1594
+ * to overflow. Therefore we resort to floating point math.
1595
+ */
1596
+ scaled_freq = (double) frequency.QuadPart / NANOSEC;
1597
+ result = (double) counter.QuadPart / scaled_freq;
1598
+ return (uint64_t) result;
1599
+ }
1600
+ #else
1601
+ static inline uint64_t js__hrtime_ns(void) {
1602
+ #ifdef __DJGPP
1603
+ struct timeval tv;
1604
+ if (gettimeofday(&tv, NULL))
1605
+ abort();
1606
+ return tv.tv_sec * NANOSEC + tv.tv_usec * 1000;
1607
+ #else
1608
+ struct timespec t;
1609
+
1610
+ if (clock_gettime(CLOCK_MONOTONIC, &t))
1611
+ abort();
1612
+
1613
+ return t.tv_sec * NANOSEC + t.tv_nsec;
1614
+ #endif
1615
+ }
1616
+ #endif
1617
+
1618
+ static inline int64_t js__gettimeofday_us(void) {
1619
+ struct timeval tv;
1620
+ #ifdef _WIN32
1621
+ gettimeofday_msvc(&tv);
1622
+ #else
1623
+ gettimeofday(&tv, NULL);
1624
+ #endif
1625
+ return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
1626
+ }
1627
+
1628
+ #if defined(_WIN32)
1629
+ static inline int js_exepath(char *buffer, size_t *size_ptr) {
1630
+ int utf8_len, utf16_buffer_len, utf16_len;
1631
+ WCHAR* utf16_buffer;
1632
+
1633
+ if (buffer == NULL || size_ptr == NULL || *size_ptr == 0)
1634
+ return -1;
1635
+
1636
+ if (*size_ptr > 32768) {
1637
+ /* Windows paths can never be longer than this. */
1638
+ utf16_buffer_len = 32768;
1639
+ } else {
1640
+ utf16_buffer_len = (int)*size_ptr;
1641
+ }
1642
+
1643
+ utf16_buffer = malloc(sizeof(WCHAR) * utf16_buffer_len);
1644
+ if (!utf16_buffer)
1645
+ return -1;
1646
+
1647
+ /* Get the path as UTF-16. */
1648
+ utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
1649
+ if (utf16_len <= 0)
1650
+ goto error;
1651
+
1652
+ /* Convert to UTF-8 */
1653
+ utf8_len = WideCharToMultiByte(CP_UTF8,
1654
+ 0,
1655
+ utf16_buffer,
1656
+ -1,
1657
+ buffer,
1658
+ (int)*size_ptr,
1659
+ NULL,
1660
+ NULL);
1661
+ if (utf8_len == 0)
1662
+ goto error;
1663
+
1664
+ free(utf16_buffer);
1665
+
1666
+ /* utf8_len *does* include the terminating null at this point, but the
1667
+ * returned size shouldn't. */
1668
+ *size_ptr = utf8_len - 1;
1669
+ return 0;
1670
+
1671
+ error:
1672
+ free(utf16_buffer);
1673
+ return -1;
1674
+ }
1675
+ #elif defined(__APPLE__)
1676
+ static inline int js_exepath(char *buffer, size_t *size) {
1677
+ /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */
1678
+ char abspath[PATH_MAX * 2 + 1];
1679
+ char exepath[PATH_MAX + 1];
1680
+ uint32_t exepath_size;
1681
+ size_t abspath_size;
1682
+
1683
+ if (buffer == NULL || size == NULL || *size == 0)
1684
+ return -1;
1685
+
1686
+ exepath_size = sizeof(exepath);
1687
+ if (_NSGetExecutablePath(exepath, &exepath_size))
1688
+ return -1;
1689
+
1690
+ if (realpath(exepath, abspath) != abspath)
1691
+ return -1;
1692
+
1693
+ abspath_size = strlen(abspath);
1694
+ if (abspath_size == 0)
1695
+ return -1;
1696
+
1697
+ *size -= 1;
1698
+ if (*size > abspath_size)
1699
+ *size = abspath_size;
1700
+
1701
+ memcpy(buffer, abspath, *size);
1702
+ buffer[*size] = '\0';
1703
+
1704
+ return 0;
1705
+ }
1706
+ #elif defined(__linux__) || defined(__GNU__)
1707
+ static inline int js_exepath(char *buffer, size_t *size) {
1708
+ ssize_t n;
1709
+
1710
+ if (buffer == NULL || size == NULL || *size == 0)
1711
+ return -1;
1712
+
1713
+ n = *size - 1;
1714
+ if (n > 0)
1715
+ n = readlink("/proc/self/exe", buffer, n);
1716
+
1717
+ if (n == -1)
1718
+ return n;
1719
+
1720
+ buffer[n] = '\0';
1721
+ *size = n;
1722
+
1723
+ return 0;
1724
+ }
1725
+ #else
1726
+ static inline int js_exepath(char* buffer, size_t* size_ptr) {
1727
+ return -1;
1728
+ }
1729
+ #endif
1730
+
1731
+ /*--- Cross-platform threading APIs. ----*/
1732
+
1733
+ #if JS_HAVE_THREADS
1734
+ #if defined(_WIN32)
1735
+ typedef void (*js__once_cb)(void);
1736
+
1737
+ typedef struct {
1738
+ js__once_cb callback;
1739
+ } js__once_data_t;
1740
+
1741
+ static int WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) {
1742
+ js__once_data_t *data = param;
1743
+
1744
+ data->callback();
1745
+
1746
+ return 1;
1747
+ }
1748
+
1749
+ static inline void js_once(js_once_t *guard, js__once_cb callback) {
1750
+ js__once_data_t data = { .callback = callback };
1751
+ InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL);
1752
+ }
1753
+
1754
+ static inline void js_mutex_init(js_mutex_t *mutex) {
1755
+ InitializeCriticalSection(mutex);
1756
+ }
1757
+
1758
+ static inline void js_mutex_destroy(js_mutex_t *mutex) {
1759
+ DeleteCriticalSection(mutex);
1760
+ }
1761
+
1762
+ static inline void js_mutex_lock(js_mutex_t *mutex) {
1763
+ EnterCriticalSection(mutex);
1764
+ }
1765
+
1766
+ static inline void js_mutex_unlock(js_mutex_t *mutex) {
1767
+ LeaveCriticalSection(mutex);
1768
+ }
1769
+
1770
+ static inline void js_cond_init(js_cond_t *cond) {
1771
+ InitializeConditionVariable(cond);
1772
+ }
1773
+
1774
+ static inline void js_cond_destroy(js_cond_t *cond) {
1775
+ /* nothing to do */
1776
+ (void) cond;
1777
+ }
1778
+
1779
+ static inline void js_cond_signal(js_cond_t *cond) {
1780
+ WakeConditionVariable(cond);
1781
+ }
1782
+
1783
+ static inline void js_cond_broadcast(js_cond_t *cond) {
1784
+ WakeAllConditionVariable(cond);
1785
+ }
1786
+
1787
+ static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
1788
+ if (!SleepConditionVariableCS(cond, mutex, INFINITE))
1789
+ abort();
1790
+ }
1791
+
1792
+ static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
1793
+ if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6)))
1794
+ return 0;
1795
+ if (GetLastError() != ERROR_TIMEOUT)
1796
+ abort();
1797
+ return -1;
1798
+ }
1799
+
1800
+ static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
1801
+ int flags)
1802
+ {
1803
+ HANDLE h, cp;
1804
+
1805
+ *thrd = INVALID_HANDLE_VALUE;
1806
+ if (flags & ~JS_THREAD_CREATE_DETACHED)
1807
+ return -1;
1808
+ h = (HANDLE)_beginthread(start, /*stacksize*/2<<20, arg);
1809
+ if (!h)
1810
+ return -1;
1811
+ if (flags & JS_THREAD_CREATE_DETACHED)
1812
+ return 0;
1813
+ // _endthread() automatically closes the handle but we want to wait on
1814
+ // it so make a copy. Race-y for very short-lived threads. Can be solved
1815
+ // by switching to _beginthreadex(CREATE_SUSPENDED) but means changing
1816
+ // |start| from __cdecl to __stdcall.
1817
+ cp = GetCurrentProcess();
1818
+ if (DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS))
1819
+ return 0;
1820
+ return -1;
1821
+ }
1822
+
1823
+ static inline int js_thread_join(js_thread_t thrd)
1824
+ {
1825
+ if (WaitForSingleObject(thrd, INFINITE))
1826
+ return -1;
1827
+ CloseHandle(thrd);
1828
+ return 0;
1829
+ }
1830
+
1831
+ #else /* !defined(_WIN32) */
1832
+
1833
+ static inline void js_once(js_once_t *guard, void (*callback)(void)) {
1834
+ if (pthread_once(guard, callback))
1835
+ abort();
1836
+ }
1837
+
1838
+ static inline void js_mutex_init(js_mutex_t *mutex) {
1839
+ if (pthread_mutex_init(mutex, NULL))
1840
+ abort();
1841
+ }
1842
+
1843
+ static inline void js_mutex_destroy(js_mutex_t *mutex) {
1844
+ if (pthread_mutex_destroy(mutex))
1845
+ abort();
1846
+ }
1847
+
1848
+ static inline void js_mutex_lock(js_mutex_t *mutex) {
1849
+ if (pthread_mutex_lock(mutex))
1850
+ abort();
1851
+ }
1852
+
1853
+ static inline void js_mutex_unlock(js_mutex_t *mutex) {
1854
+ if (pthread_mutex_unlock(mutex))
1855
+ abort();
1856
+ }
1857
+
1858
+ static inline void js_cond_init(js_cond_t *cond) {
1859
+ #if defined(__APPLE__) && defined(__MACH__)
1860
+ if (pthread_cond_init(cond, NULL))
1861
+ abort();
1862
+ #else
1863
+ pthread_condattr_t attr;
1864
+
1865
+ if (pthread_condattr_init(&attr))
1866
+ abort();
1867
+
1868
+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
1869
+ abort();
1870
+
1871
+ if (pthread_cond_init(cond, &attr))
1872
+ abort();
1873
+
1874
+ if (pthread_condattr_destroy(&attr))
1875
+ abort();
1876
+ #endif
1877
+ }
1878
+
1879
+ static inline void js_cond_destroy(js_cond_t *cond) {
1880
+ #if defined(__APPLE__) && defined(__MACH__)
1881
+ /* It has been reported that destroying condition variables that have been
1882
+ * signalled but not waited on can sometimes result in application crashes.
1883
+ * See https://codereview.chromium.org/1323293005.
1884
+ */
1885
+ pthread_mutex_t mutex;
1886
+ struct timespec ts;
1887
+ int err;
1888
+
1889
+ if (pthread_mutex_init(&mutex, NULL))
1890
+ abort();
1891
+
1892
+ if (pthread_mutex_lock(&mutex))
1893
+ abort();
1894
+
1895
+ ts.tv_sec = 0;
1896
+ ts.tv_nsec = 1;
1897
+
1898
+ err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
1899
+ if (err != 0 && err != ETIMEDOUT)
1900
+ abort();
1901
+
1902
+ if (pthread_mutex_unlock(&mutex))
1903
+ abort();
1904
+
1905
+ if (pthread_mutex_destroy(&mutex))
1906
+ abort();
1907
+ #endif /* defined(__APPLE__) && defined(__MACH__) */
1908
+
1909
+ if (pthread_cond_destroy(cond))
1910
+ abort();
1911
+ }
1912
+
1913
+ static inline void js_cond_signal(js_cond_t *cond) {
1914
+ if (pthread_cond_signal(cond))
1915
+ abort();
1916
+ }
1917
+
1918
+ static inline void js_cond_broadcast(js_cond_t *cond) {
1919
+ if (pthread_cond_broadcast(cond))
1920
+ abort();
1921
+ }
1922
+
1923
+ static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
1924
+ #if defined(__APPLE__) && defined(__MACH__)
1925
+ int r;
1926
+
1927
+ errno = 0;
1928
+ r = pthread_cond_wait(cond, mutex);
1929
+
1930
+ /* Workaround for a bug in OS X at least up to 13.6
1931
+ * See https://github.com/libuv/libuv/issues/4165
1932
+ */
1933
+ if (r == EINVAL && errno == EBUSY)
1934
+ return;
1935
+ if (r)
1936
+ abort();
1937
+ #else
1938
+ if (pthread_cond_wait(cond, mutex))
1939
+ abort();
1940
+ #endif
1941
+ }
1942
+
1943
+ static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
1944
+ int r;
1945
+ struct timespec ts;
1946
+
1947
+ #if !defined(__APPLE__)
1948
+ timeout += js__hrtime_ns();
1949
+ #endif
1950
+
1951
+ ts.tv_sec = timeout / NANOSEC;
1952
+ ts.tv_nsec = timeout % NANOSEC;
1953
+ #if defined(__APPLE__) && defined(__MACH__)
1954
+ r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
1955
+ #else
1956
+ r = pthread_cond_timedwait(cond, mutex, &ts);
1957
+ #endif
1958
+
1959
+ if (r == 0)
1960
+ return 0;
1961
+
1962
+ if (r == ETIMEDOUT)
1963
+ return -1;
1964
+
1965
+ abort();
1966
+
1967
+ /* Pacify some compilers. */
1968
+ return -1;
1969
+ }
1970
+
1971
+ static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
1972
+ int flags)
1973
+ {
1974
+ union {
1975
+ void (*x)(void *);
1976
+ void *(*f)(void *);
1977
+ } u = {start};
1978
+ pthread_attr_t attr;
1979
+ int ret;
1980
+
1981
+ if (flags & ~JS_THREAD_CREATE_DETACHED)
1982
+ return -1;
1983
+ if (pthread_attr_init(&attr))
1984
+ return -1;
1985
+ ret = -1;
1986
+ if (pthread_attr_setstacksize(&attr, 2<<20))
1987
+ goto fail;
1988
+ if (flags & JS_THREAD_CREATE_DETACHED)
1989
+ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
1990
+ goto fail;
1991
+ if (pthread_create(thrd, &attr, u.f, arg))
1992
+ goto fail;
1993
+ ret = 0;
1994
+ fail:
1995
+ pthread_attr_destroy(&attr);
1996
+ return ret;
1997
+ }
1998
+
1999
+ static inline int js_thread_join(js_thread_t thrd)
2000
+ {
2001
+ if (pthread_join(thrd, NULL))
2002
+ return -1;
2003
+ return 0;
2004
+ }
2005
+
2006
+ #endif /* !defined(_WIN32) */
2007
+ #endif /* JS_HAVE_THREADS */
2008
+
2009
+ #ifdef __cplusplus
2010
+ } /* extern "C" { */
2011
+ #endif
2012
+
2013
+ #endif /* CUTILS_H */