@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.
- package/README.md +55 -0
- package/dist/zapp-cli.js +9471 -0
- package/native/src/app/app.zc +490 -0
- package/native/src/event/event.zc +24 -0
- package/native/src/event/events.zc +70 -0
- package/native/src/platform/darwin/backend.zc +923 -0
- package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
- package/native/src/platform/darwin/bootstrap.zc +9 -0
- package/native/src/platform/darwin/engine_jsc.zc +86 -0
- package/native/src/platform/darwin/engine_qjs.zc +92 -0
- package/native/src/platform/darwin/platform.zc +156 -0
- package/native/src/platform/darwin/webview.zc +550 -0
- package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
- package/native/src/platform/darwin/window.zc +1223 -0
- package/native/src/platform/darwin/worker/common.zc +223 -0
- package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
- package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
- package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
- package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
- package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
- package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
- package/native/src/platform/darwin/worker/dispatch.zc +55 -0
- package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
- package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
- package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
- package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
- package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
- package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
- package/native/src/platform/darwin/worker/jsc.zc +670 -0
- package/native/src/platform/darwin/worker/mod.zc +30 -0
- package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
- package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
- package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
- package/native/src/platform/darwin/worker/qjs.zc +1053 -0
- package/native/src/platform/darwin/worker/timers.zc +149 -0
- package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
- package/native/src/platform/platform.zc +64 -0
- package/native/src/platform/shared/log.zc +156 -0
- package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
- package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
- package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
- package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
- package/native/src/platform/shared/worker_registry.zc +206 -0
- package/native/src/platform/window.zc +446 -0
- package/native/src/platform/windows/backend.zc +452 -0
- package/native/src/platform/windows/backend_bootstrap.zc +9 -0
- package/native/src/platform/windows/bootstrap.zc +9 -0
- package/native/src/platform/windows/engine_qjs.zc +60 -0
- package/native/src/platform/windows/platform.zc +387 -0
- package/native/src/platform/windows/webview.zc +1175 -0
- package/native/src/platform/windows/webview_bootstrap.zc +9 -0
- package/native/src/platform/windows/window.zc +1271 -0
- package/native/src/platform/windows/worker/common.zc +409 -0
- package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
- package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
- package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
- package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
- package/native/src/platform/windows/worker/core/url_core.zc +216 -0
- package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
- package/native/src/platform/windows/worker/dispatch.zc +34 -0
- package/native/src/platform/windows/worker/mod.zc +46 -0
- package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
- package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
- package/native/src/platform/windows/worker/qjs.zc +1049 -0
- package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
- package/native/src/platform/worker.zc +8 -0
- package/native/src/service/service.zc +228 -0
- package/native/vendor/quickjs-ng/.gitattributes +4 -0
- package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
- package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
- package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
- package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
- package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
- package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
- package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
- package/native/vendor/quickjs-ng/.gitmodules +5 -0
- package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
- package/native/vendor/quickjs-ng/LICENSE +24 -0
- package/native/vendor/quickjs-ng/Makefile +149 -0
- package/native/vendor/quickjs-ng/amalgam.js +53 -0
- package/native/vendor/quickjs-ng/api-test.c +927 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
- package/native/vendor/quickjs-ng/ctest.c +17 -0
- package/native/vendor/quickjs-ng/cutils.h +2013 -0
- package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
- package/native/vendor/quickjs-ng/dtoa.c +1619 -0
- package/native/vendor/quickjs-ng/dtoa.h +87 -0
- package/native/vendor/quickjs-ng/examples/fib.c +67 -0
- package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
- package/native/vendor/quickjs-ng/examples/hello.js +1 -0
- package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
- package/native/vendor/quickjs-ng/examples/meson.build +17 -0
- package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
- package/native/vendor/quickjs-ng/examples/point.c +154 -0
- package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
- package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
- package/native/vendor/quickjs-ng/fuzz.c +51 -0
- package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
- package/native/vendor/quickjs-ng/gen/hello.c +53 -0
- package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
- package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
- package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
- package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
- package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
- package/native/vendor/quickjs-ng/libregexp.c +2687 -0
- package/native/vendor/quickjs-ng/libregexp.h +98 -0
- package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
- package/native/vendor/quickjs-ng/libunicode.c +1746 -0
- package/native/vendor/quickjs-ng/libunicode.h +126 -0
- package/native/vendor/quickjs-ng/list.h +107 -0
- package/native/vendor/quickjs-ng/lre-test.c +73 -0
- package/native/vendor/quickjs-ng/meson.build +684 -0
- package/native/vendor/quickjs-ng/meson_options.txt +6 -0
- package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
- package/native/vendor/quickjs-ng/qjs.c +748 -0
- package/native/vendor/quickjs-ng/qjsc.c +673 -0
- package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
- package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
- package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
- package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
- package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
- package/native/vendor/quickjs-ng/quickjs.c +60259 -0
- package/native/vendor/quickjs-ng/quickjs.h +1419 -0
- package/native/vendor/quickjs-ng/repl.js +1927 -0
- package/native/vendor/quickjs-ng/run-test262.c +2417 -0
- package/native/vendor/quickjs-ng/standalone.js +129 -0
- package/native/vendor/quickjs-ng/tests/assert.js +49 -0
- package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
- package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
- package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
- package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
- package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
- package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
- package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
- package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
- package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
- package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
- package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
- package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
- package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
- package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
- package/native/vendor/quickjs-ng/tests/empty.js +0 -0
- package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
- package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
- package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
- package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
- package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
- package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
- package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
- package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
- package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
- package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
- package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
- package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
- package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
- package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
- package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
- package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
- package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
- package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
- package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
- package/native/vendor/quickjs-ng/tests.conf +14 -0
- package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
- package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
- package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
- package/native/vendor/quickjs-ng/update-version.sh +32 -0
- package/native/vendor/webview2/include/WebView2.h +60636 -0
- package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
- package/package.json +33 -0
- package/src/backend.ts +139 -0
- package/src/build-config.ts +87 -0
- package/src/build.ts +276 -0
- package/src/common.ts +195 -0
- package/src/config.ts +89 -0
- package/src/dev.ts +164 -0
- package/src/generate.ts +200 -0
- package/src/icons.ts +116 -0
- package/src/init.ts +190 -0
- package/src/package.ts +150 -0
- 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 */
|