mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-10 04:06:38 +00:00
Compare commits
244 Commits
HookAdmini
...
jshooks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ad6701757 | ||
|
|
176d7a1a0c | ||
|
|
ebfbb8a900 | ||
|
|
a94e8b9536 | ||
|
|
13910b23a4 | ||
|
|
6385c56832 | ||
|
|
3c879c7288 | ||
|
|
101ad3cb7e | ||
|
|
21a5e82fad | ||
|
|
c44b50b98c | ||
|
|
444152d077 | ||
|
|
d8c9e89043 | ||
|
|
285ea1d4e6 | ||
|
|
b619d03b22 | ||
|
|
34fd31dabe | ||
|
|
a6c4e39235 | ||
|
|
50a6499112 | ||
|
|
429f3289d8 | ||
|
|
257c46ec9c | ||
|
|
637d626518 | ||
|
|
cce9d372e7 | ||
|
|
aa571df467 | ||
|
|
ae8f6a16ed | ||
|
|
64441f7f40 | ||
|
|
0bf50c5dc7 | ||
|
|
8b0592ce06 | ||
|
|
c27e2a9c05 | ||
|
|
f8d22bbc24 | ||
|
|
95ab35a185 | ||
|
|
313ad7134b | ||
|
|
859dcbcabf | ||
|
|
a8e9448b1a | ||
|
|
cab4d63a07 | ||
|
|
9a90a7ffdc | ||
|
|
ddbbe91e5a | ||
|
|
2d9ac91cd1 | ||
|
|
9532ea7dec | ||
|
|
ed243745f8 | ||
|
|
5eac2d3e44 | ||
|
|
245cf4a676 | ||
|
|
864734f607 | ||
|
|
689740d818 | ||
|
|
a8c80e99c0 | ||
|
|
486003f1a8 | ||
|
|
c9f0fe02a1 | ||
|
|
a9c096e59c | ||
|
|
a83a157058 | ||
|
|
5e255e560f | ||
|
|
c953ee326d | ||
|
|
053a10a236 | ||
|
|
c53dcf1422 | ||
|
|
34b148bda0 | ||
|
|
19111a3739 | ||
|
|
3f98c15910 | ||
|
|
942227f8c3 | ||
|
|
e9461c827c | ||
|
|
3d9423dda6 | ||
|
|
5d41688e36 | ||
|
|
9bd6d2244e | ||
|
|
48919f028c | ||
|
|
46d745b43f | ||
|
|
5365bbcfe8 | ||
|
|
9c26f1f213 | ||
|
|
69b7728b2d | ||
|
|
15b679b1a7 | ||
|
|
9178aa9d8a | ||
|
|
17fdd09640 | ||
|
|
40dc69d642 | ||
|
|
e8560c2198 | ||
|
|
ca7533c14a | ||
|
|
eba913a68e | ||
|
|
ec849e0899 | ||
|
|
314fb6c9e0 | ||
|
|
643cd9fef1 | ||
|
|
3593d67df9 | ||
|
|
5571827be2 | ||
|
|
cfbfd762e8 | ||
|
|
c25fd875a8 | ||
|
|
043f1e96b6 | ||
|
|
17dfca6e61 | ||
|
|
74681718dd | ||
|
|
167417bfed | ||
|
|
2dd22648e8 | ||
|
|
e89aa05a2a | ||
|
|
8a5ccbf870 | ||
|
|
f6f87e468a | ||
|
|
d7167a9ebe | ||
|
|
7446dddddb | ||
|
|
d9388e1e51 | ||
|
|
73c1748241 | ||
|
|
58e3840345 | ||
|
|
61135c0ecb | ||
|
|
42a44d0cb8 | ||
|
|
d37039897e | ||
|
|
2061d6d44c | ||
|
|
8ea35ace02 | ||
|
|
a203314c68 | ||
|
|
092a29cd18 | ||
|
|
1ba18875ac | ||
|
|
2da58fe18f | ||
|
|
8d7cc68bda | ||
|
|
b73dd584e7 | ||
|
|
0726789d77 | ||
|
|
05bd9c6ea8 | ||
|
|
f9e7ea95fd | ||
|
|
618a933241 | ||
|
|
752dbf34ee | ||
|
|
fcf3848814 | ||
|
|
e4a6aecc18 | ||
|
|
1c4ebfe3ad | ||
|
|
f97165e4bc | ||
|
|
fc50c0fb0a | ||
|
|
1b12b400d7 | ||
|
|
f3ee0dd322 | ||
|
|
d9659dc226 | ||
|
|
fb7af36cef | ||
|
|
4bfe27d11f | ||
|
|
eaa2cc9e5c | ||
|
|
6aa1ff87b9 | ||
|
|
5ef3795cea | ||
|
|
da5f1d189b | ||
|
|
6fdf788b13 | ||
|
|
61f45055a7 | ||
|
|
f9e7fed929 | ||
|
|
5cfe566489 | ||
|
|
04409616ed | ||
|
|
ca04c2a802 | ||
|
|
f868b4d6e6 | ||
|
|
5502453de8 | ||
|
|
359ab70ba0 | ||
|
|
d82f60705d | ||
|
|
15515b84f8 | ||
|
|
8b29fc5ee1 | ||
|
|
92be8146e8 | ||
|
|
c0f55d0b00 | ||
|
|
802ea6c568 | ||
|
|
ecc779346e | ||
|
|
680c6095d4 | ||
|
|
6858861660 | ||
|
|
9faef17407 | ||
|
|
ee68cc2cd2 | ||
|
|
7c360bad33 | ||
|
|
26a66bc2ef | ||
|
|
4b93e1657f | ||
|
|
cd45285cab | ||
|
|
b7acfb9803 | ||
|
|
97a10d6556 | ||
|
|
fe43029272 | ||
|
|
bf33b6f637 | ||
|
|
c27518b846 | ||
|
|
7d8f5de93d | ||
|
|
858ea1bf25 | ||
|
|
7162fe0497 | ||
|
|
56c0e0dd5f | ||
|
|
20ca066454 | ||
|
|
171610d1a9 | ||
|
|
2f6cf0ab4b | ||
|
|
71884ad48a | ||
|
|
799a056313 | ||
|
|
eec61f16c9 | ||
|
|
1bed7f1196 | ||
|
|
211e63c568 | ||
|
|
81413a5ce8 | ||
|
|
36d630bed3 | ||
|
|
4f901788f4 | ||
|
|
72e773cbff | ||
|
|
39ec8fb901 | ||
|
|
534870f2f0 | ||
|
|
db245d237c | ||
|
|
f3118ef8fa | ||
|
|
ee21449757 | ||
|
|
9e7bee5564 | ||
|
|
8cb2bbb693 | ||
|
|
c240c1553b | ||
|
|
a498ebeac4 | ||
|
|
b13cab4ced | ||
|
|
783bff75a0 | ||
|
|
c1610a6dda | ||
|
|
f829a79d54 | ||
|
|
f35704c91f | ||
|
|
9db9ad2123 | ||
|
|
f96daa0014 | ||
|
|
5c7ec5f36f | ||
|
|
c662a8b0d2 | ||
|
|
a983120b5d | ||
|
|
f12b8cbb2d | ||
|
|
f591290589 | ||
|
|
f2becaf140 | ||
|
|
e4c6add794 | ||
|
|
78280e4b8c | ||
|
|
178fdbaff6 | ||
|
|
34d7435ff3 | ||
|
|
6429ec609d | ||
|
|
bea1697baa | ||
|
|
2b111b7f23 | ||
|
|
5254595063 | ||
|
|
52456a2d51 | ||
|
|
b340824711 | ||
|
|
f5bb779f61 | ||
|
|
bf99a1b05d | ||
|
|
d1e5eb87f5 | ||
|
|
b650d72f0b | ||
|
|
7567277dd8 | ||
|
|
13719a1357 | ||
|
|
033dedf979 | ||
|
|
6973540d52 | ||
|
|
c9dcff90fa | ||
|
|
71675c4fed | ||
|
|
70bc2d3283 | ||
|
|
c4d0fc0e0f | ||
|
|
5d61eea709 | ||
|
|
f4ffe4a3e0 | ||
|
|
59ecbd9932 | ||
|
|
6c3da46a1b | ||
|
|
46308e33b0 | ||
|
|
1f7355719d | ||
|
|
7cc395b284 | ||
|
|
a634318e8d | ||
|
|
82e754d180 | ||
|
|
9e72931bbb | ||
|
|
842a0388d1 | ||
|
|
280ba7d5de | ||
|
|
7b0bc67242 | ||
|
|
8e172e1846 | ||
|
|
7497d619bf | ||
|
|
34a159b662 | ||
|
|
663910c78a | ||
|
|
40b9aa7aed | ||
|
|
ec7d603bf9 | ||
|
|
f9137000e3 | ||
|
|
c3cf4b5999 | ||
|
|
6954abdd04 | ||
|
|
38a4b3c1b9 | ||
|
|
7e12b46169 | ||
|
|
4e91d5887f | ||
|
|
f051b87176 | ||
|
|
98d39db305 | ||
|
|
80df3adac7 | ||
|
|
a2c3567caf | ||
|
|
206773dcf4 | ||
|
|
54c00d0364 | ||
|
|
71a6f9c4d5 | ||
|
|
9ab33d580d | ||
|
|
0bd65bbb56 |
31
.codecov.yml
31
.codecov.yml
@@ -1,37 +1,6 @@
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
|
||||
comment:
|
||||
behavior: default
|
||||
layout: reach,diff,flags,tree,reach
|
||||
show_carryforward_flags: false
|
||||
|
||||
coverage:
|
||||
range: "60..80"
|
||||
precision: 1
|
||||
round: nearest
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 60%
|
||||
threshold: 2%
|
||||
patch:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 2%
|
||||
changes: false
|
||||
|
||||
github_checks:
|
||||
annotations: true
|
||||
|
||||
parsers:
|
||||
cobertura:
|
||||
partials_as_hits: true
|
||||
handle_missing_conditions : true
|
||||
|
||||
slack_app: false
|
||||
|
||||
ignore:
|
||||
- "src/test/"
|
||||
- "include/xrpl/beast/test/"
|
||||
- "include/xrpl/beast/unit_test/"
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
# This feature requires Git >= 2.24
|
||||
# To use it by default in git blame:
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
# Format first-party source according to .clang-format
|
||||
50760c693510894ca368e90369b0cc2dabfd07f3
|
||||
# Reintroduce Clang-Format & Levelization
|
||||
da1d20d6d5d862716125d60899b80fab5302954a
|
||||
# Consolidate external libraries
|
||||
da1d20d6d5d862716125d60899b80fab5302954a
|
||||
# Rename .hpp to .h
|
||||
0345a2645d0f5ad900f4fbbcaff96040d3a887fc
|
||||
# Format formerly .hpp files
|
||||
5a227dc719016e10045e17c9396ad401118044f1
|
||||
# Rewrite includes
|
||||
e61880699997398f5a746e6c4034edc7632661f5
|
||||
# Move CMake directory (#4997)
|
||||
e47b1c1b3b97c3f6d11858ee02f463596e29e7f0
|
||||
# Rearrange sources (#4997)
|
||||
bfafa2bb39e562901736d656806bd700c3699a2f
|
||||
# Rewrite includes (#4997)
|
||||
e61880699997398f5a746e6c4034edc7632661f5
|
||||
# Recompute loops (#4997)
|
||||
d25b5dcd568bb96c18e347d55fac10fe901a1bfb
|
||||
# Reformat code with clang-format-18
|
||||
02749feea88ce61c1f7eeb2d61a57d8ecf07ab11
|
||||
e2384885f5f630c8f0ffe4bf21a169b433a16858
|
||||
241b9ddde9e11beb7480600fd5ed90e1ef109b21
|
||||
760f16f56835663d9286bd29294d074de26a7ba6
|
||||
0eebe6a5f4246fced516d52b83ec4e7f47373edd
|
||||
|
||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -11,3 +11,6 @@ LICENSE binary
|
||||
*.vcxproj text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.filters text eol=crlf
|
||||
|
||||
# Mark it as generated and folded out by default
|
||||
src/test/app/SetJSHook_wasm.h linguist-generated=true
|
||||
2
.github/workflows/clang-format.yml
vendored
2
.github/workflows/clang-format.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-format-${CLANG_VERSION}
|
||||
- name: Format first-party sources
|
||||
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -not -path "src/quickjs/*" -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
- name: Check for differences
|
||||
id: assert
|
||||
run: |
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -124,6 +124,8 @@ pkg
|
||||
CMakeUserPresets.json
|
||||
bld.rippled/
|
||||
|
||||
# binary
|
||||
qjsc
|
||||
generated
|
||||
.vscode
|
||||
|
||||
|
||||
@@ -84,7 +84,6 @@ test.nodestore > xrpl.basics
|
||||
test.nodestore > xrpld.core
|
||||
test.nodestore > xrpld.nodestore
|
||||
test.nodestore > xrpld.unity
|
||||
test.nodestore > xrpl.protocol
|
||||
test.overlay > test.jtx
|
||||
test.overlay > test.toplevel
|
||||
test.overlay > test.unit_test
|
||||
@@ -119,7 +118,6 @@ test.rpc > xrpld.core
|
||||
test.rpc > xrpld.net
|
||||
test.rpc > xrpld.overlay
|
||||
test.rpc > xrpld.rpc
|
||||
test.rpc > xrpld.shamap
|
||||
test.rpc > xrpl.hook
|
||||
test.rpc > xrpl.json
|
||||
test.rpc > xrpl.protocol
|
||||
@@ -152,6 +150,7 @@ xrpl.resource > xrpl.protocol
|
||||
xrpl.server > xrpl.basics
|
||||
xrpl.server > xrpl.json
|
||||
xrpl.server > xrpl.protocol
|
||||
xrpld.app > quickjs.toplevel
|
||||
xrpld.app > test.unit_test
|
||||
xrpld.app > xrpl.basics
|
||||
xrpld.app > xrpld.conditions
|
||||
|
||||
@@ -145,6 +145,8 @@ target_link_libraries(ripple_libs INTERFACE
|
||||
SQLite::SQLite3
|
||||
)
|
||||
|
||||
include(deps/quickjs)
|
||||
|
||||
if(coverage)
|
||||
include(RippledCov)
|
||||
endif()
|
||||
|
||||
@@ -12,16 +12,17 @@ echo "-- GITHUB_REPOSITORY: $1"
|
||||
echo "-- GITHUB_SHA: $2"
|
||||
echo "-- GITHUB_RUN_NUMBER: $4"
|
||||
|
||||
umask 0000
|
||||
umask 0000;
|
||||
|
||||
####
|
||||
|
||||
cd /io
|
||||
mkdir -p src/certs
|
||||
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o src/certs/certbundle.h
|
||||
if [ "$(grep certbundle.h src/xrpld/net/detail/RegisterSSLCerts.cpp | wc -l)" -eq "0" ]; then
|
||||
cp src/xrpld/net/detail/RegisterSSLCerts.cpp src/xrpld/net/detail/RegisterSSLCerts.cpp.old
|
||||
perl -i -pe "s/^{/{
|
||||
cd /io;
|
||||
mkdir -p src/certs;
|
||||
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o src/certs/certbundle.h;
|
||||
if [ "`grep certbundle.h src/xrpld/net/detail/RegisterSSLCerts.cpp | wc -l`" -eq "0" ]
|
||||
then
|
||||
cp src/xrpld/net/detail/RegisterSSLCerts.cpp src/xrpld/net/detail/RegisterSSLCerts.cpp.old
|
||||
perl -i -pe "s/^{/{
|
||||
#ifdef EMBEDDED_CA_BUNDLE
|
||||
BIO *cbio = BIO_new_mem_buf(ca_bundle.data(), ca_bundle.size());
|
||||
X509_STORE *cts = SSL_CTX_get_cert_store(ctx.native_handle());
|
||||
@@ -67,14 +68,15 @@ fi
|
||||
source /opt/rh/gcc-toolset-11/enable
|
||||
export PATH=/usr/local/bin:$PATH
|
||||
export CC='/usr/lib64/ccache/gcc' &&
|
||||
export CXX='/usr/lib64/ccache/g++' &&
|
||||
echo "-- Build Rippled --" &&
|
||||
pwd &&
|
||||
echo "MOVING TO [ build-core.sh ]"
|
||||
export CXX='/usr/lib64/ccache/g++' &&
|
||||
echo "-- Build Rippled --" &&
|
||||
pwd &&
|
||||
|
||||
printenv >.env.temp
|
||||
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g | sed s/\$/\\\"/g >.env
|
||||
rm .env.temp
|
||||
echo "MOVING TO [ build-core.sh ]";
|
||||
|
||||
printenv > .env.temp;
|
||||
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g|sed s/\$/\\\"/g > .env;
|
||||
rm .env.temp;
|
||||
|
||||
echo "Persisting ENV:"
|
||||
cat .env
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
"3C43D9A973AA4443EF3FC38E42DD306160FBFFDAB901CD8BAA15D09F2597EB87",
|
||||
"0285B7E5E08E1A8E4C15636F0591D87F73CB6A7B6452A932AD72BBC8E5D1CBE3",
|
||||
"6E739F4F8B07BED29FC9FF440DA3C301CD14A180DF45819F658FEC2F7DE31427",
|
||||
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6"
|
||||
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6",
|
||||
"DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536"
|
||||
],
|
||||
"Flags": 0,
|
||||
"LedgerEntryType": "Amendments",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# standalone: ./xahaud -a --ledgerfile config/genesis.json --conf config/xahaud-standalone.cfg
|
||||
# standalone: ./xahaud -a --ledgerfile cfg/genesis.json --conf cfg/xahaud-standalone.cfg
|
||||
[server]
|
||||
port_rpc_admin_local
|
||||
port_ws_public
|
||||
@@ -154,3 +154,4 @@ D686F2538F410C9D0D856788E98E3579595DAF7B38D38887F81ECAC934B06040 HooksUpdate1
|
||||
EDB4EE4C524E16BDD91D9A529332DED08DCAAA51CC6DC897ACFA1A0ED131C5B6 fix240819
|
||||
8063140E9260799D6716756B891CEC3E7006C4E4F277AB84670663A88F94B9C4 fixPageCap
|
||||
88693F108C3CD8A967F3F4253A32DEF5E35F9406ACD2A11B88B11D90865763A9 fix240911
|
||||
DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536 JsHooks
|
||||
|
||||
@@ -95,9 +95,6 @@
|
||||
# - replace both functions setup_target_for_coverage_gcovr_* with a single setup_target_for_coverage_gcovr
|
||||
# - add support for all gcovr output formats
|
||||
#
|
||||
# 2024-04-03, Bronek Kozicki
|
||||
# - add support for output formats: jacoco, clover, lcov
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
@@ -259,10 +256,10 @@ endif()
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# FORMAT "cobertura" # Output format, one of:
|
||||
# # xml cobertura sonarqube jacoco clover
|
||||
# # json-summary json-details coveralls csv
|
||||
# # txt html-single html-nested html-details
|
||||
# # lcov (xml is an alias to cobertura;
|
||||
# # xml cobertura sonarqube json-summary
|
||||
# # json-details coveralls csv txt
|
||||
# # html-single html-nested html-details
|
||||
# # (xml is an alias to cobertura;
|
||||
# # if no format is set, defaults to xml)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
@@ -311,8 +308,6 @@ function(setup_target_for_coverage_gcovr)
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
|
||||
elseif(Coverage_FORMAT STREQUAL "csv")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
|
||||
elseif(Coverage_FORMAT STREQUAL "lcov")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
|
||||
else()
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
|
||||
endif()
|
||||
@@ -325,14 +320,6 @@ function(setup_target_for_coverage_gcovr)
|
||||
set(Coverage_FORMAT cobertura) # overwrite xml
|
||||
elseif(Coverage_FORMAT STREQUAL "sonarqube")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}" )
|
||||
elseif(Coverage_FORMAT STREQUAL "jacoco")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}" )
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty )
|
||||
elseif(Coverage_FORMAT STREQUAL "clover")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}" )
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty )
|
||||
elseif(Coverage_FORMAT STREQUAL "lcov")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}" )
|
||||
elseif(Coverage_FORMAT STREQUAL "json-summary")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}" )
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
|
||||
|
||||
@@ -58,6 +58,7 @@ target_link_libraries(xrpl.imports.main
|
||||
OpenSSL::Crypto
|
||||
Ripple::boost
|
||||
wasmedge::wasmedge
|
||||
NIH::quickjs
|
||||
Ripple::opts
|
||||
Ripple::syslibs
|
||||
absl::random_random
|
||||
|
||||
@@ -6,6 +6,7 @@ include(create_symbolic_link)
|
||||
|
||||
install (
|
||||
TARGETS
|
||||
quickjs
|
||||
common
|
||||
opts
|
||||
ripple_syslibs
|
||||
|
||||
52
cmake/deps/quickjs.cmake
Normal file
52
cmake/deps/quickjs.cmake
Normal file
@@ -0,0 +1,52 @@
|
||||
# QuickJS source files
|
||||
set(QUICKJS_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libutf.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/qsort_r.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/tutf8e.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/vector.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/char-utils.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/buffer-utils.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/utils.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/ringbuffer.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libregexp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libregexp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libunicode.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/cutils.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-libc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libbf.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-textcode.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-internal.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/debug.c
|
||||
)
|
||||
|
||||
# QuickJS include directories
|
||||
set(QUICKJS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs)
|
||||
|
||||
# RHTODO: Fix this to be dynamic
|
||||
set(QUICKJS_VERSION "2023-01-01")
|
||||
|
||||
# QuickJS compile definitions
|
||||
set(QUICKJS_COMPILE_DEFINITIONS
|
||||
_GNU_SOURCE
|
||||
CONFIG_VERSION="${QUICKJS_VERSION}"
|
||||
CONFIG_BIGNUM
|
||||
)
|
||||
|
||||
# Create static library
|
||||
add_library(quickjs STATIC ${QUICKJS_SOURCES})
|
||||
target_include_directories(quickjs
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${QUICKJS_INCLUDE_DIRS}>
|
||||
$<INSTALL_INTERFACE:include/quickjs>
|
||||
)
|
||||
target_compile_definitions(quickjs PUBLIC ${QUICKJS_COMPILE_DEFINITIONS})
|
||||
|
||||
add_library(NIH::quickjs ALIAS quickjs)
|
||||
target_link_libraries(ripple_libs INTERFACE NIH::quickjs)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/*.h
|
||||
DESTINATION include/quickjs
|
||||
)
|
||||
@@ -2,9 +2,6 @@
|
||||
// Generated using generate_extern.sh
|
||||
#include <stdint.h>
|
||||
#ifndef HOOK_EXTERN
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int32_t __attribute__((noduplicate))
|
||||
_g(uint32_t guard_id, uint32_t maxiter);
|
||||
@@ -339,8 +336,5 @@ prepare(
|
||||
uint32_t read_ptr,
|
||||
uint32_t read_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define HOOK_EXTERN
|
||||
#endif // HOOK_EXTERN
|
||||
|
||||
@@ -9,7 +9,7 @@ ENUM_FILE="$SCRIPT_DIR/../include/xrpl/hook/Enum.h"
|
||||
echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/'
|
||||
echo '// Generated using generate_error.sh'
|
||||
echo '#ifndef HOOK_ERROR_CODES'
|
||||
sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
|
||||
sed -n '/enum hook_return_code/,/};/p' "$ENUM_FILE" |
|
||||
awk '
|
||||
function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
|
||||
function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s }
|
||||
@@ -31,7 +31,7 @@ sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
|
||||
|
||||
{
|
||||
line = $0
|
||||
if (line ~ /enum[[:space:]]+class[[:space:]]+hook_return_code/)
|
||||
if (line ~ /enum[[:space:]]+hook_return_code/)
|
||||
next
|
||||
if (line ~ /^[[:space:]]*\{/)
|
||||
next
|
||||
|
||||
@@ -11,9 +11,6 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
|
||||
echo '// Generated using generate_extern.sh'
|
||||
echo '#include <stdint.h>'
|
||||
echo '#ifndef HOOK_EXTERN'
|
||||
echo '#ifdef __cplusplus'
|
||||
echo 'extern "C" {'
|
||||
echo '#endif'
|
||||
echo
|
||||
awk '
|
||||
function trim(s) {
|
||||
@@ -30,8 +27,8 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
|
||||
next;
|
||||
}
|
||||
|
||||
# Look for comment lines that start with // and contain function signature
|
||||
if (line ~ /^[[:space:]]*\/\/[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) {
|
||||
# Look for comment lines that start with // int64_t or // int32_t
|
||||
if (line ~ /^[[:space:]]*\/\/[[:space:]]*(int64_t|int32_t)[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) {
|
||||
# Remove leading // and trim
|
||||
sub(/^[[:space:]]*\/\/[[:space:]]*/, "", line);
|
||||
line = trim(line);
|
||||
@@ -49,9 +46,6 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
|
||||
}
|
||||
' "$APPLY_HOOK"
|
||||
|
||||
echo '#ifdef __cplusplus'
|
||||
echo '}'
|
||||
echo '#endif'
|
||||
echo '#define HOOK_EXTERN'
|
||||
echo '#endif // HOOK_EXTERN'
|
||||
} | (
|
||||
|
||||
@@ -189,7 +189,6 @@
|
||||
#define sfSignatureReward ((6U << 16U) + 29U)
|
||||
#define sfMinAccountCreateAmount ((6U << 16U) + 30U)
|
||||
#define sfLPTokenBalance ((6U << 16U) + 31U)
|
||||
#define sfTrustLineRewardAccumulator ((6U << 16U) + 99U)
|
||||
#define sfPublicKey ((7U << 16U) + 1U)
|
||||
#define sfMessageKey ((7U << 16U) + 2U)
|
||||
#define sfSigningPubKey ((7U << 16U) + 3U)
|
||||
@@ -221,7 +220,6 @@
|
||||
#define sfProvider ((7U << 16U) + 30U)
|
||||
#define sfMPTokenMetadata ((7U << 16U) + 31U)
|
||||
#define sfCredentialType ((7U << 16U) + 32U)
|
||||
#define sfHookName ((7U << 16U) + 97U)
|
||||
#define sfRemarkValue ((7U << 16U) + 98U)
|
||||
#define sfRemarkName ((7U << 16U) + 99U)
|
||||
#define sfAccount ((8U << 16U) + 1U)
|
||||
@@ -242,7 +240,6 @@
|
||||
#define sfLockingChainDoor ((8U << 16U) + 22U)
|
||||
#define sfIssuingChainDoor ((8U << 16U) + 23U)
|
||||
#define sfSubject ((8U << 16U) + 24U)
|
||||
#define sfHookAdministrator ((8U << 16U) + 98U)
|
||||
#define sfInform ((8U << 16U) + 99U)
|
||||
#define sfIndexes ((19U << 16U) + 1U)
|
||||
#define sfHashes ((19U << 16U) + 2U)
|
||||
@@ -258,7 +255,6 @@
|
||||
#define sfIssuingChainIssue ((24U << 16U) + 2U)
|
||||
#define sfAsset ((24U << 16U) + 3U)
|
||||
#define sfAsset2 ((24U << 16U) + 4U)
|
||||
#define sfClaimCurrency ((24U << 16U) + 5U)
|
||||
#define sfXChainBridge ((25U << 16U) + 1U)
|
||||
#define sfTransactionMetaData ((14U << 16U) + 2U)
|
||||
#define sfCreatedNode ((14U << 16U) + 3U)
|
||||
@@ -296,8 +292,6 @@
|
||||
#define sfActiveValidator ((14U << 16U) + 95U)
|
||||
#define sfGenesisMint ((14U << 16U) + 96U)
|
||||
#define sfRemark ((14U << 16U) + 97U)
|
||||
#define sfHighReward ((14U << 16U) + 98U)
|
||||
#define sfLowReward ((14U << 16U) + 99U)
|
||||
#define sfSigners ((15U << 16U) + 3U)
|
||||
#define sfSignerEntries ((15U << 16U) + 4U)
|
||||
#define sfTemplate ((15U << 16U) + 5U)
|
||||
|
||||
@@ -100,10 +100,6 @@ enum NFTokenCreateOfferFlags : uint32_t {
|
||||
tfSellNFToken = 0x00000001,
|
||||
};
|
||||
|
||||
enum SetHookFlags : uint32_t {
|
||||
tfNewAccount = 0x00000001,
|
||||
};
|
||||
|
||||
enum ClaimRewardFlags : uint32_t {
|
||||
tfOptOut = 0x00000001,
|
||||
};
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define featureHooksUpdate1 "1"
|
||||
#define featureHooksUpdate2 "1"
|
||||
#define fix20250131 "1"
|
||||
#define fixGuardDepth32 "1"
|
||||
namespace hook_api {
|
||||
struct Rules
|
||||
{
|
||||
@@ -265,8 +264,11 @@ enum hook_log_code : uint16_t {
|
||||
SECTIONS_OUT_OF_SEQUENCE =
|
||||
85, // the wasm contained sections out of sequence
|
||||
CUSTOM_SECTION_DISALLOWED =
|
||||
86, // the wasm contained a custom section (id=0)
|
||||
INTERNAL_ERROR = 87, // an internal error described by the log text
|
||||
86, // the wasm contained a custom section (id=0)
|
||||
INTERNAL_ERROR = 87, // an internal error described by the log text
|
||||
JS_TEST_FAILURE = 88, // smoke test of js bytecode failed
|
||||
JS_FEE_MISSING = 89,
|
||||
JS_FEE_OUT_OF_RANGE = 90,
|
||||
// RH NOTE: only HookSet msgs got log codes, possibly all Hook log lines
|
||||
// should get a code?
|
||||
};
|
||||
@@ -320,7 +322,7 @@ namespace compare_mode {
|
||||
enum compare_mode : uint32_t { EQUAL = 1, LESS = 2, GREATER = 4 };
|
||||
}
|
||||
|
||||
enum class hook_return_code : int64_t {
|
||||
enum hook_return_code : int64_t {
|
||||
SUCCESS =
|
||||
0, // return codes > 0 are reserved for hook apis to return "success"
|
||||
OUT_OF_BOUNDS =
|
||||
@@ -387,11 +389,20 @@ enum class hook_return_code : int64_t {
|
||||
TOO_MANY_NAMESPACES = -45
|
||||
};
|
||||
|
||||
enum class ExitType : uint8_t {
|
||||
enum ExitType : uint8_t {
|
||||
UNSET = 0,
|
||||
WASM_ERROR = 1,
|
||||
ROLLBACK = 2,
|
||||
ACCEPT = 3,
|
||||
JSVM_ERROR = 4,
|
||||
LEDGER_ERROR =
|
||||
5, // if the ledger contained for example a nonsense hookapi number
|
||||
INSTRUCTION_LIMIT_REACHED = 6,
|
||||
};
|
||||
|
||||
enum CodeType : uint8_t {
|
||||
WASM = 0,
|
||||
JS = 1,
|
||||
};
|
||||
|
||||
const uint16_t max_state_modifications = 256;
|
||||
@@ -425,6 +436,10 @@ getImportWhitelist(Rules const& rules)
|
||||
if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \
|
||||
whitelist[#FUNCTION_NAME] = { \
|
||||
RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE};
|
||||
#define JSHOOK_API_DEFINITION( \
|
||||
RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \
|
||||
{ \
|
||||
}
|
||||
|
||||
#include "hook_api.macro"
|
||||
|
||||
@@ -444,7 +459,6 @@ getImportWhitelist(Rules const& rules)
|
||||
|
||||
enum GuardRulesVersion : uint64_t {
|
||||
GuardRuleFix20250131 = 0x00000001,
|
||||
GuardRuleDepth32 = 0x00000002,
|
||||
};
|
||||
|
||||
inline uint64_t
|
||||
@@ -453,8 +467,6 @@ getGuardRulesVersion(Rules const& rules)
|
||||
uint64_t version = 0;
|
||||
if (rules.enabled(fix20250131))
|
||||
version |= GuardRuleFix20250131;
|
||||
if (rules.enabled(fixGuardDepth32))
|
||||
version |= GuardRuleDepth32;
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,13 +204,9 @@ struct WasmBlkInf
|
||||
}
|
||||
// compute worst case execution time
|
||||
inline uint64_t
|
||||
compute_wce(
|
||||
const WasmBlkInf* blk,
|
||||
int level,
|
||||
int max_level,
|
||||
bool* recursion_limit_reached)
|
||||
compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached)
|
||||
{
|
||||
if (level > max_level)
|
||||
if (level > 16)
|
||||
{
|
||||
*recursion_limit_reached = true;
|
||||
return 0;
|
||||
@@ -237,8 +233,8 @@ compute_wce(
|
||||
|
||||
if (blk->children.size() > 0)
|
||||
for (auto const& child : blk->children)
|
||||
worst_case_execution += compute_wce(
|
||||
child, level + 1, max_level, recursion_limit_reached);
|
||||
worst_case_execution +=
|
||||
compute_wce(child, level + 1, recursion_limit_reached);
|
||||
|
||||
if (parent == 0 ||
|
||||
parent->iteration_bound ==
|
||||
@@ -792,17 +788,12 @@ check_guard(
|
||||
}
|
||||
|
||||
bool recursion_limit_reached = false;
|
||||
int max_level = 16;
|
||||
if (rulesVersion & hook_api::GuardRuleDepth32)
|
||||
max_level = 32;
|
||||
uint64_t wce =
|
||||
compute_wce(&(*root), 0, max_level, &recursion_limit_reached);
|
||||
uint64_t wce = compute_wce(&(*root), 0, &recursion_limit_reached);
|
||||
if (recursion_limit_reached)
|
||||
{
|
||||
GUARDLOG(hook::log::NESTING_LIMIT)
|
||||
<< "GuardCheck "
|
||||
<< "Maximum allowable depth of blocks reached (" << max_level
|
||||
<< " levels). Flatten "
|
||||
<< "Maximum allowable depth of blocks reached (16 levels). Flatten "
|
||||
"your loops and conditions!.\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#define SEP_int32_t LPAREN int32_t COMMA
|
||||
#define SEP_uint64_t LPAREN uint64_t COMMA
|
||||
#define SEP_int64_t LPAREN int64_t COMMA
|
||||
#define SEP_JSValue LPAREN JSValue COMMA
|
||||
|
||||
#define VAL_uint32_t WasmEdge_ValueGetI32(in[_stack++])
|
||||
#define VAL_int32_t WasmEdge_ValueGetI32(in[_stack++])
|
||||
@@ -89,69 +90,174 @@
|
||||
|
||||
#define WASM_VAL_TYPE(T, b) CAT2(TYP_, T)
|
||||
|
||||
#define UNSIGNED_TYPE(T) std::make_unsigned_t<T>
|
||||
#define HALF_COUNT(...) \
|
||||
HALF_COUNT_IMPL( \
|
||||
__VA_ARGS__, \
|
||||
16, \
|
||||
16, \
|
||||
15, \
|
||||
15, \
|
||||
14, \
|
||||
14, \
|
||||
13, \
|
||||
13, \
|
||||
12, \
|
||||
12, \
|
||||
11, \
|
||||
11, \
|
||||
10, \
|
||||
10, \
|
||||
9, \
|
||||
9, \
|
||||
8, \
|
||||
8, \
|
||||
7, \
|
||||
7, \
|
||||
6, \
|
||||
6, \
|
||||
5, \
|
||||
5, \
|
||||
4, \
|
||||
4, \
|
||||
3, \
|
||||
3, \
|
||||
2, \
|
||||
2, \
|
||||
1, \
|
||||
1, \
|
||||
0, \
|
||||
0)
|
||||
|
||||
#define DECLARE_HOOK_FUNCTION(R, F, ...) \
|
||||
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> F( \
|
||||
hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
|
||||
COMMA __VA_ARGS__)); \
|
||||
extern WasmEdge_Result WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out); \
|
||||
extern WasmEdge_ValType WasmFunctionParams##F[]; \
|
||||
extern WasmEdge_ValType WasmFunctionResult##F[]; \
|
||||
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
|
||||
#define HALF_COUNT_IMPL( \
|
||||
_1, \
|
||||
_2, \
|
||||
_3, \
|
||||
_4, \
|
||||
_5, \
|
||||
_6, \
|
||||
_7, \
|
||||
_8, \
|
||||
_9, \
|
||||
_10, \
|
||||
_11, \
|
||||
_12, \
|
||||
_13, \
|
||||
_14, \
|
||||
_15, \
|
||||
_16, \
|
||||
_17, \
|
||||
_18, \
|
||||
_19, \
|
||||
_20, \
|
||||
_21, \
|
||||
_22, \
|
||||
_23, \
|
||||
_24, \
|
||||
_25, \
|
||||
_26, \
|
||||
_27, \
|
||||
_28, \
|
||||
_29, \
|
||||
_30, \
|
||||
_31, \
|
||||
_32, \
|
||||
N, \
|
||||
...) \
|
||||
N
|
||||
|
||||
#define DECLARE_WASM_FUNCTION(R, F, ...) \
|
||||
R F(hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
|
||||
COMMA __VA_ARGS__)); \
|
||||
extern WasmEdge_Result WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out); \
|
||||
extern WasmEdge_ValType WasmFunctionParams##F[]; \
|
||||
extern WasmEdge_ValType WasmFunctionResult##F[]; \
|
||||
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
|
||||
extern WasmEdge_String WasmFunctionName##F;
|
||||
|
||||
#define DEFINE_HOOK_FUNCTION(R, F, ...) \
|
||||
WasmEdge_Result hook_api::WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out) \
|
||||
{ \
|
||||
__VA_OPT__(int _stack = 0;) \
|
||||
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
|
||||
hook::HookContext* hookCtx = \
|
||||
reinterpret_cast<hook::HookContext*>(data_ptr); \
|
||||
auto const& return_code = hook_api::F( \
|
||||
*hookCtx, \
|
||||
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
|
||||
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
|
||||
if (std::holds_alternative<hook_api::hook_return_code>(return_code) && \
|
||||
(std::get<hook_api::hook_return_code>(return_code) == \
|
||||
RC_ROLLBACK || \
|
||||
std::get<hook_api::hook_return_code>(return_code) == RC_ACCEPT)) \
|
||||
return WasmEdge_Result_Terminate; \
|
||||
out[0] = RET_ASSIGN( \
|
||||
R, \
|
||||
std::holds_alternative<UNSIGNED_TYPE(R)>(return_code) \
|
||||
? std::get<UNSIGNED_TYPE(R)>(return_code) \
|
||||
: R(std::get<hook_api::hook_return_code>(return_code))); \
|
||||
return WasmEdge_Result_Success; \
|
||||
}; \
|
||||
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
|
||||
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
|
||||
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
|
||||
WASM_VAL_TYPE(R, dummy)}; \
|
||||
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
|
||||
WasmEdge_FunctionTypeCreate( \
|
||||
WasmFunctionParams##F, \
|
||||
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
|
||||
WasmFunctionResult##F, \
|
||||
1); \
|
||||
WasmEdge_String hook_api::WasmFunctionName##F = \
|
||||
WasmEdge_StringCreateByCString(#F); \
|
||||
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> hook_api::F( \
|
||||
hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
|
||||
#define DECLARE_JS_FUNCTION(R, F, ...) \
|
||||
extern JSValue JSFunction##F( \
|
||||
JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); \
|
||||
const int JSFunctionParamCount##F = __VA_OPT__(HALF_COUNT(__VA_ARGS__) +) 0;
|
||||
|
||||
#define DEFINE_WASM_FUNCTION(R, F, ...) \
|
||||
WasmEdge_Result hook_api::WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out) \
|
||||
{ \
|
||||
__VA_OPT__(int _stack = 0;) \
|
||||
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
|
||||
hook::HookContext* hookCtx = \
|
||||
reinterpret_cast<hook::HookContext*>(data_ptr); \
|
||||
R return_code = hook_api::F( \
|
||||
*hookCtx, \
|
||||
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
|
||||
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
|
||||
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \
|
||||
return WasmEdge_Result_Terminate; \
|
||||
out[0] = RET_ASSIGN(R, return_code); \
|
||||
return WasmEdge_Result_Success; \
|
||||
}; \
|
||||
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
|
||||
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
|
||||
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
|
||||
WASM_VAL_TYPE(R, dummy)}; \
|
||||
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
|
||||
WasmEdge_FunctionTypeCreate( \
|
||||
WasmFunctionParams##F, \
|
||||
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
|
||||
WasmFunctionResult##F, \
|
||||
1); \
|
||||
WasmEdge_String hook_api::WasmFunctionName##F = \
|
||||
WasmEdge_StringCreateByCString(#F); \
|
||||
R hook_api::F( \
|
||||
hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
|
||||
COMMA __VA_ARGS__))
|
||||
|
||||
#define HOOK_SETUP() \
|
||||
using enum hook_api::hook_return_code; \
|
||||
#define VAR_JSASSIGN(T, V) \
|
||||
if (_stack >= argc) \
|
||||
returnJS(INVALID_ARGUMENT); \
|
||||
T& V = argv[_stack++]
|
||||
|
||||
#define FORWARD_JS_FUNCTION_CALL(F, ac, av) \
|
||||
hook_api::JSFunction##F(ctx, this_val, ac, av)
|
||||
|
||||
#define DEFINE_JS_FUNCTION(R, F, ...) \
|
||||
JSValue hook_api::JSFunction##F( \
|
||||
JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) \
|
||||
{ \
|
||||
__VA_OPT__(int _stack = 0;) \
|
||||
__VA_OPT__(FOR_VARS(VAR_JSASSIGN, 2, __VA_ARGS__);)
|
||||
|
||||
#define JS_HOOK_SETUP() \
|
||||
JSRuntime* rt = JS_GetRuntime(ctx); \
|
||||
hook::HookContext& hookCtx = \
|
||||
*reinterpret_cast<hook::HookContext*>(JS_GetRuntimeOpaque(rt)); \
|
||||
[[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx; \
|
||||
[[maybe_unused]] auto& view = applyCtx.view(); \
|
||||
[[maybe_unused]] auto j = applyCtx.app.journal("View"); \
|
||||
[[maybe_unused]] auto& api = hookCtx.api(); \
|
||||
try \
|
||||
{
|
||||
#define JS_HOOK_TEARDOWN() \
|
||||
} \
|
||||
catch (const std::exception& e) \
|
||||
{ \
|
||||
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
|
||||
<< "HookError[" << HC_ACC() << "]: (JS) " << __func__ \
|
||||
<< " threw uncaught exception, what=" << e.what(); \
|
||||
return JS_NewInt64(ctx, INTERNAL_ERROR); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WASM_HOOK_SETUP() \
|
||||
try \
|
||||
{ \
|
||||
[[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx; \
|
||||
@@ -168,14 +274,14 @@
|
||||
if (!memoryCtx || !memory || !memory_length) \
|
||||
return INTERNAL_ERROR;
|
||||
|
||||
#define HOOK_TEARDOWN() \
|
||||
} \
|
||||
catch (const std::exception& e) \
|
||||
{ \
|
||||
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
|
||||
<< "HookError[" << HC_ACC() << "]: " << __func__ \
|
||||
<< " threw uncaught exception, what=" << e.what(); \
|
||||
return INTERNAL_ERROR; \
|
||||
#define WASM_HOOK_TEARDOWN() \
|
||||
} \
|
||||
catch (const std::exception& e) \
|
||||
{ \
|
||||
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
|
||||
<< "HookError[" << HC_ACC() << "]: (WASM) " << __func__ \
|
||||
<< " threw uncaught exception, what=" << e.what(); \
|
||||
return INTERNAL_ERROR; \
|
||||
}
|
||||
|
||||
#define WRITE_WASM_MEMORY( \
|
||||
@@ -214,7 +320,7 @@
|
||||
host_memory_ptr, \
|
||||
guest_memory_length) \
|
||||
{ \
|
||||
uint64_t bytes_written = 0; \
|
||||
int64_t bytes_written = 0; \
|
||||
WRITE_WASM_MEMORY( \
|
||||
bytes_written, \
|
||||
guest_dst_ptr, \
|
||||
@@ -269,6 +375,28 @@
|
||||
: RC_ROLLBACK); \
|
||||
}
|
||||
|
||||
#define HOOK_EXIT_JS(error_msg, error_code, exit_type) \
|
||||
{ \
|
||||
int64_t val = 0; \
|
||||
if (JS_IsNumber(error_code)) \
|
||||
JS_ToInt64(ctx, &val, error_code); \
|
||||
hookCtx.result.exitCode = val; \
|
||||
hookCtx.result.exitType = exit_type; \
|
||||
if (JS_IsString(error_msg)) \
|
||||
{ \
|
||||
size_t len; \
|
||||
const char* cstr = JS_ToCStringLen(ctx, &len, error_msg); \
|
||||
if (len > 256) \
|
||||
len = 256; \
|
||||
hookCtx.result.exitReason = std::string(cstr, len); \
|
||||
JS_FreeCString(ctx, cstr); \
|
||||
} \
|
||||
return JS_Exit( \
|
||||
ctx, \
|
||||
exit_type == hook_api::ExitType::ACCEPT ? "HookExit Accept" \
|
||||
: "HookExit Rollback"); \
|
||||
}
|
||||
|
||||
#define WRITE_WASM_MEMORY_OR_RETURN_AS_INT64( \
|
||||
write_ptr_in, write_len_in, data_ptr_in, data_len_in, is_account_in) \
|
||||
{ \
|
||||
@@ -283,7 +411,7 @@
|
||||
data_ptr < (data_ptr_in)) \
|
||||
return INTERNAL_ERROR; \
|
||||
if (data_len == 0) \
|
||||
return 0ULL; \
|
||||
return 0; \
|
||||
if ((write_ptr_in) == 0) \
|
||||
return data_as_int64(data_ptr, data_len); \
|
||||
if (data_len > (write_len_in)) \
|
||||
|
||||
@@ -7,311 +7,559 @@ HOOK_API_DEFINITION(
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, accept, (uint32_t, uint32_t, int64_t),
|
||||
uint256{})
|
||||
// function accept(error_msg: string, error_code: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, accept, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, rollback, (uint32_t, uint32_t, int64_t),
|
||||
uint256{})
|
||||
// function rollback(error_msg: string, error_code: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, rollback, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function util_raddr(acc_id:string): string
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, util_raddr, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function util_accid(acc_id:string): string
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, util_accid, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function util_verify(data:string, sig: string, pubkey: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, util_verify, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function util_sha512h(data: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, util_sha512h, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function util_keylet(keylet_type: number, keylet_data: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, util_keylet, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, sto_validate, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function sto_validate(sto: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_validate, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function sto_subfield(sto: string, field_id: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_subfield, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function sto_subarray(sto: string, array_id: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_subarray, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function sto_emplace(sto: string, field_bytes: number, field_id: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_emplace, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function sto_erase(sto: string, field_id: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_erase, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_burden();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_burden, (),
|
||||
uint256{})
|
||||
// function etxn_burden(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_burden, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_details, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function etxn_details(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_details, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_fee_base, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function etxn_fee_base(txblob: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_fee_base, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_reserve(uint32_t count);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_reserve, (uint32_t),
|
||||
uint256{})
|
||||
// function etxn_reserve(count: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_reserve, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_generation();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_generation, (),
|
||||
uint256{})
|
||||
// function etxn_generation(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_generation, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, etxn_nonce, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function etxn_nonce(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, etxn_nonce, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function emit(txn: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, emit, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_set(int32_t exponent, int64_t mantissa);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_set, (int32_t, int64_t),
|
||||
uint256{})
|
||||
// function float_set(e: number, m: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_set, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_multiply(int64_t float1, int64_t float2);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_multiply, (int64_t, int64_t),
|
||||
uint256{})
|
||||
// function float_multiply(f1: number, f2: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_multiply, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_mulratio(f1: number, round_up: number, numerator: number, denominator: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_mulratio, (JSValue, JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_negate(int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_negate, (int64_t),
|
||||
uint256{})
|
||||
// function float_negate(f1: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_negate, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_compare, (int64_t, int64_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_compare(f1: number, f2: number, mode: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_compare, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_sum(int64_t float1, int64_t float2);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_sum, (int64_t, int64_t),
|
||||
uint256{})
|
||||
// function float_sum(f1: number, f2: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_sum, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_sto(cur: string, isu: string, float1: number, field_code: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_sto, (JSValue, JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_sto_set, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_sto_set(buf: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_sto_set, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_invert(int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_invert, (int64_t),
|
||||
uint256{})
|
||||
// function float_invert(f1: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_invert, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_divide(int64_t float1, int64_t float2);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_divide, (int64_t, int64_t),
|
||||
uint256{})
|
||||
// function float_divide(f1: number, f2: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_divide, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_one();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_one, (),
|
||||
uint256{})
|
||||
// function float_one(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_one, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_mantissa(int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_mantissa, (int64_t),
|
||||
uint256{})
|
||||
// function float_mantissa(f1: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_mantissa, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_sign(int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_sign, (int64_t),
|
||||
uint256{})
|
||||
// function float_sign(f1: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_sign, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_int, (int64_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_int(f1: number, decimal_places: number, abs: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_int, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_log(int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_log, (int64_t),
|
||||
uint256{})
|
||||
// function float_log(f1: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_log, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t float_root(int64_t float1, uint32_t n);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, float_root, (int64_t, uint32_t),
|
||||
uint256{})
|
||||
// function float_root(f1: number, n: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, float_root, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t fee_base();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, fee_base, (),
|
||||
uint256{})
|
||||
// function fee_base(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, fee_base, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t ledger_seq();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, ledger_seq, (),
|
||||
uint256{})
|
||||
// function ledger_seq(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, ledger_seq, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t ledger_last_time();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, ledger_last_time, (),
|
||||
uint256{})
|
||||
// function ledger_last_time(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, ledger_last_time, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, ledger_last_hash, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function ledger_last_hash(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, ledger_last_hash, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, ledger_nonce, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function ledger_nonce(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, ledger_nonce, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function ledger_keylet(low: string, high: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, ledger_keylet, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_account, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function hook_account(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_account, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_hash, (uint32_t, uint32_t, int32_t),
|
||||
uint256{})
|
||||
// function hook_hash(hook_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_hash, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function hook_param_set(value: string, key: string, hash: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_param_set, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function hook_param(key: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_param, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_again();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_again, (),
|
||||
uint256{})
|
||||
// function hook_again(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_again, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_skip, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function hook_skip(hhash: string, flags: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_skip, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t hook_pos();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, hook_pos, (),
|
||||
uint256{})
|
||||
// function hook_pos(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, hook_pos, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function slot(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_clear(uint32_t slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_clear, (uint32_t),
|
||||
uint256{})
|
||||
// function slot_clear(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_clear, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_count(uint32_t slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_count, (uint32_t),
|
||||
uint256{})
|
||||
// function slot_count(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_count, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_set, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function slot_set(kl: string, slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_set, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_size(uint32_t slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_size, (uint32_t),
|
||||
uint256{})
|
||||
// function slot_size(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_size, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function slot_subarray(parent_slot_no: number, array_id: number, new_slot: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_subarray, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function slot_subfield(parent_slot_no: number, field_id: number, new_slot: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_subfield, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_type(uint32_t slot_no, uint32_t flags);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_type, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function slot_type(slot_no: number, flags: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_type, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t slot_float(uint32_t slot_no);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, slot_float, (uint32_t),
|
||||
uint256{})
|
||||
// function slot_float(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_float, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function state_set(val: string, key: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, state_set, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function state_foreign_set(val: string, key: string, ns: string, accid: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, state_foreign_set, (JSValue, JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function state(key: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, state, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function state_foreign(key: string, ns: string, accid: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, state_foreign, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function trace(msg: string, data: string, as_hex: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, trace, (JSValue, JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number);
|
||||
HOOK_API_DEFINITION(
|
||||
@@ -327,48 +575,108 @@ HOOK_API_DEFINITION(
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_burden, (),
|
||||
uint256{})
|
||||
// function otxn_burden(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_burden, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_field, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function otxn_field(field_id: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_field, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_generation();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_generation, (),
|
||||
uint256{})
|
||||
// function otxn_generation(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_generation, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_id, (uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function otxn_id(flags: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_id, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_type();
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_type, (),
|
||||
uint256{})
|
||||
// function otxn_type(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_type, (),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_slot(uint32_t slot_no);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_slot, (uint32_t),
|
||||
uint256{})
|
||||
// function otxn_slot(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_slot, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
uint256{})
|
||||
// function otxn_param(param_key: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_param, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t meta_slot(uint32_t slot_no);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, meta_slot, (uint32_t),
|
||||
uint256{})
|
||||
// function meta_slot(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, meta_slot, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, xpop_slot, (uint32_t, uint32_t),
|
||||
featureHooksUpdate1)
|
||||
// function xpop_slot(slot_no_tx: number, slot_no_meta: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, xpop_slot, (JSValue, JSValue),
|
||||
uint256{})
|
||||
|
||||
// int64_t prepare(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, prepare, (uint32_t, uint32_t, uint32_t, uint32_t),
|
||||
featureHooksUpdate2)
|
||||
// function prepare(tmpl: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, prepare, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// function otxn_json(): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, otxn_json, (),
|
||||
uint256{})
|
||||
|
||||
// function slot_json(slot_no: number): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, slot_json, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// function sto_to_json(sto_in: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_to_json, (JSValue),
|
||||
uint256{})
|
||||
|
||||
// function sto_from_json(json_in: string): number
|
||||
JSHOOK_API_DEFINITION(
|
||||
JSValue, sto_from_json, (JSValue),
|
||||
uint256{})
|
||||
|
||||
@@ -33,39 +33,35 @@
|
||||
*
|
||||
* Steps required to add new features to the code:
|
||||
*
|
||||
* 1) Add the appropriate XRPL_FEATURE or XRPL_FIX macro definition for the
|
||||
* feature to features.macro with the feature's name, `Supported::no`, and
|
||||
* `VoteBehavior::DefaultNo`.
|
||||
*
|
||||
* 2) Use the generated variable name as the parameter to `view.rules.enabled()`
|
||||
* to control flow into new code that this feature limits. (featureName or
|
||||
* fixName)
|
||||
*
|
||||
* 3) If the feature development is COMPLETE, and the feature is ready to be
|
||||
* SUPPORTED, change the macro parameter in features.macro to Supported::yes.
|
||||
*
|
||||
* 4) In general, any newly supported amendments (`Supported::yes`) should have
|
||||
* a `VoteBehavior::DefaultNo` indefinitely so that external governance can
|
||||
* make the decision on when to activate it. High priority bug fixes can be
|
||||
* an exception to this rule. In such cases, ensure the fix has been
|
||||
* clearly communicated to the community using appropriate channels,
|
||||
* then change the macro parameter in features.macro to
|
||||
* `VoteBehavior::DefaultYes`. The communication process is beyond
|
||||
* the scope of these instructions.
|
||||
*
|
||||
* 1) In this file, increment `numFeatures` and add a uint256 declaration
|
||||
* for the feature at the bottom
|
||||
* 2) Add a uint256 definition for the feature to the corresponding source
|
||||
* file (Feature.cpp). Use `registerFeature` to create the feature with
|
||||
* the feature's name, `Supported::no`, and `VoteBehavior::DefaultNo`. This
|
||||
* should be the only place the feature's name appears in code as a string.
|
||||
* 3) Use the uint256 as the parameter to `view.rules.enabled()` to
|
||||
* control flow into new code that this feature limits.
|
||||
* 4) If the feature development is COMPLETE, and the feature is ready to be
|
||||
* SUPPORTED, change the `registerFeature` parameter to Supported::yes.
|
||||
* 5) When the feature is ready to be ENABLED, change the `registerFeature`
|
||||
* parameter to `VoteBehavior::DefaultYes`.
|
||||
* In general, any newly supported amendments (`Supported::yes`) should have
|
||||
* a `VoteBehavior::DefaultNo` for at least one full release cycle. High
|
||||
* priority bug fixes can be an exception to this rule of thumb.
|
||||
*
|
||||
* When a feature has been enabled for several years, the conditional code
|
||||
* may be removed, and the feature "retired". To retire a feature:
|
||||
*
|
||||
* 1) MOVE the macro definition in features.macro to the "retired features"
|
||||
* section at the end of the file, and change the macro to XRPL_RETIRE.
|
||||
*
|
||||
* 1) Remove the uint256 declaration from this file.
|
||||
* 2) MOVE the uint256 definition in Feature.cpp to the "retired features"
|
||||
* section at the end of the file.
|
||||
* 3) CHANGE the name of the variable to start with "retired".
|
||||
* 4) CHANGE the parameters of the `registerFeature` call to `Supported::yes`
|
||||
* and `VoteBehavior::DefaultNo`.
|
||||
* The feature must remain registered and supported indefinitely because it
|
||||
* may exist in the Amendments object on ledger. There is no need to vote
|
||||
* for it because there's nothing to vote for. If the feature definition is
|
||||
* removed completely from the code, any instances running that code will get
|
||||
* amendment blocked. Removing the feature from the ledger is beyond the scope
|
||||
* of these instructions.
|
||||
* still exists in the ledger, but there is no need to vote for it because
|
||||
* there's nothing to vote for. If it is removed completely from the code, any
|
||||
* instances running that code will get amendment blocked. Removing the
|
||||
* feature from the ledger is beyond the scope of these instructions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -80,32 +76,11 @@ allAmendments();
|
||||
|
||||
namespace detail {
|
||||
|
||||
#pragma push_macro("XRPL_FEATURE")
|
||||
#undef XRPL_FEATURE
|
||||
#pragma push_macro("XRPL_FIX")
|
||||
#undef XRPL_FIX
|
||||
#pragma push_macro("XRPL_RETIRE")
|
||||
#undef XRPL_RETIRE
|
||||
|
||||
#define XRPL_FEATURE(name, supported, vote) +1
|
||||
#define XRPL_FIX(name, supported, vote) +1
|
||||
#define XRPL_RETIRE(name) +1
|
||||
|
||||
// This value SHOULD be equal to the number of amendments registered in
|
||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
|
||||
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
|
||||
// the actual number of amendments. A LogicError on startup will verify this.
|
||||
static constexpr std::size_t numFeatures =
|
||||
(0 +
|
||||
#include <xrpl/protocol/detail/features.macro>
|
||||
);
|
||||
|
||||
#undef XRPL_RETIRE
|
||||
#pragma pop_macro("XRPL_RETIRE")
|
||||
#undef XRPL_FIX
|
||||
#pragma pop_macro("XRPL_FIX")
|
||||
#undef XRPL_FEATURE
|
||||
#pragma pop_macro("XRPL_FEATURE")
|
||||
static constexpr std::size_t numFeatures = 116;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -345,17 +320,12 @@ foreachFeature(FeatureBitset bs, F&& f)
|
||||
#undef XRPL_FEATURE
|
||||
#pragma push_macro("XRPL_FIX")
|
||||
#undef XRPL_FIX
|
||||
#pragma push_macro("XRPL_RETIRE")
|
||||
#undef XRPL_RETIRE
|
||||
|
||||
#define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name;
|
||||
#define XRPL_FIX(name, supported, vote) extern uint256 const fix##name;
|
||||
#define XRPL_RETIRE(name)
|
||||
|
||||
#include <xrpl/protocol/detail/features.macro>
|
||||
|
||||
#undef XRPL_RETIRE
|
||||
#pragma pop_macro("XRPL_RETIRE")
|
||||
#undef XRPL_FIX
|
||||
#pragma pop_macro("XRPL_FIX")
|
||||
#undef XRPL_FEATURE
|
||||
|
||||
@@ -137,7 +137,6 @@ enum TEMcodes : TERUnderlyingType {
|
||||
temXCHAIN_BRIDGE_NONDOOR_OWNER,
|
||||
temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT,
|
||||
temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT,
|
||||
temXCHAIN_TOO_MANY_ATTESTATIONS, // RESERVED - not used
|
||||
|
||||
temHOOK_DATA_TOO_LARGE,
|
||||
temEMPTY_DID,
|
||||
@@ -363,6 +362,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecARRAY_TOO_LARGE = 197,
|
||||
tecLOCKED = 198,
|
||||
tecBAD_CREDENTIALS = 199,
|
||||
tecINVALID_HOOK_API_VERSION = 200,
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -223,11 +223,6 @@ constexpr std::uint32_t const tfNFTokenCancelOfferMask = ~tfUniversal;
|
||||
// NFTokenAcceptOffer flags:
|
||||
constexpr std::uint32_t const tfNFTokenAcceptOfferMask = ~tfUniversal;
|
||||
|
||||
enum SetHookFlags : uint32_t {
|
||||
tfNewAccount = 0x00000001,
|
||||
};
|
||||
constexpr std::uint32_t const tfSetHookMask = ~(tfUniversal | tfNewAccount);
|
||||
|
||||
// URIToken mask
|
||||
constexpr std::uint32_t const tfURITokenMintMask = ~(tfUniversal | tfBurnable);
|
||||
constexpr std::uint32_t const tfURITokenNonMintMask = ~tfUniversal;
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
#if !defined(XRPL_FIX)
|
||||
#error "undefined macro: XRPL_FIX"
|
||||
#endif
|
||||
#if !defined(XRPL_RETIRE)
|
||||
#error "undefined macro: XRPL_RETIRE"
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -34,10 +31,7 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FEATURE(HookAdministrator, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(IOURewardClaim, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(JSHooks, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (IOULockedBalanceInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ImportIssuer, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -63,16 +57,16 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYe
|
||||
XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes);
|
||||
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes);
|
||||
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes);
|
||||
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo);
|
||||
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes);
|
||||
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (RewardClaimFlags, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(HookCanEmit, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -156,24 +150,4 @@ XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete)
|
||||
XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete)
|
||||
XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
|
||||
|
||||
// The following amendments have been active for at least two years. Their
|
||||
// pre-amendment code has been removed and the identifiers are deprecated.
|
||||
// All known amendments and amendments that may appear in a validated
|
||||
// ledger must be registered either here or above with the "active" amendments
|
||||
XRPL_RETIRE(MultiSign)
|
||||
XRPL_RETIRE(TrustSetAuth)
|
||||
XRPL_RETIRE(FeeEscalation)
|
||||
XRPL_RETIRE(PayChan)
|
||||
XRPL_RETIRE(CryptoConditions)
|
||||
XRPL_RETIRE(TickSize)
|
||||
XRPL_RETIRE(fix1368)
|
||||
XRPL_RETIRE(Escrow)
|
||||
XRPL_RETIRE(fix1373)
|
||||
XRPL_RETIRE(EnforceInvariants)
|
||||
XRPL_RETIRE(SortedDirectories)
|
||||
XRPL_RETIRE(fix1201)
|
||||
XRPL_RETIRE(fix1512)
|
||||
XRPL_RETIRE(fix1523)
|
||||
XRPL_RETIRE(fix1528)
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -262,7 +262,6 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
|
||||
{sfHookStateScale, soeOPTIONAL},
|
||||
{sfCron, soeOPTIONAL},
|
||||
{sfAMMID, soeOPTIONAL},
|
||||
{sfHookAdministrator, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** A ledger object which contains a list of object identifiers.
|
||||
@@ -397,8 +396,6 @@ LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({
|
||||
{sfHighQualityOut, soeOPTIONAL},
|
||||
{sfLockedBalance, soeOPTIONAL},
|
||||
{sfLockCount, soeOPTIONAL},
|
||||
{sfHighReward, soeOPTIONAL},
|
||||
{sfLowReward, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** The ledger object which lists the network's fee settings.
|
||||
|
||||
@@ -257,7 +257,6 @@ TYPED_SFIELD(sfPrice, AMOUNT, 28)
|
||||
TYPED_SFIELD(sfSignatureReward, AMOUNT, 29)
|
||||
TYPED_SFIELD(sfMinAccountCreateAmount, AMOUNT, 30)
|
||||
TYPED_SFIELD(sfLPTokenBalance, AMOUNT, 31)
|
||||
TYPED_SFIELD(sfTrustLineRewardAccumulator,AMOUNT, 99)
|
||||
|
||||
// variable length (common)
|
||||
TYPED_SFIELD(sfPublicKey, VL, 1)
|
||||
@@ -293,7 +292,6 @@ TYPED_SFIELD(sfAssetClass, VL, 29)
|
||||
TYPED_SFIELD(sfProvider, VL, 30)
|
||||
TYPED_SFIELD(sfMPTokenMetadata, VL, 31)
|
||||
TYPED_SFIELD(sfCredentialType, VL, 32)
|
||||
TYPED_SFIELD(sfHookName, VL, 97)
|
||||
TYPED_SFIELD(sfRemarkValue, VL, 98)
|
||||
TYPED_SFIELD(sfRemarkName, VL, 99)
|
||||
|
||||
@@ -319,7 +317,6 @@ TYPED_SFIELD(sfAttestationRewardAccount, ACCOUNT, 21)
|
||||
TYPED_SFIELD(sfLockingChainDoor, ACCOUNT, 22)
|
||||
TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23)
|
||||
TYPED_SFIELD(sfSubject, ACCOUNT, 24)
|
||||
TYPED_SFIELD(sfHookAdministrator, ACCOUNT, 98)
|
||||
TYPED_SFIELD(sfInform, ACCOUNT, 99)
|
||||
|
||||
// vector of 256-bit
|
||||
@@ -343,7 +340,6 @@ TYPED_SFIELD(sfLockingChainIssue, ISSUE, 1)
|
||||
TYPED_SFIELD(sfIssuingChainIssue, ISSUE, 2)
|
||||
TYPED_SFIELD(sfAsset, ISSUE, 3)
|
||||
TYPED_SFIELD(sfAsset2, ISSUE, 4)
|
||||
TYPED_SFIELD(sfClaimCurrency, ISSUE, 5)
|
||||
|
||||
// bridge
|
||||
TYPED_SFIELD(sfXChainBridge, XCHAIN_BRIDGE, 1)
|
||||
@@ -390,8 +386,6 @@ UNTYPED_SFIELD(sfImportVLKey, OBJECT, 94)
|
||||
UNTYPED_SFIELD(sfActiveValidator, OBJECT, 95)
|
||||
UNTYPED_SFIELD(sfGenesisMint, OBJECT, 96)
|
||||
UNTYPED_SFIELD(sfRemark, OBJECT, 97)
|
||||
UNTYPED_SFIELD(sfHighReward, OBJECT, 98)
|
||||
UNTYPED_SFIELD(sfLowReward, OBJECT, 99)
|
||||
|
||||
// array of objects (common)
|
||||
// ARRAY/1 is reserved for end of array
|
||||
|
||||
@@ -195,7 +195,6 @@ TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, ({
|
||||
/** This transaction type installs a hook. */
|
||||
TRANSACTION(ttHOOK_SET, 22, SetHook, ({
|
||||
{sfHooks, soeREQUIRED},
|
||||
{sfDestination, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This transaction mints a new NFT. */
|
||||
@@ -551,7 +550,6 @@ TRANSACTION(ttIMPORT, 97, Import, ({
|
||||
* from a specified hook */
|
||||
TRANSACTION(ttCLAIM_REWARD, 98, ClaimReward, ({
|
||||
{sfIssuer, soeOPTIONAL},
|
||||
{sfClaimCurrency, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This transaction invokes a hook, providing arbitrary data. Essentially as a 0 drop payment. **/
|
||||
|
||||
@@ -76,7 +76,6 @@ JSS(Holder); // field.
|
||||
JSS(HookApiVersion); // field
|
||||
JSS(HookCanEmit); // field
|
||||
JSS(HookHash); // field
|
||||
JSS(HookName); // field
|
||||
JSS(HookNamespace); // field
|
||||
JSS(HookOn); // field
|
||||
JSS(HookOnIncoming); // field
|
||||
|
||||
@@ -11,11 +11,11 @@ echo "START BUILDING (HOST)"
|
||||
echo "Cleaning previously built binary"
|
||||
rm -f release-build/xahaud
|
||||
|
||||
BUILD_CORES=$(echo "scale=0 ; $(nproc) / 1.337" | bc)
|
||||
BUILD_CORES=$(echo "scale=0 ; `nproc` / 1.337" | bc)
|
||||
|
||||
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
|
||||
#Default
|
||||
BUILD_CORES=${BUILD_CORES:-8}
|
||||
BUILD_CORES=${BUILD_CORES:-8}
|
||||
fi
|
||||
|
||||
# Ensure still works outside of GH Actions by setting these to /dev/null
|
||||
@@ -31,19 +31,21 @@ echo "-- GITHUB_SHA: $GITHUB_SHA"
|
||||
echo "-- GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER"
|
||||
echo "-- CONTAINER_NAME: $CONTAINER_NAME"
|
||||
|
||||
which docker 2>/dev/null 2>/dev/null
|
||||
if [ "$?" -eq "1" ]; then
|
||||
which docker 2> /dev/null 2> /dev/null
|
||||
if [ "$?" -eq "1" ]
|
||||
then
|
||||
echo 'Docker not found. Install it first.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
stat .git 2>/dev/null 2>/dev/null
|
||||
if [ "$?" -eq "1" ]; then
|
||||
stat .git 2> /dev/null 2> /dev/null
|
||||
if [ "$?" -eq "1" ]
|
||||
then
|
||||
echo 'Run this inside the source directory. (.git dir not found).'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME | wc -l)
|
||||
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME |wc -l)
|
||||
|
||||
CACHE_VOLUME_NAME="xahau-release-builder-cache"
|
||||
|
||||
@@ -55,14 +57,13 @@ if false; then
|
||||
docker stop $CONTAINER_NAME
|
||||
else
|
||||
echo "No static container, build on temp container"
|
||||
rm -rf release-build
|
||||
mkdir -p release-build
|
||||
rm -rf release-build;
|
||||
mkdir -p release-build;
|
||||
|
||||
docker volume create $CACHE_VOLUME_NAME
|
||||
|
||||
# Create inline Dockerfile with environment setup for build-full.sh
|
||||
DOCKERFILE_CONTENT=$(
|
||||
cat <<'DOCKERFILE_EOF'
|
||||
DOCKERFILE_CONTENT=$(cat <<'DOCKERFILE_EOF'
|
||||
FROM ghcr.io/phusion/holy-build-box:4.0.1-amd64
|
||||
|
||||
ARG BUILD_CORES=8
|
||||
@@ -217,7 +218,7 @@ RUN /hbb_exe/activate-exec bash -c "ccache -M 100G && \
|
||||
ln -s ../../bin/ccache /usr/lib64/ccache/c++"
|
||||
|
||||
DOCKERFILE_EOF
|
||||
)
|
||||
)
|
||||
|
||||
# Build custom Docker image
|
||||
IMAGE_NAME="xahaud-builder:latest"
|
||||
@@ -227,14 +228,14 @@ DOCKERFILE_EOF
|
||||
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
|
||||
# Non GH, local building
|
||||
echo "Non-GH runner, local building, temp container"
|
||||
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
|
||||
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
|
||||
else
|
||||
# GH Action, runner
|
||||
echo "GH Action, runner, clean & re-create create persistent container"
|
||||
docker rm -f $CONTAINER_NAME
|
||||
echo "echo 'Stopping container: $CONTAINER_NAME'" >>"$JOB_CLEANUP_SCRIPT"
|
||||
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >>"$JOB_CLEANUP_SCRIPT"
|
||||
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
|
||||
echo "echo 'Stopping container: $CONTAINER_NAME'" >> "$JOB_CLEANUP_SCRIPT"
|
||||
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >> "$JOB_CLEANUP_SCRIPT"
|
||||
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
|
||||
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
|
||||
docker stop $CONTAINER_NAME
|
||||
fi
|
||||
|
||||
@@ -66,7 +66,7 @@ invalidAMMAsset(
|
||||
Issue const& issue,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair)
|
||||
{
|
||||
if (isBadCurrency(issue.currency))
|
||||
if (badCurrency() == issue.currency)
|
||||
return temBAD_CURRENCY;
|
||||
if (isXRP(issue) && issue.account.isNonZero())
|
||||
return temBAD_ISSUER;
|
||||
|
||||
@@ -250,9 +250,12 @@ FeatureCollections::registerFeature(
|
||||
Feature const* i = getByName(name);
|
||||
if (!i)
|
||||
{
|
||||
// If this check fails, and you just added a feature, increase the
|
||||
// numFeatures value in Feature.h
|
||||
check(
|
||||
features.size() < detail::numFeatures,
|
||||
"More features defined than allocated.");
|
||||
"More features defined than allocated. Adjust numFeatures in "
|
||||
"Feature.h.");
|
||||
|
||||
auto const f = sha512Half(Slice(name.data(), name.size()));
|
||||
|
||||
@@ -421,26 +424,45 @@ featureToName(uint256 const& f)
|
||||
#undef XRPL_FEATURE
|
||||
#pragma push_macro("XRPL_FIX")
|
||||
#undef XRPL_FIX
|
||||
#pragma push_macro("XRPL_RETIRE")
|
||||
#undef XRPL_RETIRE
|
||||
|
||||
#define XRPL_FEATURE(name, supported, vote) \
|
||||
uint256 const feature##name = registerFeature(#name, supported, vote);
|
||||
#define XRPL_FIX(name, supported, vote) \
|
||||
uint256 const fix##name = registerFeature("fix" #name, supported, vote);
|
||||
#define XRPL_RETIRE(name) \
|
||||
[[deprecated("The referenced amendment has been retired"), maybe_unused]] \
|
||||
uint256 const retired##name = retireFeature(#name);
|
||||
|
||||
#include <xrpl/protocol/detail/features.macro>
|
||||
|
||||
#undef XRPL_RETIRE
|
||||
#pragma pop_macro("XRPL_RETIRE")
|
||||
#undef XRPL_FIX
|
||||
#pragma pop_macro("XRPL_FIX")
|
||||
#undef XRPL_FEATURE
|
||||
#pragma pop_macro("XRPL_FEATURE")
|
||||
|
||||
// clang-format off
|
||||
|
||||
// The following amendments have been active for at least two years. Their
|
||||
// pre-amendment code has been removed and the identifiers are deprecated.
|
||||
// All known amendments and amendments that may appear in a validated
|
||||
// ledger must be registered either here or above with the "active" amendments
|
||||
[[deprecated("The referenced amendment has been retired"), maybe_unused]]
|
||||
uint256 const
|
||||
retiredMultiSign = retireFeature("MultiSign"),
|
||||
retiredTrustSetAuth = retireFeature("TrustSetAuth"),
|
||||
retiredFeeEscalation = retireFeature("FeeEscalation"),
|
||||
retiredPayChan = retireFeature("PayChan"),
|
||||
retiredCryptoConditions = retireFeature("CryptoConditions"),
|
||||
retiredTickSize = retireFeature("TickSize"),
|
||||
retiredFix1368 = retireFeature("fix1368"),
|
||||
retiredEscrow = retireFeature("Escrow"),
|
||||
retiredFix1373 = retireFeature("fix1373"),
|
||||
retiredEnforceInvariants = retireFeature("EnforceInvariants"),
|
||||
retiredSortedDirectories = retireFeature("SortedDirectories"),
|
||||
retiredFix1201 = retireFeature("fix1201"),
|
||||
retiredFix1512 = retireFeature("fix1512"),
|
||||
retiredFix1523 = retireFeature("fix1523"),
|
||||
retiredFix1528 = retireFeature("fix1528");
|
||||
|
||||
// clang-format on
|
||||
|
||||
// All of the features should now be registered, since variables in a cpp file
|
||||
// are initialized from top to bottom.
|
||||
//
|
||||
|
||||
@@ -99,7 +99,7 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
{sfHookApiVersion, soeOPTIONAL},
|
||||
{sfHookName, soeOPTIONAL},
|
||||
{sfFee, soeOPTIONAL},
|
||||
{sfFlags, soeOPTIONAL}});
|
||||
|
||||
add(sfHookGrant.jsonName,
|
||||
@@ -254,24 +254,6 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfIssuer, soeREQUIRED},
|
||||
{sfCredentialType, soeREQUIRED},
|
||||
});
|
||||
|
||||
add(sfHighReward.jsonName,
|
||||
sfHighReward.getCode(),
|
||||
{
|
||||
{sfRewardLgrFirst, soeREQUIRED},
|
||||
{sfRewardLgrLast, soeREQUIRED},
|
||||
{sfRewardTime, soeREQUIRED},
|
||||
{sfTrustLineRewardAccumulator, soeREQUIRED},
|
||||
});
|
||||
|
||||
add(sfLowReward.jsonName,
|
||||
sfLowReward.getCode(),
|
||||
{
|
||||
{sfRewardLgrFirst, soeREQUIRED},
|
||||
{sfRewardLgrLast, soeREQUIRED},
|
||||
{sfRewardTime, soeREQUIRED},
|
||||
{sfTrustLineRewardAccumulator, soeREQUIRED},
|
||||
});
|
||||
}
|
||||
|
||||
InnerObjectFormats const&
|
||||
|
||||
@@ -111,7 +111,7 @@ issueFromJson(Json::Value const& v)
|
||||
}
|
||||
|
||||
auto const currency = to_currency(curStr.asString());
|
||||
if (isBadCurrency(currency) || currency == noCurrency())
|
||||
if (currency == badCurrency() || currency == noCurrency())
|
||||
{
|
||||
Throw<Json::error>("issueFromJson currency must be a valid currency");
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ currencyFromJson(SField const& name, Json::Value const& v)
|
||||
}
|
||||
|
||||
auto const currency = to_currency(v.asString());
|
||||
if (isBadCurrency(currency) || currency == noCurrency())
|
||||
if (currency == badCurrency() || currency == noCurrency())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"currencyFromJson currency must be a valid currency");
|
||||
|
||||
@@ -124,6 +124,7 @@ transResults()
|
||||
MAKE_ERROR(tecARRAY_TOO_LARGE, "Array is too large."),
|
||||
MAKE_ERROR(tecLOCKED, "Fund is locked."),
|
||||
MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."),
|
||||
MAKE_ERROR(tecINVALID_HOOK_API_VERSION, "Invalid field for current hook API version."),
|
||||
|
||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||
|
||||
@@ -48,7 +48,6 @@ TxFormats::TxFormats()
|
||||
{sfFirstLedgerSequence, soeOPTIONAL},
|
||||
{sfNetworkID, soeOPTIONAL},
|
||||
{sfHookParameters, soeOPTIONAL},
|
||||
{sfHookName, soeOPTIONAL},
|
||||
};
|
||||
|
||||
#pragma push_macro("UNWRAP")
|
||||
|
||||
820
src/quickjs/buffer-utils.c
Normal file
820
src/quickjs/buffer-utils.c
Normal file
@@ -0,0 +1,820 @@
|
||||
#include "defines.h"
|
||||
#include "char-utils.h"
|
||||
#include "buffer-utils.h"
|
||||
#include "utils.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(HAVE_TERMIOS_H)
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* \addtogroup buffer-utils
|
||||
* @{
|
||||
*/
|
||||
size_t
|
||||
ansi_length(const char* str, size_t len) {
|
||||
size_t i, n = 0, p;
|
||||
for(i = 0; i < len;) {
|
||||
if(str[i] == 0x1b && (p = ansi_skip(&str[i], len - i)) > 0) {
|
||||
i += p;
|
||||
continue;
|
||||
}
|
||||
n++;
|
||||
i++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
ansi_skip(const char* str, size_t len) {
|
||||
size_t pos = 0;
|
||||
if(str[pos] == 0x1b) {
|
||||
if(++pos < len && str[pos] == '[') {
|
||||
while(++pos < len)
|
||||
if(is_alphanumeric_char(str[pos]))
|
||||
break;
|
||||
if(++pos < len && str[pos] == '~')
|
||||
++pos;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
ansi_truncate(const char* str, size_t len, size_t limit) {
|
||||
size_t i, n = 0, p;
|
||||
for(i = 0; i < len;) {
|
||||
if((p = ansi_skip(&str[i], len - i)) > 0) {
|
||||
i += p;
|
||||
continue;
|
||||
}
|
||||
n += is_escape_char(str[i]) ? 2 : 1;
|
||||
|
||||
i++;
|
||||
if(n > limit)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int64_t
|
||||
array_search(void* a, size_t m, size_t elsz, void* needle) {
|
||||
char* ptr = a;
|
||||
int64_t n, ret;
|
||||
n = m / elsz;
|
||||
for(ret = 0; ret < n; ret++) {
|
||||
if(!memcmp(ptr, needle, elsz))
|
||||
return ret;
|
||||
|
||||
ptr += elsz;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char*
|
||||
str_escape(const char* s) {
|
||||
DynBuf dbuf;
|
||||
dbuf_init2(&dbuf, 0, 0);
|
||||
dbuf_put_escaped(&dbuf, s, strlen(s));
|
||||
dbuf_0(&dbuf);
|
||||
return (char*)dbuf.buf;
|
||||
}
|
||||
|
||||
char*
|
||||
byte_escape(const void* s, size_t n) {
|
||||
DynBuf dbuf;
|
||||
dbuf_init2(&dbuf, 0, 0);
|
||||
dbuf_put_escaped(&dbuf, s, n);
|
||||
dbuf_0(&dbuf);
|
||||
return (char*)dbuf.buf;
|
||||
}
|
||||
|
||||
size_t
|
||||
byte_findb(const void* haystack, size_t hlen, const void* what, size_t wlen) {
|
||||
size_t i, last;
|
||||
const char* s = (const char*)haystack;
|
||||
if(hlen < wlen)
|
||||
return hlen;
|
||||
last = hlen - wlen;
|
||||
for(i = 0; i <= last; i++) {
|
||||
if(byte_equal(s, wlen, what))
|
||||
return i;
|
||||
s++;
|
||||
}
|
||||
return hlen;
|
||||
}
|
||||
|
||||
size_t
|
||||
byte_finds(const void* haystack, size_t hlen, const char* what) {
|
||||
return byte_findb(haystack, hlen, what, strlen(what));
|
||||
}
|
||||
|
||||
size_t
|
||||
byte_equal(const void* s, size_t n, const void* t) {
|
||||
return memcmp(s, t, n) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
byte_copy(void* out, size_t len, const void* in) {
|
||||
char* s = (char*)out;
|
||||
const char* t = (const char*)in;
|
||||
size_t i;
|
||||
for(i = 0; i < len; ++i)
|
||||
s[i] = t[i];
|
||||
}
|
||||
|
||||
void
|
||||
byte_copyr(void* out, size_t len, const void* in) {
|
||||
char* s = (char*)out + len;
|
||||
const char* t = (const char*)in;
|
||||
const char* u = t + len;
|
||||
|
||||
for(;;) {
|
||||
if(t >= u)
|
||||
break;
|
||||
--u;
|
||||
--s;
|
||||
*s = *u;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
byte_rchrs(const char* in, size_t len, const char needles[], size_t nn) {
|
||||
const char *s = in, *end = in + len, *found = 0;
|
||||
size_t i;
|
||||
for(; s < end; s++) {
|
||||
for(i = 0; i < nn; ++i) {
|
||||
if(*s == needles[i])
|
||||
found = s;
|
||||
}
|
||||
}
|
||||
return (size_t)((found ? found : s) - in);
|
||||
}
|
||||
|
||||
char*
|
||||
dbuf_at_n(const DynBuf* db, size_t i, size_t* n, char sep) {
|
||||
size_t p, l = 0;
|
||||
for(p = 0; p < db->size; ++p) {
|
||||
if(l == i) {
|
||||
*n = byte_chr((const char*)&db->buf[p], db->size - p, sep);
|
||||
return (char*)&db->buf[p];
|
||||
}
|
||||
if(db->buf[p] == sep)
|
||||
++l;
|
||||
}
|
||||
*n = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*
|
||||
dbuf_last_line(DynBuf* db, size_t* len) {
|
||||
size_t i;
|
||||
|
||||
if((i = byte_rchr(db->buf, db->size, '\n')) < db->size)
|
||||
i++;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
if(len)
|
||||
*len = db->size - i;
|
||||
|
||||
return (const char*)&db->buf[i];
|
||||
}
|
||||
|
||||
int
|
||||
dbuf_prepend(DynBuf* s, const uint8_t* data, size_t len) {
|
||||
int ret;
|
||||
if(!(ret = dbuf_reserve_start(s, len)))
|
||||
memcpy(s->buf, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_colorstr(DynBuf* db, const char* str, const char* color, int with_color) {
|
||||
if(with_color)
|
||||
dbuf_putstr(db, color);
|
||||
|
||||
dbuf_putstr(db, str);
|
||||
if(with_color)
|
||||
dbuf_putstr(db, COLOR_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_escaped_pred(DynBuf* db, const char* str, size_t len, int (*pred)(int)) {
|
||||
size_t i = 0, j;
|
||||
char c;
|
||||
|
||||
while(i < len) {
|
||||
if((j = predicate_find(&str[i], len - i, pred))) {
|
||||
dbuf_append(db, (const uint8_t*)&str[i], j);
|
||||
i += j;
|
||||
}
|
||||
|
||||
if(i == len)
|
||||
break;
|
||||
|
||||
dbuf_putc(db, '\\');
|
||||
|
||||
if(str[i] == 0x1b) {
|
||||
dbuf_append(db, (const uint8_t*)"x1b", 3);
|
||||
} else {
|
||||
int r = pred(str[i]);
|
||||
|
||||
dbuf_putc(db, (r > 1 && r <= 127) ? r : (c = escape_char_letter(str[i])) ? c : str[i]);
|
||||
|
||||
if(r == 'u' || r == 'x')
|
||||
dbuf_printf(db, r == 'u' ? "%04x" : "%02x", str[i]);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t escape_url_tab[256] = {
|
||||
'%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%',
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '%',
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%',
|
||||
};
|
||||
|
||||
const uint8_t escape_noquote_tab[256] = {
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
};
|
||||
|
||||
const uint8_t escape_singlequote_tab[256] = {
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0x27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
};
|
||||
|
||||
const uint8_t escape_doublequote_tab[256] = {
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
|
||||
'x', 'x', 'x', 'x', 0, 0, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
};
|
||||
|
||||
const uint8_t escape_backquote_tab[256] = {
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0, 0x76, 0x66, 0, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
};
|
||||
|
||||
void
|
||||
dbuf_put_escaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]) {
|
||||
size_t i = 0, clen;
|
||||
int32_t c;
|
||||
const uint8_t *pos, *end, *next;
|
||||
|
||||
for(pos = (const uint8_t*)str, end = pos + len; pos < end; pos = next) {
|
||||
uint8_t r, ch;
|
||||
|
||||
if((c = unicode_from_utf8(pos, end - pos, &next)) < 0)
|
||||
break;
|
||||
clen = next - pos;
|
||||
ch = c;
|
||||
r = (clen >= 2 || c > 0xff) ? 'u' : table[c];
|
||||
|
||||
if(r == 'u' && clen > 1 && (c & 0xffffff00) == 0) {
|
||||
r = 'x';
|
||||
// ch = c >> 8;
|
||||
}
|
||||
|
||||
if(r == '%') {
|
||||
static const char hexdigits[] = "0123456789ABCDEF";
|
||||
|
||||
dbuf_putc(db, '%');
|
||||
dbuf_putc(db, hexdigits[c >> 4]);
|
||||
dbuf_putc(db, hexdigits[c & 0xf]);
|
||||
} else if(c == 0x1b) {
|
||||
dbuf_putstr(db, "\\x1b");
|
||||
} else if(r == 'u') {
|
||||
dbuf_printf(db, c > 0xffff ? "\\u{%X}" : "\\u%04x", c);
|
||||
} else if(r == 'x') {
|
||||
dbuf_printf(db, "\\x%02x", ch);
|
||||
} else if(r) {
|
||||
dbuf_putc(db, '\\');
|
||||
dbuf_putc(db, (r > 1 && r <= 127) ? r : (c = escape_char_letter(ch)) ? c : ch);
|
||||
} else {
|
||||
dbuf_put(db, pos, next - pos);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_unescaped_pred(DynBuf* db, const char* str, size_t len, int (*pred)(const char*, size_t*)) {
|
||||
size_t i = 0, j;
|
||||
// char c;
|
||||
|
||||
while(i < len) {
|
||||
int r = 0;
|
||||
if((j = byte_chr(&str[i], len - i, '\\'))) {
|
||||
dbuf_append(db, (const uint8_t*)&str[i], j);
|
||||
i += j;
|
||||
}
|
||||
if(i == len)
|
||||
break;
|
||||
size_t n = 1;
|
||||
|
||||
if(pred) {
|
||||
r = pred(&str[i + 1], &n);
|
||||
|
||||
if(!r && n == 1)
|
||||
dbuf_putc(db, '\\');
|
||||
}
|
||||
|
||||
if(r >= 0)
|
||||
dbuf_putc(db, /*n > 1 ||*/ r ? /*(r > 1 && r < 256) ?*/ r : str[i]);
|
||||
i += n;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
hexdigit(char c) {
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
||||
if(c >= 'a' && c <= 'f')
|
||||
c -= 32;
|
||||
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_unescaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]) {
|
||||
size_t i = 0, j;
|
||||
char escape_char = table == escape_url_tab ? '%' : '\\';
|
||||
|
||||
while(i < len) {
|
||||
if((j = byte_chr(&str[i], len - i, escape_char))) {
|
||||
dbuf_append(db, (const uint8_t*)&str[i], j);
|
||||
i += j;
|
||||
}
|
||||
|
||||
if(i == len)
|
||||
break;
|
||||
|
||||
if(escape_char == '%') {
|
||||
int hi = hexdigit(str[i + 1]), lo = hexdigit(str[i + 2]);
|
||||
uint8_t c = (hi << 4) | (lo & 0xf);
|
||||
dbuf_putc(db, c);
|
||||
|
||||
i += 2;
|
||||
|
||||
} else {
|
||||
++i;
|
||||
|
||||
uint8_t c;
|
||||
|
||||
switch(str[i]) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
default: c = str[i]; break;
|
||||
}
|
||||
|
||||
uint8_t r = table[c];
|
||||
|
||||
if(!(r && r != 'x' && r != 'u')) {
|
||||
dbuf_putc(db, '\\');
|
||||
dbuf_putc(db, c);
|
||||
} else {
|
||||
dbuf_putc(db, str[i] == r ? c : r);
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_escaped(DynBuf* db, const char* str, size_t len) {
|
||||
return dbuf_put_escaped_table(db, str, len, escape_noquote_tab);
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_value(DynBuf* db, JSContext* ctx, JSValueConst value) {
|
||||
const char* str;
|
||||
size_t len;
|
||||
str = JS_ToCStringLen(ctx, &len, value);
|
||||
dbuf_append(db, str, len);
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_uint32(DynBuf* db, uint32_t num) {
|
||||
char buf[FMT_ULONG];
|
||||
dbuf_put(db, (const uint8_t*)buf, fmt_ulong(buf, num));
|
||||
}
|
||||
|
||||
void
|
||||
dbuf_put_atom(DynBuf* db, JSContext* ctx, JSAtom atom) {
|
||||
const char* str;
|
||||
str = JS_AtomToCString(ctx, atom);
|
||||
dbuf_putstr(db, str);
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
|
||||
int
|
||||
dbuf_reserve_start(DynBuf* s, size_t len) {
|
||||
if(unlikely((s->size + len) > s->allocated_size)) {
|
||||
if(dbuf_realloc(s, s->size + len))
|
||||
return -1;
|
||||
}
|
||||
if(s->size > 0)
|
||||
memcpy(s->buf + len, s->buf, s->size);
|
||||
|
||||
s->size += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
dbuf_reserve(DynBuf* s, size_t len) {
|
||||
if(unlikely((s->size + len) > s->allocated_size))
|
||||
if(dbuf_realloc(s, s->size + len))
|
||||
return 0;
|
||||
|
||||
return &s->buf[s->size];
|
||||
}
|
||||
|
||||
size_t
|
||||
dbuf_token_pop(DynBuf* db, char delim) {
|
||||
size_t n, p, len;
|
||||
len = db->size;
|
||||
for(n = db->size; n > 0;) {
|
||||
if((p = byte_rchr(db->buf, n, delim)) == n) {
|
||||
db->size = 0;
|
||||
break;
|
||||
}
|
||||
if(p > 0 && db->buf[p - 1] == '\\') {
|
||||
n = p - 1;
|
||||
continue;
|
||||
}
|
||||
db->size = p;
|
||||
break;
|
||||
}
|
||||
return len - db->size;
|
||||
}
|
||||
|
||||
size_t
|
||||
dbuf_token_push(DynBuf* db, const char* str, size_t len, char delim) {
|
||||
size_t pos;
|
||||
if(db->size)
|
||||
dbuf_putc(db, delim);
|
||||
|
||||
pos = db->size;
|
||||
dbuf_put_escaped_pred(db, str, len, is_dot_char);
|
||||
return db->size - pos;
|
||||
}
|
||||
|
||||
JSValue
|
||||
dbuf_tostring_free(DynBuf* s, JSContext* ctx) {
|
||||
JSValue r;
|
||||
r = JS_NewStringLen(ctx, s->buf ? (const char*)s->buf : "", s->buf ? s->size : 0);
|
||||
dbuf_free(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
dbuf_load(DynBuf* s, const char* filename) {
|
||||
FILE* fp;
|
||||
size_t nbytes = 0;
|
||||
if((fp = fopen(filename, "rb"))) {
|
||||
char buf[4096];
|
||||
size_t r;
|
||||
while(!feof(fp)) {
|
||||
if((r = fread(buf, 1, sizeof(buf), fp)) == 0) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
dbuf_put(s, (uint8_t const*)buf, r);
|
||||
nbytes += r;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int
|
||||
dbuf_vprintf(DynBuf* s, const char* fmt, va_list ap) {
|
||||
|
||||
s->size += vsnprintf((char*)(s->buf + s->size), s->allocated_size - s->size, fmt, ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputBuffer
|
||||
js_input_buffer(JSContext* ctx, JSValueConst value) {
|
||||
InputBuffer ret = {{{0, 0}}, 0, &input_buffer_free_default, JS_UNDEFINED, {0, INT64_MAX}};
|
||||
|
||||
if(js_is_typedarray(ctx, value)) {
|
||||
ret.value = offset_typedarray(&ret.range, value, ctx);
|
||||
} else if(js_is_arraybuffer(ctx, value) || js_is_sharedarraybuffer(ctx, value)) {
|
||||
ret.value = JS_DupValue(ctx, value);
|
||||
}
|
||||
|
||||
if(js_is_arraybuffer(ctx, ret.value) || js_is_sharedarraybuffer(ctx, ret.value)) {
|
||||
block_arraybuffer(&ret.block, ret.value, ctx);
|
||||
} else {
|
||||
JS_ThrowTypeError(ctx, "Invalid type (%s) for input buffer", js_value_typestr(ctx, ret.value));
|
||||
JS_FreeValue(ctx, ret.value);
|
||||
ret.value = JS_EXCEPTION;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef free
|
||||
|
||||
InputBuffer
|
||||
js_input_chars(JSContext* ctx, JSValueConst value) {
|
||||
InputBuffer ret = {{{0, 0}}, 0, &input_buffer_free_default, JS_UNDEFINED, OFFSET_INIT()};
|
||||
|
||||
if(JS_IsString(value)) {
|
||||
ret.data = (uint8_t*)JS_ToCStringLen(ctx, &ret.size, value);
|
||||
ret.value = JS_DupValue(ctx, value);
|
||||
ret.free = &input_buffer_free_default;
|
||||
} else {
|
||||
ret = js_input_buffer(ctx, value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
InputBuffer
|
||||
js_input_args(JSContext* ctx, int argc, JSValueConst argv[]) {
|
||||
InputBuffer input = js_input_chars(ctx, argv[0]);
|
||||
|
||||
if(argc > 1)
|
||||
js_offset_length(ctx, input.size, argc - 1, argv + 1, &input.range);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
InputBuffer
|
||||
js_output_args(JSContext* ctx, int argc, JSValueConst argv[]) {
|
||||
InputBuffer output = js_input_buffer(ctx, argv[0]);
|
||||
|
||||
if(argc > 1)
|
||||
js_offset_length(ctx, output.size, argc - 1, argv + 1, &output.range);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
BOOL
|
||||
input_buffer_valid(const InputBuffer* in) {
|
||||
return !JS_IsException(in->value);
|
||||
}
|
||||
|
||||
InputBuffer
|
||||
input_buffer_clone(const InputBuffer* in, JSContext* ctx) {
|
||||
InputBuffer ret = js_input_buffer(ctx, in->value);
|
||||
|
||||
ret.pos = in->pos;
|
||||
ret.size = in->size;
|
||||
ret.free = in->free;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
input_buffer_dump(const InputBuffer* in, DynBuf* db) {
|
||||
dbuf_printf(db, "(InputBuffer){ .data = %p, .size = %lu, .pos = %lu, .free = %p }", in->data, (unsigned long)in->size, (unsigned long)in->pos, in->free);
|
||||
}
|
||||
|
||||
void
|
||||
input_buffer_free(InputBuffer* in, JSContext* ctx) {
|
||||
if(in->data) {
|
||||
in->free(ctx, (const char*)in->data, in->value);
|
||||
in->data = 0;
|
||||
in->size = 0;
|
||||
in->pos = 0;
|
||||
in->value = JS_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t*
|
||||
input_buffer_peek(InputBuffer* in, size_t* lenp) {
|
||||
input_buffer_peekc(in, lenp);
|
||||
return input_buffer_data(in) + in->pos;
|
||||
}
|
||||
|
||||
const uint8_t*
|
||||
input_buffer_get(InputBuffer* in, size_t* lenp) {
|
||||
const uint8_t* ret = input_buffer_peek(in, lenp);
|
||||
|
||||
in->pos += *lenp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char*
|
||||
input_buffer_currentline(InputBuffer* in, size_t* len) {
|
||||
size_t i;
|
||||
|
||||
if((i = byte_rchr(input_buffer_data(in), in->pos, '\n')) < in->pos)
|
||||
i++;
|
||||
|
||||
if(len)
|
||||
*len = in->pos - i;
|
||||
|
||||
return (const char*)&input_buffer_data(in)[i];
|
||||
}
|
||||
|
||||
size_t
|
||||
input_buffer_column(InputBuffer* in, size_t* len) {
|
||||
size_t i;
|
||||
|
||||
if((i = byte_rchr(input_buffer_data(in), in->pos, '\n')) < in->pos)
|
||||
i++;
|
||||
|
||||
return in->pos - i;
|
||||
}
|
||||
|
||||
int
|
||||
js_offset_length(JSContext* ctx, int64_t size, int argc, JSValueConst argv[], OffsetLength* off_len_p) {
|
||||
int ret = 0;
|
||||
int64_t off = 0, len = size;
|
||||
|
||||
if(argc >= 1 && JS_IsNumber(argv[0])) {
|
||||
if(!JS_ToInt64(ctx, &off, argv[0]))
|
||||
ret = 1;
|
||||
|
||||
if(argc >= 2 && JS_IsNumber(argv[1]))
|
||||
if(!JS_ToInt64(ctx, &len, argv[1]))
|
||||
ret = 2;
|
||||
|
||||
if(size && off != size)
|
||||
off = ((off % size) + size) % size;
|
||||
|
||||
if(len >= 0)
|
||||
len = MIN_NUM(len, size - off);
|
||||
else
|
||||
len = size - off;
|
||||
|
||||
if(off_len_p) {
|
||||
off_len_p->offset = off;
|
||||
off_len_p->length = len;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
js_index_range(JSContext* ctx, int64_t size, int argc, JSValueConst argv[], IndexRange* idx_rng_p) {
|
||||
int ret = 0;
|
||||
int64_t start = 0, end = size;
|
||||
|
||||
if(argc >= 1 && JS_IsNumber(argv[0])) {
|
||||
if(!JS_ToInt64(ctx, &start, argv[0]))
|
||||
ret = 1;
|
||||
|
||||
if(argc >= 2 && JS_IsNumber(argv[1]))
|
||||
if(!JS_ToInt64(ctx, &end, argv[1]))
|
||||
ret = 2;
|
||||
|
||||
if(size > 0) {
|
||||
start = ((start % size) + size) % size;
|
||||
end = ((end % size) + size) % size;
|
||||
}
|
||||
|
||||
if(end > size)
|
||||
end = size;
|
||||
|
||||
if(idx_rng_p) {
|
||||
idx_rng_p->start = start;
|
||||
idx_rng_p->end = end;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
screen_size(int size[2]) {
|
||||
#ifdef _WIN32
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
|
||||
size[0] = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
size[1] = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
return 0;
|
||||
|
||||
#elif defined(HAVE_TERMIOS_H)
|
||||
{
|
||||
struct winsize w = {.ws_col = -1, .ws_row = -1};
|
||||
|
||||
if(isatty(STDIN_FILENO))
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &w);
|
||||
else if(isatty(STDOUT_FILENO))
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
else if(isatty(STDERR_FILENO))
|
||||
ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
size[0] = w.ws_col;
|
||||
size[1] = w.ws_row;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
size[0] = 80;
|
||||
size[1] = 25;
|
||||
return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#undef js_realloc_rt
|
||||
void
|
||||
js_dbuf_allocator(JSContext* ctx, DynBuf* s) {
|
||||
dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc*)js_realloc_rt);
|
||||
}
|
||||
|
||||
inline int
|
||||
input_buffer_peekc(InputBuffer* in, size_t* lenp) {
|
||||
const uint8_t *pos, *end, *next;
|
||||
int cp;
|
||||
pos = input_buffer_data(in) + in->pos;
|
||||
end = input_buffer_data(in) + input_buffer_length(in);
|
||||
cp = unicode_from_utf8(pos, end - pos, &next);
|
||||
|
||||
*lenp = next - pos;
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
inline int
|
||||
input_buffer_putc(InputBuffer* in, unsigned int c, JSContext* ctx) {
|
||||
int len;
|
||||
|
||||
if(in->pos + UTF8_CHAR_LEN_MAX > in->size)
|
||||
if(block_realloc(&in->block, in->pos + UTF8_CHAR_LEN_MAX, ctx))
|
||||
return -1;
|
||||
|
||||
len = unicode_to_utf8(&in->data[in->pos], c);
|
||||
|
||||
in->pos += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
dbuf_bitflags(DynBuf* db, uint32_t bits, const char* const names[]) {
|
||||
size_t i, n = 0;
|
||||
for(i = 0; i < sizeof(bits) * 8; i++) {
|
||||
if(bits & (1 << i)) {
|
||||
size_t len = strlen(names[i]);
|
||||
if(n) {
|
||||
n++;
|
||||
dbuf_putstr(db, "|");
|
||||
}
|
||||
dbuf_append(db, names[i], len);
|
||||
n += len;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
348
src/quickjs/buffer-utils.h
Normal file
348
src/quickjs/buffer-utils.h
Normal file
@@ -0,0 +1,348 @@
|
||||
#ifndef BUFFER_UTILS_H
|
||||
#define BUFFER_UTILS_H
|
||||
|
||||
#include <quickjs.h>
|
||||
#include <cutils.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "char-utils.h"
|
||||
|
||||
/**
|
||||
* \defgroup buffer-utils buffer-utils: Buffer Utilities
|
||||
* @{
|
||||
*/
|
||||
int64_t array_search(void* a, size_t m, size_t elsz, void* needle);
|
||||
#define array_contains(a, m, elsz, needle) (array_search((a), (m), (elsz), (needle)) != -1)
|
||||
|
||||
size_t ansi_length(const char*, size_t);
|
||||
size_t ansi_skip(const char*, size_t);
|
||||
size_t ansi_truncate(const char*, size_t, size_t limit);
|
||||
int64_t array_search(void*, size_t, size_t elsz, void* needle);
|
||||
char* str_escape(const char*);
|
||||
|
||||
char* byte_escape(const void*, size_t);
|
||||
size_t byte_findb(const void*, size_t, const void* what, size_t wlen);
|
||||
size_t byte_finds(const void*, size_t, const char* what);
|
||||
size_t byte_equal(const void* s, size_t n, const void* t);
|
||||
void byte_copy(void* out, size_t len, const void* in);
|
||||
void byte_copyr(void* out, size_t len, const void* in);
|
||||
size_t byte_rchrs(const char* in, size_t len, const char needles[], size_t nn);
|
||||
|
||||
#define DBUF_INIT_0() \
|
||||
(DynBuf) { 0, 0, 0, 0, 0, 0 }
|
||||
#define DBUF_INIT_CTX(ctx) \
|
||||
(DynBuf) { 0, 0, 0, 0, (DynBufReallocFunc*)js_realloc_rt, JS_GetRuntime(ctx) }
|
||||
|
||||
extern const uint8_t escape_url_tab[256], escape_noquote_tab[256], escape_singlequote_tab[256], escape_doublequote_tab[256], escape_backquote_tab[256];
|
||||
|
||||
char* dbuf_at_n(const DynBuf*, size_t, size_t* n, char sep);
|
||||
const char* dbuf_last_line(DynBuf*, size_t*);
|
||||
int dbuf_prepend(DynBuf*, const uint8_t*, size_t len);
|
||||
void dbuf_put_colorstr(DynBuf*, const char*, const char* color, int with_color);
|
||||
void dbuf_put_escaped_pred(DynBuf*, const char*, size_t len, int (*pred)(int));
|
||||
void dbuf_put_escaped_table(DynBuf*, const char*, size_t len, const uint8_t table[256]);
|
||||
void dbuf_put_unescaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]);
|
||||
void dbuf_put_unescaped_pred(DynBuf*, const char*, size_t len, int (*pred)());
|
||||
void dbuf_put_escaped(DynBuf*, const char*, size_t len);
|
||||
void dbuf_put_value(DynBuf*, JSContext*, JSValue value);
|
||||
void dbuf_put_uint32(DynBuf* db, uint32_t num);
|
||||
void dbuf_put_atom(DynBuf* db, JSContext* ctx, JSAtom atom);
|
||||
int dbuf_reserve_start(DynBuf*, size_t);
|
||||
uint8_t* dbuf_reserve(DynBuf*, size_t);
|
||||
size_t dbuf_token_pop(DynBuf*, char);
|
||||
size_t dbuf_token_push(DynBuf*, const char*, size_t len, char delim);
|
||||
JSValue dbuf_tostring_free(DynBuf*, JSContext*);
|
||||
ssize_t dbuf_load(DynBuf*, const char*);
|
||||
int dbuf_vprintf(DynBuf*, const char*, va_list);
|
||||
|
||||
int screen_size(int size[2]);
|
||||
|
||||
static inline int
|
||||
dbuf_putm(DynBuf* db, ...) {
|
||||
int r = 0;
|
||||
va_list a;
|
||||
const char* s;
|
||||
va_start(a, db);
|
||||
while((s = va_arg(a, char*)))
|
||||
if(dbuf_putstr(db, s))
|
||||
return -1;
|
||||
va_end(a);
|
||||
return r;
|
||||
}
|
||||
|
||||
#define dbuf_append(d, x, n) dbuf_put((d), (const uint8_t*)(x), (n))
|
||||
|
||||
static inline size_t
|
||||
dbuf_count(DynBuf* db, int ch) {
|
||||
return byte_count(db->buf, db->size, ch);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dbuf_0(DynBuf* db) {
|
||||
dbuf_putc(db, '\0');
|
||||
db->size--;
|
||||
}
|
||||
|
||||
static inline void
|
||||
dbuf_zero(DynBuf* db) {
|
||||
dbuf_realloc(db, 0);
|
||||
db->size = 0;
|
||||
}
|
||||
|
||||
size_t dbuf_bitflags(DynBuf* db, uint32_t bits, const char* const names[]);
|
||||
|
||||
#define js_dbuf_init(ctx, buf) dbuf_init2((buf), (ctx), (realloc_func*)&utils_js_realloc)
|
||||
#define js_dbuf_init_rt(rt, buf) dbuf_init2((buf), (rt), (realloc_func*)&utils_js_realloc_rt)
|
||||
|
||||
void js_dbuf_allocator(JSContext* ctx, DynBuf* s);
|
||||
|
||||
typedef struct {
|
||||
uint8_t* base;
|
||||
size_t size;
|
||||
} MemoryBlock;
|
||||
|
||||
static inline void
|
||||
block_init(MemoryBlock* mb) {
|
||||
mb->base = 0;
|
||||
mb->size = 0;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
static inline void* block_data(const MemoryBlock* mb) { return mb->base; }
|
||||
static inline size_t block_length(const MemoryBlock* mb) { return mb->size; }
|
||||
static inline void* block_begin(const MemoryBlock* mb) { return mb->base; }
|
||||
static inline void* block_end(const MemoryBlock* mb) { return mb->base + mb->size; }
|
||||
/* clang-format on */
|
||||
|
||||
static inline BOOL
|
||||
block_arraybuffer(MemoryBlock* mb, JSValueConst ab, JSContext* ctx) {
|
||||
mb->base = JS_GetArrayBuffer(ctx, &mb->size, ab);
|
||||
return mb->base != 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t *start, *end;
|
||||
} PointerRange;
|
||||
|
||||
static inline void
|
||||
range_init(PointerRange* pr) {
|
||||
pr->end = pr->start = 0;
|
||||
}
|
||||
|
||||
static inline PointerRange
|
||||
range_from(const MemoryBlock* mb) {
|
||||
return (PointerRange){mb->base, mb->base + mb->size};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int64_t start, end;
|
||||
} IndexRange;
|
||||
|
||||
typedef struct {
|
||||
int64_t offset, length;
|
||||
} OffsetLength;
|
||||
|
||||
#define OFFSET_INIT() \
|
||||
(OffsetLength) { 0, INT64_MAX }
|
||||
|
||||
static inline void
|
||||
offset_init(OffsetLength* ol) {
|
||||
ol->offset = 0;
|
||||
ol->length = INT64_MAX;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
offset_is_default(const OffsetLength* ol) {
|
||||
return ol->offset == 0 && ol->length == INT64_MAX;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
offset_data(const OffsetLength* ol, const void* x) {
|
||||
return (uint8_t*)x + ol->offset;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
offset_size(const OffsetLength* ol, size_t n) {
|
||||
if(ol->length == -1)
|
||||
return (signed long)n - ol->offset;
|
||||
return MIN_NUM(ol->length, (signed long)n - ol->offset);
|
||||
}
|
||||
|
||||
static inline MemoryBlock
|
||||
offset_block(const OffsetLength* ol, const void* x, size_t n) {
|
||||
return (MemoryBlock){offset_data(ol, x), offset_size(ol, n)};
|
||||
}
|
||||
|
||||
static inline PointerRange
|
||||
offset_range(const OffsetLength* ol, const void* x, size_t n) {
|
||||
MemoryBlock mb = offset_block(ol, x, n);
|
||||
return range_from(&mb);
|
||||
}
|
||||
|
||||
static inline OffsetLength
|
||||
offset_slice(const OffsetLength ol, int64_t start, int64_t end) {
|
||||
if(start < 0)
|
||||
start = ol.length + (start % ol.length);
|
||||
else if(start > ol.length)
|
||||
start = ol.length;
|
||||
if(end < 0)
|
||||
end = ol.length + (end % ol.length);
|
||||
else if(end > ol.length)
|
||||
end = ol.length;
|
||||
|
||||
return (OffsetLength){start, end - start};
|
||||
}
|
||||
|
||||
static inline OffsetLength
|
||||
offset_offset(const OffsetLength* ol, const OffsetLength* by) {
|
||||
OffsetLength ret;
|
||||
ret.offset = ol->offset + by->offset;
|
||||
ret.length = MIN_NUM(by->length, ol->length - by->offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline OffsetLength
|
||||
offset_from_indexrange(const IndexRange* ir) {
|
||||
OffsetLength ret;
|
||||
ret.offset = ir->start;
|
||||
ret.length = ir->end - ir->start;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline JSValue
|
||||
offset_typedarray(OffsetLength* ol, JSValueConst array, JSContext* ctx) {
|
||||
JSValue ret;
|
||||
size_t offset, length;
|
||||
|
||||
ret = JS_GetTypedArrayBuffer(ctx, array, &offset, &length, NULL);
|
||||
|
||||
if(!JS_IsException(ret)) {
|
||||
ol->offset = offset;
|
||||
ol->length = length;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline IndexRange
|
||||
indexrange_from_offset(const OffsetLength* ol) {
|
||||
IndexRange ret;
|
||||
ret.start = ol->offset;
|
||||
ret.end = ol->offset + ol->length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline MemoryBlock
|
||||
block_range(const MemoryBlock* mb, const OffsetLength* range) {
|
||||
MemoryBlock ret;
|
||||
ret.base = mb->base + range->offset;
|
||||
ret.size = MIN_NUM((size_t)range->length, mb->size - range->offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
block_realloc(MemoryBlock* mb, size_t new_size, JSContext* ctx) {
|
||||
if((mb->base = js_realloc(ctx, mb->base, new_size))) {
|
||||
mb->size = new_size;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct InputBuffer {
|
||||
union {
|
||||
MemoryBlock block;
|
||||
struct {
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
};
|
||||
};
|
||||
size_t pos;
|
||||
void (*free)(JSContext*, const char*, JSValue);
|
||||
JSValue value;
|
||||
OffsetLength range;
|
||||
} InputBuffer;
|
||||
|
||||
static inline void
|
||||
input_buffer_free_default(JSContext* ctx, const char* str, JSValue val) {
|
||||
if(JS_IsString(val))
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if(!JS_IsUndefined(val))
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
|
||||
InputBuffer js_input_buffer(JSContext* ctx, JSValueConst value);
|
||||
InputBuffer js_input_chars(JSContext* ctx, JSValueConst value);
|
||||
InputBuffer js_input_args(JSContext* ctx, int argc, JSValueConst argv[]);
|
||||
InputBuffer js_output_args(JSContext* ctx, int argc, JSValueConst argv[]);
|
||||
|
||||
InputBuffer input_buffer_clone(const InputBuffer* in, JSContext* ctx);
|
||||
BOOL input_buffer_valid(const InputBuffer* in);
|
||||
void input_buffer_dump(const InputBuffer* in, DynBuf* db);
|
||||
void input_buffer_free(InputBuffer* in, JSContext* ctx);
|
||||
|
||||
static inline uint8_t*
|
||||
input_buffer_data(const InputBuffer* in) {
|
||||
return offset_data(&in->range, in->data);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
input_buffer_length(const InputBuffer* in) {
|
||||
return offset_size(&in->range, in->size);
|
||||
}
|
||||
|
||||
static inline MemoryBlock
|
||||
input_buffer_block(InputBuffer* in) {
|
||||
return (MemoryBlock){input_buffer_data(in), input_buffer_length(in)};
|
||||
}
|
||||
|
||||
static inline MemoryBlock*
|
||||
input_buffer_blockptr(InputBuffer* in) {
|
||||
return &in->block;
|
||||
}
|
||||
|
||||
const uint8_t* input_buffer_get(InputBuffer* in, size_t* lenp);
|
||||
const uint8_t* input_buffer_peek(InputBuffer* in, size_t* lenp);
|
||||
const char* input_buffer_currentline(InputBuffer*, size_t* len);
|
||||
size_t input_buffer_column(InputBuffer*, size_t* len);
|
||||
|
||||
int input_buffer_peekc(InputBuffer* in, size_t* lenp);
|
||||
int input_buffer_putc(InputBuffer*, unsigned int, JSContext*);
|
||||
|
||||
static inline int
|
||||
input_buffer_getc(InputBuffer* in) {
|
||||
size_t n;
|
||||
int ret;
|
||||
ret = input_buffer_peekc(in, &n);
|
||||
in->pos += n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
input_buffer_begin(const InputBuffer* in) {
|
||||
return input_buffer_data(in);
|
||||
}
|
||||
|
||||
static inline void*
|
||||
input_buffer_end(const InputBuffer* in) {
|
||||
return input_buffer_data(in) + input_buffer_length(in);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
input_buffer_eof(const InputBuffer* in) {
|
||||
return in->pos == input_buffer_length(in);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
input_buffer_remain(const InputBuffer* in) {
|
||||
return input_buffer_length(in) - in->pos;
|
||||
}
|
||||
|
||||
int js_offset_length(JSContext*, int64_t size, int argc, JSValueConst argv[], OffsetLength* off_len_p);
|
||||
int js_index_range(JSContext*, int64_t size, int argc, JSValueConst argv[], IndexRange* idx_rng_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(BUFFER_UTILS) */
|
||||
578
src/quickjs/char-utils.c
Normal file
578
src/quickjs/char-utils.c
Normal file
@@ -0,0 +1,578 @@
|
||||
#include "char-utils.h"
|
||||
#include "libutf.h"
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
|
||||
#include <winnls.h>
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup char-utils
|
||||
* @{
|
||||
*/
|
||||
size_t
|
||||
token_length(const char* str, size_t len, char delim) {
|
||||
const char *s, *e;
|
||||
size_t pos;
|
||||
|
||||
for(s = str, e = s + len; s < e; s += pos + 1) {
|
||||
pos = byte_chr(s, e - s, delim);
|
||||
|
||||
if(s + pos == e)
|
||||
break;
|
||||
|
||||
if(pos == 0 || s[pos - 1] != '\\') {
|
||||
s += pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s - str;
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_ulong(char* dest, uint32_t i) {
|
||||
uint32_t len, tmp, len2;
|
||||
|
||||
for(len = 1, tmp = i; tmp > 9; ++len)
|
||||
tmp /= 10;
|
||||
|
||||
if(dest)
|
||||
for(tmp = i, dest += len, len2 = len + 1; --len2; tmp /= 10)
|
||||
*--dest = (char)((tmp % 10) + '0');
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_longlong(char* dest, int64_t i) {
|
||||
if(i < 0) {
|
||||
if(dest)
|
||||
*dest++ = '-';
|
||||
return fmt_ulonglong(dest, (uint64_t)-i) + 1;
|
||||
}
|
||||
|
||||
return fmt_ulonglong(dest, (uint64_t)i);
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_ulonglong(char* dest, uint64_t i) {
|
||||
size_t len;
|
||||
uint64_t tmp, len2;
|
||||
|
||||
for(len = 1, tmp = i; tmp > 9ll; ++len)
|
||||
tmp /= 10ll;
|
||||
|
||||
if(dest)
|
||||
for(tmp = i, dest += len, len2 = len + 1; --len2; tmp /= 10ll)
|
||||
*--dest = (tmp % 10ll) + '0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#define tohex(c) (char)((c) >= 10 ? (c)-10 + 'a' : (c) + '0')
|
||||
|
||||
size_t
|
||||
fmt_xlonglong(char* dest, uint64_t i) {
|
||||
uint64_t len, tmp;
|
||||
|
||||
for(len = 1, tmp = i; tmp > 15ll; ++len)
|
||||
tmp >>= 4ll;
|
||||
|
||||
if(dest)
|
||||
for(tmp = i, dest += len;;) {
|
||||
*--dest = tohex(tmp & 15ll);
|
||||
|
||||
if(!(tmp >>= 4ll))
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_xlonglong0(char* dest, uint64_t num, size_t n) {
|
||||
size_t i = 0, len;
|
||||
|
||||
if((len = fmt_xlonglong(NULL, num)) < n) {
|
||||
len = n - len;
|
||||
|
||||
while(i < len)
|
||||
dest[i++] = '0';
|
||||
}
|
||||
|
||||
i += fmt_xlonglong(&dest[i], num);
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_8long(char* dest, uint32_t i) {
|
||||
uint32_t len, tmp;
|
||||
|
||||
/* first count the number of bytes needed */
|
||||
for(len = 1, tmp = i; tmp > 7; ++len)
|
||||
tmp >>= 3;
|
||||
|
||||
if(dest)
|
||||
for(tmp = i, dest += len;;) {
|
||||
*--dest = (char)((tmp & 7) + '0');
|
||||
|
||||
if(!(tmp >>= 3))
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#define tohex(c) (char)((c) >= 10 ? (c)-10 + 'a' : (c) + '0')
|
||||
|
||||
size_t
|
||||
fmt_xlong(char* dest, uint32_t i) {
|
||||
uint32_t len, tmp;
|
||||
|
||||
/* first count the number of bytes needed */
|
||||
for(len = 1, tmp = i; tmp > 15; ++len)
|
||||
tmp >>= 4;
|
||||
|
||||
if(dest)
|
||||
for(tmp = i, dest += len;;) {
|
||||
*--dest = tohex(tmp & 15);
|
||||
|
||||
if(!(tmp >>= 4))
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
fmt_xlong0(char* dest, uint32_t num, size_t n) {
|
||||
size_t i = 0, len;
|
||||
|
||||
if((len = fmt_xlong(NULL, num)) < n) {
|
||||
len = n - len;
|
||||
|
||||
while(i < len)
|
||||
dest[i++] = '0';
|
||||
}
|
||||
|
||||
i += fmt_xlong(&dest[i], num);
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_ushort(const char* src, uint16_t* dest) {
|
||||
const char* cur;
|
||||
uint16_t l;
|
||||
|
||||
for(cur = src, l = 0; *cur >= '0' && *cur <= '9'; ++cur) {
|
||||
uint32_t tmp = l * 10ul + *cur - '0';
|
||||
|
||||
if((uint16_t)tmp != tmp)
|
||||
break;
|
||||
|
||||
l = tmp;
|
||||
}
|
||||
|
||||
if(cur > src)
|
||||
*dest = l;
|
||||
|
||||
return (size_t)(cur - src);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_uint(const char* src, uint32_t* dest) {
|
||||
uint64_t u64;
|
||||
size_t r = scan_ulonglong(src, &u64);
|
||||
*dest = u64;
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_int(const char* src, int32_t* dest) {
|
||||
int64_t i64;
|
||||
size_t r = scan_longlong(src, &i64);
|
||||
*dest = i64;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifndef MAXLONG
|
||||
#define MAXLONG (((uint32_t)-1) >> 1)
|
||||
#endif
|
||||
|
||||
size_t
|
||||
scan_longlong(const char* src, int64_t* dest) {
|
||||
size_t i, o;
|
||||
uint64_t l;
|
||||
char c = src[0];
|
||||
unsigned int neg = c == '-';
|
||||
o = c == '-' || c == '+';
|
||||
|
||||
if((i = scan_ulonglong(src + o, &l))) {
|
||||
if(i > 0ll && l > MAXLONG + neg) {
|
||||
l /= 10ll;
|
||||
--i;
|
||||
}
|
||||
|
||||
if(i + o)
|
||||
*dest = (int64_t)(c == '-' ? -l : l);
|
||||
|
||||
return i + o;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_ulonglong(const char* src, uint64_t* dest) {
|
||||
const char* tmp = src;
|
||||
uint64_t l = 0;
|
||||
unsigned char c;
|
||||
|
||||
while((c = (unsigned char)(*tmp - '0')) < 10) {
|
||||
uint64_t n;
|
||||
n = l << 3ll;
|
||||
|
||||
if((n >> 3ll) != l)
|
||||
break;
|
||||
|
||||
if(n + (l << 1ll) < n)
|
||||
break;
|
||||
|
||||
n += l << 1ll;
|
||||
|
||||
if(n + c < n)
|
||||
break;
|
||||
|
||||
l = n + c;
|
||||
++tmp;
|
||||
}
|
||||
|
||||
if(tmp - src)
|
||||
*dest = l;
|
||||
|
||||
return (size_t)(tmp - src);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_xlonglong(const char* src, uint64_t* dest) {
|
||||
const char* tmp = src;
|
||||
int64_t l = 0;
|
||||
unsigned char c;
|
||||
|
||||
while((c = scan_fromhex(*tmp)) < 16) {
|
||||
l = (l << 4) + c;
|
||||
++tmp;
|
||||
}
|
||||
|
||||
*dest = l;
|
||||
return tmp - src;
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_8longn(const char* src, size_t n, uint32_t* dest) {
|
||||
const char* tmp = src;
|
||||
uint32_t l = 0;
|
||||
unsigned char c;
|
||||
|
||||
while(n-- > 0 && (c = (unsigned char)(*tmp - '0')) < 8) {
|
||||
if(l >> (sizeof(l) * 8 - 3))
|
||||
break;
|
||||
|
||||
l = l * 8 + c;
|
||||
++tmp;
|
||||
}
|
||||
|
||||
*dest = l;
|
||||
return (size_t)(tmp - src);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_whitenskip(const char* s, size_t limit) {
|
||||
const char *t, *u;
|
||||
|
||||
for(t = s, u = t + limit; t < u; ++t)
|
||||
if(!is_whitespace_char(*t))
|
||||
break;
|
||||
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_nonwhitenskip(const char* s, size_t limit) {
|
||||
const char *t, *u;
|
||||
|
||||
for(t = s, u = t + limit; t < u; ++t)
|
||||
if(is_whitespace_char(*t))
|
||||
break;
|
||||
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_line(const char* s, size_t limit) {
|
||||
const char *t, *u;
|
||||
|
||||
for(t = s, u = s + limit; t < u; ++t)
|
||||
if(*t == '\n' || *t == '\r')
|
||||
break;
|
||||
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_lineskip(const char* s, size_t limit) {
|
||||
const char *t, *u;
|
||||
|
||||
for(t = s, u = s + limit; t < u; ++t)
|
||||
if(*t == '\n') {
|
||||
++t;
|
||||
break;
|
||||
}
|
||||
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_lineskip_escaped(const char* s, size_t limit) {
|
||||
const char *t, *u;
|
||||
|
||||
for(t = s, u = s + limit; t < u; ++t) {
|
||||
if(*t == '\\') {
|
||||
++t;
|
||||
continue;
|
||||
}
|
||||
if(*t == '\n') {
|
||||
++t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
size_t
|
||||
scan_eolskip(const char* s, size_t limit) {
|
||||
size_t n = 0;
|
||||
|
||||
if(n + 1 < limit && s[0] == '\r' && s[1] == '\n')
|
||||
n += 2;
|
||||
else if(n < limit && s[0] == '\n')
|
||||
n += 1;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
utf8_strlen(const void* in, size_t len) {
|
||||
const uint8_t *pos, *end, *next;
|
||||
size_t i = 0;
|
||||
|
||||
for(pos = (const uint8_t*)in, end = pos + len; pos < end; pos = next, ++i)
|
||||
unicode_from_utf8(pos, end - pos, &next);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
|
||||
wchar_t*
|
||||
utf8_towcs(const char* s) {
|
||||
int len = (int)strlen(s);
|
||||
int n = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0);
|
||||
wchar_t* ret;
|
||||
|
||||
if((ret = (wchar_t*)malloc((n + 1) * sizeof(wchar_t)))) {
|
||||
MultiByteToWideChar(CP_UTF8, 0, s, len, ret, n);
|
||||
ret[n] = L'\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char*
|
||||
utf8_fromwcs(const wchar_t* wstr) {
|
||||
int len = (int)wcslen(wstr);
|
||||
int n = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
||||
char* ret;
|
||||
|
||||
if((ret = malloc((n + 1)))) {
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, len, ret, n, NULL, NULL);
|
||||
ret[n] = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL
|
||||
utf16_multiword(const void* in) {
|
||||
const uint16_t* p16 = in;
|
||||
LibutfC16Type type = libutf_c16_type(p16[0]);
|
||||
|
||||
return !((LIBUTF_UTF16_NOT_SURROGATE == type) || (LIBUTF_UTF16_SURROGATE_HIGH != type || LIBUTF_UTF16_SURROGATE_LOW != libutf_c16_type(p16[1])));
|
||||
}
|
||||
|
||||
int
|
||||
case_lowerc(int c) {
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
case_starts(const char* a, const char* b) {
|
||||
const char *s, *t;
|
||||
|
||||
for(s = a, t = b;; ++s, ++t) {
|
||||
unsigned char x, y;
|
||||
|
||||
if(!*t)
|
||||
return 1;
|
||||
|
||||
x = case_lowerc(*s);
|
||||
y = case_lowerc(*t);
|
||||
|
||||
if(x != y)
|
||||
break;
|
||||
|
||||
if(!x)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
case_diffb(const void* S, size_t len, const void* T) {
|
||||
unsigned char x, y;
|
||||
const char *s, *t;
|
||||
|
||||
for(s = (const char*)S, t = (const char*)T; len > 0;) {
|
||||
--len;
|
||||
x = case_lowerc(*s);
|
||||
y = case_lowerc(*t);
|
||||
|
||||
++s;
|
||||
++t;
|
||||
|
||||
if(x != y)
|
||||
return ((int)(unsigned int)x) - ((int)(unsigned int)y);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
case_findb(const void* haystack, size_t hlen, const void* what, size_t wlen) {
|
||||
size_t i, last;
|
||||
const char* s = haystack;
|
||||
|
||||
if(hlen < wlen)
|
||||
return hlen;
|
||||
|
||||
last = hlen - wlen;
|
||||
|
||||
for(i = 0; i <= last; i++, s++)
|
||||
if(!case_diffb(s, wlen, what))
|
||||
return i;
|
||||
|
||||
return hlen;
|
||||
}
|
||||
|
||||
size_t
|
||||
case_finds(const void* haystack, const char* what) {
|
||||
return case_findb(haystack, strlen(haystack), what, strlen(what));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
write_file(const char* file, const void* buf, size_t len) {
|
||||
FILE* f;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if((f = fopen(file, "w+")))
|
||||
switch(fwrite(buf, len, 1, f)) {
|
||||
case 1: {
|
||||
ret = len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(f);
|
||||
ret = ftell(f);
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
puts_file(const char* file, const char* s) {
|
||||
return write_file(file, s, strlen(s));
|
||||
}
|
||||
|
||||
size_t
|
||||
u64toa(char* x, uint64_t num, int base) {
|
||||
size_t len = 0;
|
||||
uint64_t n = num;
|
||||
|
||||
do {
|
||||
n /= base;
|
||||
len++;
|
||||
x++;
|
||||
} while(n != 0);
|
||||
|
||||
*x-- = '\0';
|
||||
|
||||
do {
|
||||
char c = num % base;
|
||||
num /= base;
|
||||
|
||||
if(c >= 10)
|
||||
c += 'a' - '0' - 10;
|
||||
*x-- = c + '0';
|
||||
} while(num != 0);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
i64toa(char* x, int64_t num, int base) {
|
||||
size_t pos = 0, len;
|
||||
|
||||
if(num < 0) {
|
||||
x[pos++] = '-';
|
||||
num = -num;
|
||||
}
|
||||
|
||||
len = u64toa(&x[pos], num, base);
|
||||
|
||||
return pos + len;
|
||||
}
|
||||
|
||||
size_t
|
||||
str_findb(const char* s1, const char* x, size_t n) {
|
||||
const char* b;
|
||||
size_t i, j, len = strlen(s1);
|
||||
|
||||
if(len >= n) {
|
||||
size_t end = len - n + 1;
|
||||
|
||||
for(i = 0; i < end; i++) {
|
||||
b = &s1[i];
|
||||
|
||||
for(j = 0; x[j] == b[j];)
|
||||
if(++j == n)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
str_find(const void* s, const void* what) {
|
||||
return str_findb(s, what, strlen(what));
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
441
src/quickjs/char-utils.h
Normal file
441
src/quickjs/char-utils.h
Normal file
@@ -0,0 +1,441 @@
|
||||
#ifndef CHAR_UTILS_H
|
||||
#define CHAR_UTILS_H
|
||||
|
||||
#include <cutils.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* \defgroup char-utils char-utils: Character Utilities
|
||||
* @{
|
||||
*/
|
||||
#define is_control_char(c) ((c) == '\a' || (c) == '\b' || (c) == '\t' || (c) == '\n' || (c) == '\v' || (c) == '\f' || (c) == '\r')
|
||||
#define is_alphanumeric_char(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
|
||||
|
||||
#define is_digit_char(c) ((c) >= '0' && (c) <= '9')
|
||||
#define is_print_char(c) ((c) >= ' ' && (c) <= '\x7f')
|
||||
#define is_newline_char(c) ((c) == '\n')
|
||||
#define is_identifier_char(c) (is_alphanumeric_char(c) || is_digit_char(c) || (c) == '$' || (c) == '_')
|
||||
#define is_whitespace_char(c) ((c) == ' ' || (c) == '\t' || (c) == '\v' || (c) == '\n' || (c) == '\r')
|
||||
|
||||
#define str_equal(s, t) (!strcmp((s), (t)))
|
||||
|
||||
static inline int
|
||||
escape_char_pred(int c) {
|
||||
static const unsigned char table[256] = {
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0x27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
return table[(unsigned char)c];
|
||||
}
|
||||
|
||||
static inline int
|
||||
unescape_char_pred(int c) {
|
||||
switch(c) {
|
||||
case 'b': return 8;
|
||||
case 'f': return 12;
|
||||
case 'n': return 10;
|
||||
case 'r': return 13;
|
||||
case 't': return 9;
|
||||
case 'v': return 11;
|
||||
case '\'': return 39;
|
||||
case '\\': return 92;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_escape_char(int c) {
|
||||
return is_control_char(c) || c == '\\' || c == '\'' || c == 0x1b || c == 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_backslash_char(int c) {
|
||||
return c == '\\';
|
||||
}
|
||||
|
||||
//#define is_dot_char(c) ((c) == '.')0
|
||||
//#define is_backslash_char(c) ((c) == '\\')
|
||||
|
||||
static inline int
|
||||
is_dot_char(int c) {
|
||||
return c == '.';
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_identifier(const char* str) {
|
||||
if(!((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z') || *str == '$' || *str == '_'))
|
||||
return 0;
|
||||
|
||||
while(*++str)
|
||||
if(!is_identifier_char(*str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_integer(const char* str) {
|
||||
if(*str == '-')
|
||||
++str;
|
||||
|
||||
if(!(*str >= '1' && *str <= '9') && !(*str == '0' && str[1] == '\0'))
|
||||
return 0;
|
||||
|
||||
while(*++str)
|
||||
if(!is_digit_char(*str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
byte_count(const void* s, size_t n, char c) {
|
||||
const uint8_t* t;
|
||||
uint8_t ch = (uint8_t)c;
|
||||
size_t count;
|
||||
|
||||
for(t = (uint8_t*)s, count = 0; n; ++t, --n)
|
||||
if(*t == ch)
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
byte_chr(const void* str, size_t len, char c) {
|
||||
const char* s = memchr(str, c, len);
|
||||
|
||||
if(s)
|
||||
return s - (const char*)str;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
byte_rchr(const void* haystack, size_t len, char needle) {
|
||||
const char *s, *t;
|
||||
|
||||
for(s = (const char*)haystack, t = s + len;;) {
|
||||
--t;
|
||||
|
||||
if(s > t)
|
||||
break;
|
||||
|
||||
if(*t == needle)
|
||||
return (size_t)(t - s);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*size_t
|
||||
byte_rchr(const void* str, size_t len, char c) {
|
||||
const char* s = memrchr(str, c, len);
|
||||
if(s)
|
||||
return s - (const char*)str;
|
||||
return len;
|
||||
}*/
|
||||
|
||||
static inline size_t
|
||||
byte_chrs(const void* str, size_t len, const char needle[], size_t nl) {
|
||||
const char *s, *t;
|
||||
|
||||
for(s = str, t = s + len; s != t; s++)
|
||||
if(byte_chr(needle, nl, *s) < nl)
|
||||
break;
|
||||
|
||||
return s - (const char*)str;
|
||||
}
|
||||
|
||||
static inline int
|
||||
byte_diff(const void* a, size_t len, const void* b) {
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < len; ++i) {
|
||||
int r = ((unsigned char*)a)[i] - ((unsigned char*)b)[i];
|
||||
|
||||
if(r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
byte_diff2(const char* a, size_t alen, const char* b, size_t blen) {
|
||||
|
||||
if(alen < blen)
|
||||
return -b[alen];
|
||||
|
||||
if(blen < alen)
|
||||
return a[blen];
|
||||
|
||||
return byte_diff(a, alen, b);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_chr(const char* in, char needle) {
|
||||
const char *t, c = needle;
|
||||
|
||||
for(t = in; *t; ++t)
|
||||
if(*t == c)
|
||||
break;
|
||||
|
||||
return (size_t)(t - in);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_chrs(const char* in, const char needles[], size_t nn) {
|
||||
const char* t;
|
||||
size_t i;
|
||||
|
||||
for(t = in; *t; ++t)
|
||||
for(i = 0; i < nn; i++)
|
||||
if(*t == needles[i])
|
||||
return (size_t)(t - in);
|
||||
|
||||
return (size_t)(t - in);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_rchr(const char* s, char needle) {
|
||||
const char *in, *found = 0;
|
||||
|
||||
for(in = s; *in; ++in)
|
||||
if(*in == needle)
|
||||
found = in;
|
||||
|
||||
return (size_t)((found ? found : in) - s);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_rchrs(const char* in, const char needles[], size_t nn) {
|
||||
const char *s, *found = 0;
|
||||
size_t i;
|
||||
|
||||
for(s = in; *s; ++s)
|
||||
for(i = 0; i < nn; ++i)
|
||||
if(*s == needles[i])
|
||||
found = s;
|
||||
|
||||
return (size_t)((found ? found : s) - in);
|
||||
}
|
||||
|
||||
static inline int
|
||||
str_endb(const char* a, const char* x, size_t n) {
|
||||
size_t alen = strlen(a);
|
||||
a += alen - n;
|
||||
|
||||
return alen >= n && !memcmp(a, x, n);
|
||||
}
|
||||
|
||||
/* str_ends returns 1 if the b is a suffix of a, 0 otherwise */
|
||||
static inline int
|
||||
str_ends(const char* a, const char* b) {
|
||||
return str_endb(a, b, strlen(b));
|
||||
}
|
||||
|
||||
static inline int
|
||||
str_startb(const char* a, const char* x, size_t len) {
|
||||
size_t i;
|
||||
|
||||
for(i = 0;; i++) {
|
||||
if(i == len)
|
||||
return 1;
|
||||
if(a[i] != x[i])
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
str_start(const char* a, const char* b) {
|
||||
return str_startb(a, b, strlen(b));
|
||||
}
|
||||
|
||||
#define str_contains(s, needle) (!!strchr((s), (needle)))
|
||||
|
||||
char* str_escape(const char*);
|
||||
|
||||
static inline size_t
|
||||
str_count(const char* s, char c) {
|
||||
size_t i, count = 0;
|
||||
|
||||
for(i = 0; s[i]; i++)
|
||||
if(s[i] == c)
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_copy(char* out, const char* in) {
|
||||
char* s;
|
||||
|
||||
for(s = out; (*s = *in); ++s)
|
||||
++in;
|
||||
|
||||
return (size_t)(s - out);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
str_copyn(char* out, const char* in, size_t n) {
|
||||
char* s;
|
||||
|
||||
for(s = out; n-- && (*s = *in); ++s)
|
||||
++in;
|
||||
|
||||
*s = '\0';
|
||||
return (size_t)(s - out);
|
||||
}
|
||||
|
||||
static inline char*
|
||||
str_ndup(const char* s, size_t n) {
|
||||
char* r = malloc(n + 1);
|
||||
|
||||
if(r == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy(r, s, n);
|
||||
r[n] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t str_findb(const char*, const char*, size_t);
|
||||
size_t str_find(const void*, const void*);
|
||||
|
||||
static inline size_t
|
||||
predicate_find(const char* str, size_t len, int (*pred)(int32_t)) {
|
||||
size_t pos;
|
||||
|
||||
for(pos = 0; pos < len; pos++)
|
||||
if(pred(str[pos]))
|
||||
break;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
lookup_find(const char* str, size_t len, const char table[256]) {
|
||||
size_t pos;
|
||||
|
||||
for(pos = 0; pos < len; pos++)
|
||||
if(table[(unsigned char)str[pos]])
|
||||
break;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline char
|
||||
escape_char_letter(char c) {
|
||||
switch(c) {
|
||||
case '\0': return '0';
|
||||
case '\a': return 'a';
|
||||
case '\b': return 'b';
|
||||
case '\t': return 't';
|
||||
case '\n': return 'n';
|
||||
case '\v': return 'v';
|
||||
case '\f': return 'f';
|
||||
case '\r': return 'r';
|
||||
case '\\': return '\\';
|
||||
case '\'': return '\'';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FMT_LONG 41 /* enough space to hold -2^127 in decimal, plus \0 */
|
||||
#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
|
||||
#define FMT_8LONG 44 /* enough space to hold 2^128 - 1 in octal, plus \0 */
|
||||
#define FMT_XLONG 33 /* enough space to hold 2^128 - 1 in hexadecimal, plus \0 */
|
||||
|
||||
size_t token_length(const char*, size_t, char delim);
|
||||
size_t fmt_ulong(char*, uint32_t);
|
||||
size_t scan_ushort(const char*, uint16_t*);
|
||||
size_t fmt_longlong(char*, int64_t);
|
||||
size_t fmt_ulonglong(char*, uint64_t);
|
||||
size_t fmt_xlonglong(char*, uint64_t);
|
||||
size_t fmt_xlonglong0(char*, uint64_t, size_t);
|
||||
size_t fmt_8long(char* dest, uint32_t i);
|
||||
size_t fmt_xlong(char* dest, uint32_t num);
|
||||
size_t fmt_xlong0(char* dest, uint32_t num, size_t n);
|
||||
size_t scan_longlong(const char*, int64_t*);
|
||||
size_t scan_int(const char*, int32_t*);
|
||||
size_t scan_uint(const char*, uint32_t*);
|
||||
size_t scan_ulonglong(const char*, uint64_t*);
|
||||
size_t scan_xlonglong(const char*, uint64_t*);
|
||||
size_t scan_8longn(const char*, size_t, uint32_t* dest);
|
||||
size_t scan_whitenskip(const char*, size_t);
|
||||
size_t scan_nonwhitenskip(const char*, size_t);
|
||||
size_t scan_line(const char*, size_t);
|
||||
size_t scan_lineskip(const char*, size_t);
|
||||
size_t scan_lineskip_escaped(const char*, size_t);
|
||||
size_t scan_eolskip(const char*, size_t);
|
||||
size_t utf8_strlen(const void*, size_t);
|
||||
wchar_t* utf8_towcs(const char*);
|
||||
char* utf8_fromwcs(const wchar_t*);
|
||||
BOOL utf16_multiword(const void*);
|
||||
int case_lowerc(int);
|
||||
int case_starts(const char*, const char*);
|
||||
int case_diffb(const void*, size_t, const void* T);
|
||||
size_t case_findb(const void*, size_t, const void* what, size_t wlen);
|
||||
size_t case_finds(const void*, const char*);
|
||||
|
||||
static inline int
|
||||
scan_fromhex(unsigned char c) {
|
||||
c -= '0';
|
||||
|
||||
if(c <= 9)
|
||||
return c;
|
||||
|
||||
c &= ~0x20;
|
||||
c -= 'A' - '0';
|
||||
|
||||
if(c < 6)
|
||||
return c + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
scan_8long(const char* src, uint32_t* dest) {
|
||||
return scan_8longn(src, (size_t)-1, dest);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
utf8_charlen(const char* in, size_t len) {
|
||||
const uint8_t* next = (const void*)in;
|
||||
int r = unicode_from_utf8((const uint8_t*)in, len, &next);
|
||||
return r == -1 ? 0 : next - (const uint8_t*)in;
|
||||
}
|
||||
|
||||
static inline int
|
||||
utf8_charcode(const char* in, size_t len) {
|
||||
const uint8_t* next = (const void*)in;
|
||||
int r = unicode_from_utf8((const uint8_t*)in, len, &next);
|
||||
return next > in ? r : -1;
|
||||
}
|
||||
|
||||
BOOL utf16_multiword(const void*);
|
||||
|
||||
ssize_t write_file(const char* file, const void* buf, size_t len);
|
||||
ssize_t puts_file(const char* file, const char* s);
|
||||
|
||||
size_t u64toa(char*, uint64_t num, int base);
|
||||
size_t i64toa(char*, int64_t num, int base);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(CHAR_UTILS_H) */
|
||||
631
src/quickjs/cutils.c
Normal file
631
src/quickjs/cutils.c
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* C utilities
|
||||
*
|
||||
* Copyright (c) 2017 Fabrice Bellard
|
||||
* Copyright (c) 2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cutils.h"
|
||||
|
||||
void pstrcpy(char *buf, int buf_size, const char *str)
|
||||
{
|
||||
int c;
|
||||
char *q = buf;
|
||||
|
||||
if (buf_size <= 0)
|
||||
return;
|
||||
|
||||
for(;;) {
|
||||
c = *str++;
|
||||
if (c == 0 || q >= buf + buf_size - 1)
|
||||
break;
|
||||
*q++ = c;
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
/* strcat and truncate. */
|
||||
char *pstrcat(char *buf, int buf_size, const char *s)
|
||||
{
|
||||
int len;
|
||||
len = strlen(buf);
|
||||
if (len < buf_size)
|
||||
pstrcpy(buf + len, buf_size - len, s);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int strstart(const char *str, const char *val, const char **ptr)
|
||||
{
|
||||
const char *p, *q;
|
||||
p = str;
|
||||
q = val;
|
||||
while (*q != '\0') {
|
||||
if (*p != *q)
|
||||
return 0;
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
if (ptr)
|
||||
*ptr = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int has_suffix(const char *str, const char *suffix)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
size_t slen = strlen(suffix);
|
||||
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
|
||||
}
|
||||
|
||||
/* Dynamic buffer package */
|
||||
|
||||
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
|
||||
{
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
|
||||
{
|
||||
memset(s, 0, sizeof(*s));
|
||||
if (!realloc_func)
|
||||
realloc_func = dbuf_default_realloc;
|
||||
s->opaque = opaque;
|
||||
s->realloc_func = realloc_func;
|
||||
}
|
||||
|
||||
void dbuf_init(DynBuf *s)
|
||||
{
|
||||
dbuf_init2(s, NULL, NULL);
|
||||
}
|
||||
|
||||
/* return < 0 if error */
|
||||
int dbuf_realloc(DynBuf *s, size_t new_size)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *new_buf;
|
||||
if (new_size > s->allocated_size) {
|
||||
if (s->error)
|
||||
return -1;
|
||||
size = s->allocated_size * 3 / 2;
|
||||
if (size > new_size)
|
||||
new_size = size;
|
||||
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
|
||||
if (!new_buf) {
|
||||
s->error = TRUE;
|
||||
return -1;
|
||||
}
|
||||
s->buf = new_buf;
|
||||
s->allocated_size = new_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
||||
{
|
||||
size_t end;
|
||||
end = offset + len;
|
||||
if (dbuf_realloc(s, end))
|
||||
return -1;
|
||||
memcpy(s->buf + offset, data, len);
|
||||
if (end > s->size)
|
||||
s->size = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
|
||||
{
|
||||
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||
if (dbuf_realloc(s, s->size + len))
|
||||
return -1;
|
||||
}
|
||||
memcpy_no_ub(s->buf + s->size, data, len);
|
||||
s->size += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
|
||||
{
|
||||
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||
if (dbuf_realloc(s, s->size + len))
|
||||
return -1;
|
||||
}
|
||||
memcpy(s->buf + s->size, s->buf + offset, len);
|
||||
s->size += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_putc(DynBuf *s, uint8_t c)
|
||||
{
|
||||
return dbuf_put(s, &c, 1);
|
||||
}
|
||||
|
||||
int dbuf_putstr(DynBuf *s, const char *str)
|
||||
{
|
||||
return dbuf_put(s, (const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[128];
|
||||
int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len < sizeof(buf)) {
|
||||
/* fast case */
|
||||
return dbuf_put(s, (uint8_t *)buf, len);
|
||||
} else {
|
||||
if (dbuf_realloc(s, s->size + len + 1))
|
||||
return -1;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
|
||||
fmt, ap);
|
||||
va_end(ap);
|
||||
s->size += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbuf_free(DynBuf *s)
|
||||
{
|
||||
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
|
||||
is called twice */
|
||||
if (s->buf) {
|
||||
s->realloc_func(s->opaque, s->buf, 0);
|
||||
}
|
||||
memset(s, 0, sizeof(*s));
|
||||
}
|
||||
|
||||
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
|
||||
are output. */
|
||||
int unicode_to_utf8(uint8_t *buf, unsigned int c)
|
||||
{
|
||||
uint8_t *q = buf;
|
||||
|
||||
if (c < 0x80) {
|
||||
*q++ = c;
|
||||
} else {
|
||||
if (c < 0x800) {
|
||||
*q++ = (c >> 6) | 0xc0;
|
||||
} else {
|
||||
if (c < 0x10000) {
|
||||
*q++ = (c >> 12) | 0xe0;
|
||||
} else {
|
||||
if (c < 0x00200000) {
|
||||
*q++ = (c >> 18) | 0xf0;
|
||||
} else {
|
||||
if (c < 0x04000000) {
|
||||
*q++ = (c >> 24) | 0xf8;
|
||||
} else if (c < 0x80000000) {
|
||||
*q++ = (c >> 30) | 0xfc;
|
||||
*q++ = ((c >> 24) & 0x3f) | 0x80;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
*q++ = ((c >> 18) & 0x3f) | 0x80;
|
||||
}
|
||||
*q++ = ((c >> 12) & 0x3f) | 0x80;
|
||||
}
|
||||
*q++ = ((c >> 6) & 0x3f) | 0x80;
|
||||
}
|
||||
*q++ = (c & 0x3f) | 0x80;
|
||||
}
|
||||
return q - buf;
|
||||
}
|
||||
|
||||
static const unsigned int utf8_min_code[5] = {
|
||||
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
|
||||
};
|
||||
|
||||
static const unsigned char utf8_first_code_mask[5] = {
|
||||
0x1f, 0xf, 0x7, 0x3, 0x1,
|
||||
};
|
||||
|
||||
/* return -1 if error. *pp is not updated in this case. max_len must
|
||||
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
|
||||
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
|
||||
{
|
||||
int l, c, b, i;
|
||||
|
||||
c = *p++;
|
||||
if (c < 0x80) {
|
||||
*pp = p;
|
||||
return c;
|
||||
}
|
||||
switch(c) {
|
||||
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
|
||||
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
|
||||
case 0xc8: case 0xc9: case 0xca: case 0xcb:
|
||||
case 0xcc: case 0xcd: case 0xce: case 0xcf:
|
||||
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
|
||||
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
||||
case 0xd8: case 0xd9: case 0xda: case 0xdb:
|
||||
case 0xdc: case 0xdd: case 0xde: case 0xdf:
|
||||
l = 1;
|
||||
break;
|
||||
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
|
||||
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
|
||||
case 0xe8: case 0xe9: case 0xea: case 0xeb:
|
||||
case 0xec: case 0xed: case 0xee: case 0xef:
|
||||
l = 2;
|
||||
break;
|
||||
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
|
||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
||||
l = 3;
|
||||
break;
|
||||
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
|
||||
l = 4;
|
||||
break;
|
||||
case 0xfc: case 0xfd:
|
||||
l = 5;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
/* check that we have enough characters */
|
||||
if (l > (max_len - 1))
|
||||
return -1;
|
||||
c &= utf8_first_code_mask[l - 1];
|
||||
for(i = 0; i < l; i++) {
|
||||
b = *p++;
|
||||
if (b < 0x80 || b >= 0xc0)
|
||||
return -1;
|
||||
c = (c << 6) | (b & 0x3f);
|
||||
}
|
||||
if (c < utf8_min_code[l - 1])
|
||||
return -1;
|
||||
*pp = p;
|
||||
return c;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
|
||||
|
||||
static void *rqsort_arg;
|
||||
static int (*rqsort_cmp)(const void *, const void *, void *);
|
||||
|
||||
static int rqsort_cmp2(const void *p1, const void *p2)
|
||||
{
|
||||
return rqsort_cmp(p1, p2, rqsort_arg);
|
||||
}
|
||||
|
||||
/* not reentrant, but not needed with emscripten */
|
||||
void rqsort(void *base, size_t nmemb, size_t size,
|
||||
int (*cmp)(const void *, const void *, void *),
|
||||
void *arg)
|
||||
{
|
||||
rqsort_arg = arg;
|
||||
rqsort_cmp = cmp;
|
||||
qsort(base, nmemb, size, rqsort_cmp2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
typedef void (*exchange_f)(void *a, void *b, size_t size);
|
||||
typedef int (*cmp_f)(const void *, const void *, void *opaque);
|
||||
|
||||
static void exchange_bytes(void *a, void *b, size_t size) {
|
||||
uint8_t *ap = (uint8_t *)a;
|
||||
uint8_t *bp = (uint8_t *)b;
|
||||
|
||||
while (size-- != 0) {
|
||||
uint8_t t = *ap;
|
||||
*ap++ = *bp;
|
||||
*bp++ = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void exchange_one_byte(void *a, void *b, size_t size) {
|
||||
uint8_t *ap = (uint8_t *)a;
|
||||
uint8_t *bp = (uint8_t *)b;
|
||||
uint8_t t = *ap;
|
||||
*ap = *bp;
|
||||
*bp = t;
|
||||
}
|
||||
|
||||
static void exchange_int16s(void *a, void *b, size_t size) {
|
||||
uint16_t *ap = (uint16_t *)a;
|
||||
uint16_t *bp = (uint16_t *)b;
|
||||
|
||||
for (size /= sizeof(uint16_t); size-- != 0;) {
|
||||
uint16_t t = *ap;
|
||||
*ap++ = *bp;
|
||||
*bp++ = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void exchange_one_int16(void *a, void *b, size_t size) {
|
||||
uint16_t *ap = (uint16_t *)a;
|
||||
uint16_t *bp = (uint16_t *)b;
|
||||
uint16_t t = *ap;
|
||||
*ap = *bp;
|
||||
*bp = t;
|
||||
}
|
||||
|
||||
static void exchange_int32s(void *a, void *b, size_t size) {
|
||||
uint32_t *ap = (uint32_t *)a;
|
||||
uint32_t *bp = (uint32_t *)b;
|
||||
|
||||
for (size /= sizeof(uint32_t); size-- != 0;) {
|
||||
uint32_t t = *ap;
|
||||
*ap++ = *bp;
|
||||
*bp++ = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void exchange_one_int32(void *a, void *b, size_t size) {
|
||||
uint32_t *ap = (uint32_t *)a;
|
||||
uint32_t *bp = (uint32_t *)b;
|
||||
uint32_t t = *ap;
|
||||
*ap = *bp;
|
||||
*bp = t;
|
||||
}
|
||||
|
||||
static void exchange_int64s(void *a, void *b, size_t size) {
|
||||
uint64_t *ap = (uint64_t *)a;
|
||||
uint64_t *bp = (uint64_t *)b;
|
||||
|
||||
for (size /= sizeof(uint64_t); size-- != 0;) {
|
||||
uint64_t t = *ap;
|
||||
*ap++ = *bp;
|
||||
*bp++ = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void exchange_one_int64(void *a, void *b, size_t size) {
|
||||
uint64_t *ap = (uint64_t *)a;
|
||||
uint64_t *bp = (uint64_t *)b;
|
||||
uint64_t t = *ap;
|
||||
*ap = *bp;
|
||||
*bp = t;
|
||||
}
|
||||
|
||||
static void exchange_int128s(void *a, void *b, size_t size) {
|
||||
uint64_t *ap = (uint64_t *)a;
|
||||
uint64_t *bp = (uint64_t *)b;
|
||||
|
||||
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
|
||||
uint64_t t = ap[0];
|
||||
uint64_t u = ap[1];
|
||||
ap[0] = bp[0];
|
||||
ap[1] = bp[1];
|
||||
bp[0] = t;
|
||||
bp[1] = u;
|
||||
}
|
||||
}
|
||||
|
||||
static void exchange_one_int128(void *a, void *b, size_t size) {
|
||||
uint64_t *ap = (uint64_t *)a;
|
||||
uint64_t *bp = (uint64_t *)b;
|
||||
uint64_t t = ap[0];
|
||||
uint64_t u = ap[1];
|
||||
ap[0] = bp[0];
|
||||
ap[1] = bp[1];
|
||||
bp[0] = t;
|
||||
bp[1] = u;
|
||||
}
|
||||
|
||||
static inline exchange_f exchange_func(const void *base, size_t size) {
|
||||
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
|
||||
case 0:
|
||||
if (size == sizeof(uint64_t) * 2)
|
||||
return exchange_one_int128;
|
||||
else
|
||||
return exchange_int128s;
|
||||
case 8:
|
||||
if (size == sizeof(uint64_t))
|
||||
return exchange_one_int64;
|
||||
else
|
||||
return exchange_int64s;
|
||||
case 4:
|
||||
case 12:
|
||||
if (size == sizeof(uint32_t))
|
||||
return exchange_one_int32;
|
||||
else
|
||||
return exchange_int32s;
|
||||
case 2:
|
||||
case 6:
|
||||
case 10:
|
||||
case 14:
|
||||
if (size == sizeof(uint16_t))
|
||||
return exchange_one_int16;
|
||||
else
|
||||
return exchange_int16s;
|
||||
default:
|
||||
if (size == 1)
|
||||
return exchange_one_byte;
|
||||
else
|
||||
return exchange_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||
{
|
||||
uint8_t *basep = (uint8_t *)base;
|
||||
size_t i, n, c, r;
|
||||
exchange_f swap = exchange_func(base, size);
|
||||
|
||||
if (nmemb > 1) {
|
||||
i = (nmemb / 2) * size;
|
||||
n = nmemb * size;
|
||||
|
||||
while (i > 0) {
|
||||
i -= size;
|
||||
for (r = i; (c = r * 2 + size) < n; r = c) {
|
||||
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||
c += size;
|
||||
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||
break;
|
||||
swap(basep + r, basep + c, size);
|
||||
}
|
||||
}
|
||||
for (i = n - size; i > 0; i -= size) {
|
||||
swap(basep, basep + i, size);
|
||||
|
||||
for (r = 0; (c = r * 2 + size) < i; r = c) {
|
||||
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||
c += size;
|
||||
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||
break;
|
||||
swap(basep + r, basep + c, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
|
||||
{
|
||||
return cmp(a, b, opaque) < 0 ?
|
||||
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
|
||||
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
|
||||
}
|
||||
|
||||
/* pointer based version with local stack and insertion sort threshhold */
|
||||
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||
{
|
||||
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
|
||||
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
|
||||
size_t m4, i, lt, gt, span, span2;
|
||||
int c, depth;
|
||||
exchange_f swap = exchange_func(base, size);
|
||||
exchange_f swap_block = exchange_func(base, size | 128);
|
||||
|
||||
if (nmemb < 2 || size <= 0)
|
||||
return;
|
||||
|
||||
sp->base = (uint8_t *)base;
|
||||
sp->count = nmemb;
|
||||
sp->depth = 0;
|
||||
sp++;
|
||||
|
||||
while (sp > stack) {
|
||||
sp--;
|
||||
ptr = sp->base;
|
||||
nmemb = sp->count;
|
||||
depth = sp->depth;
|
||||
|
||||
while (nmemb > 6) {
|
||||
if (++depth > 50) {
|
||||
/* depth check to ensure worst case logarithmic time */
|
||||
heapsortx(ptr, nmemb, size, cmp, opaque);
|
||||
nmemb = 0;
|
||||
break;
|
||||
}
|
||||
/* select median of 3 from 1/4, 1/2, 3/4 positions */
|
||||
/* should use median of 5 or 9? */
|
||||
m4 = (nmemb >> 2) * size;
|
||||
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
|
||||
swap(ptr, m, size); /* move the pivot to the start or the array */
|
||||
i = lt = 1;
|
||||
pi = plt = ptr + size;
|
||||
gt = nmemb;
|
||||
pj = pgt = top = ptr + nmemb * size;
|
||||
for (;;) {
|
||||
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
|
||||
if (c == 0) {
|
||||
swap(plt, pi, size);
|
||||
lt++;
|
||||
plt += size;
|
||||
}
|
||||
i++;
|
||||
pi += size;
|
||||
}
|
||||
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
|
||||
if (c == 0) {
|
||||
gt--;
|
||||
pgt -= size;
|
||||
swap(pgt, pj, size);
|
||||
}
|
||||
}
|
||||
if (pi >= pj)
|
||||
break;
|
||||
swap(pi, pj, size);
|
||||
i++;
|
||||
pi += size;
|
||||
}
|
||||
/* array has 4 parts:
|
||||
* from 0 to lt excluded: elements identical to pivot
|
||||
* from lt to pi excluded: elements smaller than pivot
|
||||
* from pi to gt excluded: elements greater than pivot
|
||||
* from gt to n excluded: elements identical to pivot
|
||||
*/
|
||||
/* move elements identical to pivot in the middle of the array: */
|
||||
/* swap values in ranges [0..lt[ and [i-lt..i[
|
||||
swapping the smallest span between lt and i-lt is sufficient
|
||||
*/
|
||||
span = plt - ptr;
|
||||
span2 = pi - plt;
|
||||
lt = i - lt;
|
||||
if (span > span2)
|
||||
span = span2;
|
||||
swap_block(ptr, pi - span, span);
|
||||
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
|
||||
swapping the smallest span between top-gt and gt-i is sufficient
|
||||
*/
|
||||
span = top - pgt;
|
||||
span2 = pgt - pi;
|
||||
pgt = top - span2;
|
||||
gt = nmemb - (gt - i);
|
||||
if (span > span2)
|
||||
span = span2;
|
||||
swap_block(pi, top - span, span);
|
||||
|
||||
/* now array has 3 parts:
|
||||
* from 0 to lt excluded: elements smaller than pivot
|
||||
* from lt to gt excluded: elements identical to pivot
|
||||
* from gt to n excluded: elements greater than pivot
|
||||
*/
|
||||
/* stack the larger segment and keep processing the smaller one
|
||||
to minimize stack use for pathological distributions */
|
||||
if (lt > nmemb - gt) {
|
||||
sp->base = ptr;
|
||||
sp->count = lt;
|
||||
sp->depth = depth;
|
||||
sp++;
|
||||
ptr = pgt;
|
||||
nmemb -= gt;
|
||||
} else {
|
||||
sp->base = pgt;
|
||||
sp->count = nmemb - gt;
|
||||
sp->depth = depth;
|
||||
sp++;
|
||||
nmemb = lt;
|
||||
}
|
||||
}
|
||||
/* Use insertion sort for small fragments */
|
||||
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
|
||||
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
|
||||
swap(pj, pj - size, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
341
src/quickjs/cutils.h
Normal file
341
src/quickjs/cutils.h
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* C utilities
|
||||
*
|
||||
* Copyright (c) 2017 Fabrice Bellard
|
||||
* Copyright (c) 2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef CUTILS_H
|
||||
#define CUTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define force_inline inline __attribute__((always_inline))
|
||||
#define no_inline __attribute__((noinline))
|
||||
#define __maybe_unused __attribute__((unused))
|
||||
|
||||
#define xglue(x, y) x ## y
|
||||
#define glue(x, y) xglue(x, y)
|
||||
#define stringify(s) tostring(s)
|
||||
#define tostring(s) #s
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||
#endif
|
||||
#ifndef countof
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
#ifndef container_of
|
||||
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
|
||||
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
|
||||
#endif
|
||||
|
||||
typedef int BOOL;
|
||||
|
||||
#ifndef FALSE
|
||||
enum {
|
||||
FALSE = 0,
|
||||
TRUE = 1,
|
||||
};
|
||||
#endif
|
||||
|
||||
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||
char *pstrcat(char *buf, int buf_size, const char *s);
|
||||
int strstart(const char *str, const char *val, const char **ptr);
|
||||
int has_suffix(const char *str, const char *suffix);
|
||||
|
||||
/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
|
||||
static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
|
||||
if (n)
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
static inline int max_int(int a, int b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int min_int(int a, int b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int64_t max_int64(int64_t a, int64_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int64_t min_int64(int64_t a, int64_t b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int clz32(unsigned int a)
|
||||
{
|
||||
return __builtin_clz(a);
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int clz64(uint64_t a)
|
||||
{
|
||||
return __builtin_clzll(a);
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int ctz32(unsigned int a)
|
||||
{
|
||||
return __builtin_ctz(a);
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int ctz64(uint64_t a)
|
||||
{
|
||||
return __builtin_ctzll(a);
|
||||
}
|
||||
|
||||
struct __attribute__((packed)) packed_u64 {
|
||||
uint64_t v;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) packed_u32 {
|
||||
uint32_t v;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) packed_u16 {
|
||||
uint16_t v;
|
||||
};
|
||||
|
||||
static inline uint64_t get_u64(const uint8_t *tab)
|
||||
{
|
||||
return ((const struct packed_u64 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline int64_t get_i64(const uint8_t *tab)
|
||||
{
|
||||
return (int64_t)((const struct packed_u64 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline void put_u64(uint8_t *tab, uint64_t val)
|
||||
{
|
||||
((struct packed_u64 *)tab)->v = val;
|
||||
}
|
||||
|
||||
static inline uint32_t get_u32(const uint8_t *tab)
|
||||
{
|
||||
return ((const struct packed_u32 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline int32_t get_i32(const uint8_t *tab)
|
||||
{
|
||||
return (int32_t)((const struct packed_u32 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline void put_u32(uint8_t *tab, uint32_t val)
|
||||
{
|
||||
((struct packed_u32 *)tab)->v = val;
|
||||
}
|
||||
|
||||
static inline uint32_t get_u16(const uint8_t *tab)
|
||||
{
|
||||
return ((const struct packed_u16 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline int32_t get_i16(const uint8_t *tab)
|
||||
{
|
||||
return (int16_t)((const struct packed_u16 *)tab)->v;
|
||||
}
|
||||
|
||||
static inline void put_u16(uint8_t *tab, uint16_t val)
|
||||
{
|
||||
((struct packed_u16 *)tab)->v = val;
|
||||
}
|
||||
|
||||
static inline uint32_t get_u8(const uint8_t *tab)
|
||||
{
|
||||
return *tab;
|
||||
}
|
||||
|
||||
static inline int32_t get_i8(const uint8_t *tab)
|
||||
{
|
||||
return (int8_t)*tab;
|
||||
}
|
||||
|
||||
static inline void put_u8(uint8_t *tab, uint8_t val)
|
||||
{
|
||||
*tab = val;
|
||||
}
|
||||
|
||||
#ifndef bswap16
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return (x >> 8) | (x << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef bswap32
|
||||
static inline uint32_t bswap32(uint32_t v)
|
||||
{
|
||||
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
|
||||
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef bswap64
|
||||
static inline uint64_t bswap64(uint64_t v)
|
||||
{
|
||||
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
|
||||
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: should take an extra argument to pass slack information to the caller */
|
||||
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
|
||||
|
||||
typedef struct DynBuf {
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t allocated_size;
|
||||
BOOL error; /* true if a memory allocation error occurred */
|
||||
DynBufReallocFunc *realloc_func;
|
||||
void *opaque; /* for realloc_func */
|
||||
} DynBuf;
|
||||
|
||||
void dbuf_init(DynBuf *s);
|
||||
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||
int dbuf_realloc(DynBuf *s, size_t new_size);
|
||||
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
|
||||
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
|
||||
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
||||
int dbuf_putc(DynBuf *s, uint8_t c);
|
||||
int dbuf_putstr(DynBuf *s, const char *str);
|
||||
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 2);
|
||||
}
|
||||
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 4);
|
||||
}
|
||||
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 8);
|
||||
}
|
||||
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||
const char *fmt, ...);
|
||||
void dbuf_free(DynBuf *s);
|
||||
static inline BOOL dbuf_error(DynBuf *s) {
|
||||
return s->error;
|
||||
}
|
||||
static inline void dbuf_set_error(DynBuf *s)
|
||||
{
|
||||
s->error = TRUE;
|
||||
}
|
||||
|
||||
#define UTF8_CHAR_LEN_MAX 6
|
||||
|
||||
int unicode_to_utf8(uint8_t *buf, unsigned int c);
|
||||
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
|
||||
|
||||
static inline BOOL is_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
|
||||
}
|
||||
|
||||
static inline BOOL is_hi_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
|
||||
}
|
||||
|
||||
static inline BOOL is_lo_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
|
||||
}
|
||||
|
||||
static inline uint32_t get_hi_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) - (0x10000 >> 10) + 0xD800;
|
||||
}
|
||||
|
||||
static inline uint32_t get_lo_surrogate(uint32_t c)
|
||||
{
|
||||
return (c & 0x3FF) | 0xDC00;
|
||||
}
|
||||
|
||||
static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
|
||||
{
|
||||
return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
|
||||
}
|
||||
|
||||
static inline int from_hex(int c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void rqsort(void *base, size_t nmemb, size_t size,
|
||||
int (*cmp)(const void *, const void *, void *),
|
||||
void *arg);
|
||||
|
||||
#endif /* CUTILS_H */
|
||||
483
src/quickjs/debug.c
Normal file
483
src/quickjs/debug.c
Normal file
@@ -0,0 +1,483 @@
|
||||
#define _IN_DEBUG_C 1
|
||||
#include "debug.h"
|
||||
#include <quickjs.h>
|
||||
#include <list.h>
|
||||
#include <cutils.h>
|
||||
#include <assert.h>
|
||||
#include "defines.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* \addtogroup debug
|
||||
* @{
|
||||
*/
|
||||
struct alloc_block {
|
||||
struct list_head link;
|
||||
const char* file;
|
||||
int line;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define ALLOC_BLOCK_SIZE sizeof(struct alloc_block)
|
||||
#define ALLOC_BLOCK(p) (((struct alloc_block*)(p)) - 1)
|
||||
#define ALLOC_PTR struct alloc_block*
|
||||
|
||||
#undef malloc
|
||||
#undef calloc
|
||||
#undef realloc
|
||||
#undef strdup
|
||||
#undef free
|
||||
#undef js_malloc
|
||||
#undef js_mallocz
|
||||
#undef js_realloc
|
||||
#undef js_strdup
|
||||
#undef js_strndup
|
||||
#undef js_free
|
||||
#undef js_malloc_usable_size
|
||||
#undef js_malloc_rt
|
||||
#undef js_mallocz_rt
|
||||
#undef js_realloc_rt
|
||||
#undef js_free_rt
|
||||
#undef js_malloc_usable_size_rt
|
||||
|
||||
thread_local struct list_head alloc_block_list = {0, 0};
|
||||
|
||||
static inline void
|
||||
add_to_list(struct list_head* el, struct list_head* head) {
|
||||
if(alloc_block_list.prev == 0 && alloc_block_list.next == 0)
|
||||
init_list_head(&alloc_block_list);
|
||||
|
||||
list_add_tail(el, head);
|
||||
}
|
||||
|
||||
int64_t
|
||||
check_pointer(void* p) {
|
||||
ALLOC_PTR ptr = ALLOC_BLOCK(p);
|
||||
struct list_head* link;
|
||||
int64_t ret = 0;
|
||||
list_for_each(link, &alloc_block_list) {
|
||||
if(link == &ptr->link)
|
||||
return ret;
|
||||
ret++;
|
||||
}
|
||||
// assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_malloc(size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = malloc(n + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_calloc(size_t m, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
m *= n;
|
||||
n = 1;
|
||||
|
||||
if((ptr = calloc(m + ALLOC_BLOCK_SIZE, 1))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_realloc(void* p, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if(p) {
|
||||
|
||||
check_pointer(p);
|
||||
|
||||
ptr = ALLOC_BLOCK(p);
|
||||
list_del(&ptr->link);
|
||||
|
||||
if(n == 0) {
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr = realloc(ptr, n + ALLOC_BLOCK_SIZE);
|
||||
} else {
|
||||
ptr = malloc(n + ALLOC_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(ptr) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_strdup(const char* s, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
size_t len = strlen(s);
|
||||
|
||||
if((ptr = malloc(len + 1 + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = len + 1;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
|
||||
memcpy(&ptr[1], s, len + 1);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
debug_free(void* p, const char* file, int line) {
|
||||
ALLOC_PTR ptr = ALLOC_BLOCK(p);
|
||||
|
||||
list_del(&ptr->link);
|
||||
|
||||
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
|
||||
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_malloc(JSContext* ctx, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = js_malloc(ctx, n + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_mallocz(JSContext* ctx, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = js_mallocz(ctx, n + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_realloc(JSContext* ctx, void* p, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if(p) {
|
||||
|
||||
check_pointer(p);
|
||||
|
||||
ptr = ALLOC_BLOCK(p);
|
||||
list_del(&ptr->link);
|
||||
|
||||
if(n == 0) {
|
||||
js_free(ctx, ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr = js_realloc(ctx, ptr, n + ALLOC_BLOCK_SIZE);
|
||||
} else {
|
||||
ptr = js_malloc(ctx, n + ALLOC_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(ptr) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_realloc2(JSContext* ctx, void* p, size_t size, size_t* pslack, const char* file, int line) {
|
||||
void* ptr;
|
||||
|
||||
if((ptr = debug_js_realloc(ctx, p, size, file, line))) {
|
||||
if(pslack) {
|
||||
size_t new_size = debug_js_malloc_usable_size(ctx, ptr, file, line);
|
||||
*pslack = (new_size > size) ? new_size - size : 0;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_strdup(JSContext* ctx, const char* s, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
size_t len = strlen(s);
|
||||
|
||||
if((ptr = js_malloc(ctx, len + 1 + ALLOC_BLOCK_SIZE))) {
|
||||
char* p = (char*)&ptr[1];
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = len + 1;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
|
||||
memcpy(p, s, len + 1);
|
||||
return p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_strndup(JSContext* ctx, const char* s, size_t len, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = js_malloc(ctx, len + 1 + ALLOC_BLOCK_SIZE))) {
|
||||
char* p = (char*)&ptr[1];
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = len + 1;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
|
||||
memcpy(p, s, len);
|
||||
p[len] = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
debug_js_malloc_usable_size(JSContext* ctx, const void* p, const char* file, int line) {
|
||||
ALLOC_PTR ptr = ALLOC_BLOCK(p);
|
||||
|
||||
return js_malloc_usable_size(ctx, ptr) - ALLOC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
debug_js_free(JSContext* ctx, void* p, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
check_pointer(p);
|
||||
ptr = ALLOC_BLOCK(p);
|
||||
list_del(&ptr->link);
|
||||
|
||||
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
|
||||
|
||||
js_free(ctx, ptr);
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_malloc_rt(JSRuntime* rt, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = js_malloc_rt(rt, n + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_mallocz_rt(JSRuntime* rt, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if((ptr = js_mallocz_rt(rt, n + ALLOC_BLOCK_SIZE))) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
debug_js_realloc_rt(JSRuntime* rt, void* p, size_t n, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
|
||||
if(p) {
|
||||
check_pointer(p);
|
||||
|
||||
ptr = ALLOC_BLOCK(p);
|
||||
list_del(&ptr->link);
|
||||
if(n == 0) {
|
||||
js_free_rt(rt, ptr);
|
||||
return 0;
|
||||
}
|
||||
ptr = js_realloc_rt(rt, ptr, n + ALLOC_BLOCK_SIZE);
|
||||
} else {
|
||||
ptr = js_malloc_rt(rt, n + ALLOC_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(ptr) {
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = n;
|
||||
|
||||
add_to_list(&ptr->link, &alloc_block_list);
|
||||
return &ptr[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
debug_js_malloc_usable_size_rt(JSRuntime* rt, const void* p, const char* file, int line) {
|
||||
ALLOC_PTR ptr = ALLOC_BLOCK(p);
|
||||
|
||||
return js_malloc_usable_size_rt(rt, ptr) - ALLOC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
debug_js_free_rt(JSRuntime* rt, void* p, const char* file, int line) {
|
||||
ALLOC_PTR ptr;
|
||||
check_pointer(p);
|
||||
|
||||
ptr = ALLOC_BLOCK(p);
|
||||
|
||||
// printf("debug_js_free_rt %p\n", p);
|
||||
|
||||
list_del(&ptr->link);
|
||||
|
||||
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
|
||||
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
|
||||
#undef malloc
|
||||
#undef calloc
|
||||
#undef realloc
|
||||
#undef strdup
|
||||
#undef free
|
||||
#undef js_malloc
|
||||
#undef js_mallocz
|
||||
#undef js_realloc
|
||||
#undef js_strdup
|
||||
#undef js_strndup
|
||||
#undef js_malloc_usable_size
|
||||
#undef js_free
|
||||
#undef js_malloc_rt
|
||||
#undef js_mallocz_rt
|
||||
#undef js_realloc_rt
|
||||
#undef js_malloc_usable_size_rt
|
||||
#undef js_free_rt
|
||||
|
||||
void*
|
||||
orig_malloc(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_calloc(size_t nelem, size_t elemsz) {
|
||||
return calloc(nelem, elemsz);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_realloc(void* ptr, size_t size) {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_strdup(const char* str) {
|
||||
return strdup(str);
|
||||
}
|
||||
|
||||
void
|
||||
orig_free(void* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_malloc(JSContext* ctx, size_t size) {
|
||||
return js_malloc(ctx, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_mallocz(JSContext* ctx, size_t size) {
|
||||
return js_mallocz(ctx, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_realloc(JSContext* ctx, void* p, size_t size) {
|
||||
return js_realloc(ctx, p, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_strdup(JSContext* ctx, const char* str) {
|
||||
return js_strdup(ctx, str);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_strndup(JSContext* ctx, const char* str, size_t size) {
|
||||
return js_strndup(ctx, str, size);
|
||||
}
|
||||
|
||||
size_t
|
||||
orig_js_malloc_usable_size(JSContext* ctx, const void* p) {
|
||||
return js_malloc_usable_size(ctx, p);
|
||||
}
|
||||
|
||||
void
|
||||
orig_js_free(JSContext* ctx, void* p) {
|
||||
return js_free(ctx, p);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_malloc_rt(JSRuntime* rt, size_t size) {
|
||||
return js_malloc_rt(rt, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_mallocz_rt(JSRuntime* rt, size_t size) {
|
||||
return js_mallocz_rt(rt, size);
|
||||
}
|
||||
|
||||
void*
|
||||
orig_js_realloc_rt(JSRuntime* rt, void* p, size_t size) {
|
||||
return js_realloc_rt(rt, p, size);
|
||||
}
|
||||
|
||||
size_t
|
||||
orig_js_malloc_usable_size_rt(JSRuntime* rt, const void* p) {
|
||||
return js_malloc_usable_size_rt(rt, p);
|
||||
}
|
||||
|
||||
void
|
||||
orig_js_free_rt(JSRuntime* rt, void* p) {
|
||||
return js_free_rt(rt, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
165
src/quickjs/debug.h
Normal file
165
src/quickjs/debug.h
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#include <quickjs.h>
|
||||
#include <cutils.h>
|
||||
#include "defines.h"
|
||||
|
||||
#ifndef QUICKJS_H
|
||||
#error "quickjs.h not included"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \defgroup debug debug: Debugging helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern thread_local struct list_head alloc_block_list;
|
||||
|
||||
int64_t check_pointer(void*);
|
||||
void* debug_malloc(size_t, const char*, int);
|
||||
void* debug_calloc(size_t, size_t, const char*, int line);
|
||||
void* debug_realloc(void*, size_t, const char*, int line);
|
||||
void* debug_strdup(const char*, const char*, int);
|
||||
void debug_free(void*, const char*, int);
|
||||
void* debug_js_malloc(JSContext*, size_t, const char*, int line);
|
||||
void* debug_js_mallocz(JSContext*, size_t, const char*, int line);
|
||||
void* debug_js_realloc(JSContext*, void*, size_t, const char* file, int line);
|
||||
void* debug_js_realloc2(JSContext*, void*, size_t, size_t* pslack, const char* file, int line);
|
||||
void* debug_js_strdup(JSContext*, const char*, const char*, int line);
|
||||
void* debug_js_strndup(JSContext*, const char*, size_t, const char* file, int line);
|
||||
size_t debug_js_malloc_usable_size(JSContext*, const void*, const char*, int line);
|
||||
void debug_js_free(JSContext*, void*, const char*, int line);
|
||||
void* debug_js_malloc_rt(JSRuntime*, size_t, const char*, int line);
|
||||
void* debug_js_mallocz_rt(JSRuntime*, size_t, const char*, int line);
|
||||
void* debug_js_realloc_rt(JSRuntime*, void*, size_t, const char* file, int line);
|
||||
size_t debug_js_malloc_usable_size_rt(JSRuntime*, const void*, const char*, int line);
|
||||
void debug_js_free_rt(JSRuntime*, void*, const char*, int line);
|
||||
|
||||
#if !defined(_IN_DEBUG_C)
|
||||
|
||||
#if defined(DEBUG_ALLOC)
|
||||
#define malloc(size) debug_malloc(size, __FILE__, __LINE__)
|
||||
#define calloc(nelem, size) debug_calloc(nelem, size, __FILE__, __LINE__)
|
||||
#define realloc(ptr, size) debug_realloc(ptr, size, __FILE__, __LINE__)
|
||||
#define strdup(str) debug_strdup(str, __FILE__, __LINE__)
|
||||
#define free(ptr) debug_free(ptr, __FILE__, __LINE__)
|
||||
#define js_malloc(ctx, size) debug_js_malloc(ctx, size, __FILE__, __LINE__)
|
||||
#define js_mallocz(ctx, size) debug_js_mallocz(ctx, size, __FILE__, __LINE__)
|
||||
#define js_realloc(ctx, ptr, size) debug_js_realloc(ctx, ptr, size, __FILE__, __LINE__)
|
||||
#define js_strdup(ctx, str) debug_js_strdup(ctx, str, __FILE__, __LINE__)
|
||||
#define js_strndup(ctx, str, len) debug_js_strndup(ctx, str, len, __FILE__, __LINE__)
|
||||
#define js_free(ctx, ptr) debug_js_free(ctx, ptr, __FILE__, __LINE__)
|
||||
#define js_malloc_usable_size(ctx, ptr) debug_js_malloc_usable_size(ctx, ptr, __FILE__, __LINE__)
|
||||
#define js_malloc_rt(rt, size) debug_js_malloc_rt(rt, size, __FILE__, __LINE__)
|
||||
#define js_mallocz_rt(rt, size) debug_js_mallocz_rt(rt, size, __FILE__, __LINE__)
|
||||
#define js_realloc_rt(rt, ptr, size) debug_js_realloc_rt(rt, ptr, size, __FILE__, __LINE__)
|
||||
#define js_malloc_usable_size_rt(rt, ptr) debug_js_malloc_usable_size_rt(rt, ptr, __FILE__, __LINE__)
|
||||
#define js_free_rt(rt, ptr) debug_js_free_rt(rt, ptr, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define realloc_helper(name) \
|
||||
void* name(void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return debug_malloc(size, __FILE__, __LINE__); \
|
||||
if(size == 0) \
|
||||
return debug_free(ptr, __FILE__, __LINE__); \
|
||||
return debug_realloc(ptr, size, __FILE__, __LINE__); \
|
||||
}
|
||||
#define realloc2_helper(name) \
|
||||
void* name(void* opaque, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return debug_malloc(size, __FILE__, __LINE__); \
|
||||
if(size == 0) { \
|
||||
debug_free(ptr, __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
return debug_realloc(ptr, size, __FILE__, __LINE__); \
|
||||
}
|
||||
#define js_realloc_helper(name) \
|
||||
void* name(JSContext* ctx, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return debug_js_malloc(ctx, size, __FILE__, __LINE__); \
|
||||
if(size == 0) { \
|
||||
debug_js_free(ctx, ptr, __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
return debug_js_realloc(ctx, ptr, size, __FILE__, __LINE__); \
|
||||
}
|
||||
#define js_realloc_rt_helper(name) \
|
||||
void* name(JSRuntime* rt, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return debug_js_malloc_rt(rt, size, __FILE__, __LINE__); \
|
||||
if(size == 0) { \
|
||||
debug_js_free_rt(rt, ptr, __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
return debug_js_realloc_rt(rt, ptr, size, __FILE__, __LINE__); \
|
||||
}
|
||||
#else
|
||||
#define realloc_helper(name) \
|
||||
void* name(void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return malloc(size); \
|
||||
if(size == 0) { \
|
||||
free(ptr); \
|
||||
return 0; \
|
||||
} \
|
||||
return realloc(ptr, size); \
|
||||
}
|
||||
#define realloc2_helper(name) \
|
||||
void* name(void* opaque, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return malloc(size); \
|
||||
if(size == 0) { \
|
||||
free(ptr); \
|
||||
return 0; \
|
||||
} \
|
||||
return realloc(ptr, size); \
|
||||
}
|
||||
#define js_realloc_helper(name) \
|
||||
void* name(JSContext* ctx, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return orig_js_malloc(ctx, size); \
|
||||
if(size == 0) { \
|
||||
orig_js_free(ctx, ptr); \
|
||||
return 0; \
|
||||
} \
|
||||
return orig_js_realloc(ctx, ptr, size); \
|
||||
}
|
||||
#define js_realloc_rt_helper(name) \
|
||||
void* name(JSRuntime* rt, void* ptr, size_t size) { \
|
||||
if(ptr == 0) \
|
||||
return orig_js_malloc_rt(rt, size); \
|
||||
if(size == 0) { \
|
||||
orig_js_free_rt(rt, ptr); \
|
||||
return 0; \
|
||||
} \
|
||||
return orig_js_realloc_rt(rt, ptr, size); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void* orig_malloc(size_t);
|
||||
void* orig_calloc(size_t, size_t);
|
||||
void* orig_realloc(void*, size_t);
|
||||
void* orig_strdup(const char*);
|
||||
void orig_free(void*);
|
||||
void* orig_js_malloc(JSContext*, size_t);
|
||||
void* orig_js_mallocz(JSContext*, size_t);
|
||||
void* orig_js_realloc(JSContext*, void*, size_t);
|
||||
void* orig_js_strdup(JSContext*, const char*);
|
||||
void* orig_js_strndup(JSContext*, const char*, size_t);
|
||||
size_t orig_js_malloc_usable_size(JSContext*, const void*);
|
||||
void orig_js_free(JSContext*, void*);
|
||||
void* orig_js_malloc_rt(JSRuntime*, size_t);
|
||||
void* orig_js_mallocz_rt(JSRuntime*, size_t);
|
||||
void* orig_js_realloc_rt(JSRuntime*, void*, size_t);
|
||||
size_t orig_js_malloc_usable_size_rt(JSRuntime*, const void*);
|
||||
void orig_js_free_rt(JSRuntime*, void*);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(DEBUG_H) */
|
||||
181
src/quickjs/defines.h
Normal file
181
src/quickjs/defines.h
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef DEFINES_H
|
||||
#define DEFINES_H
|
||||
|
||||
/**
|
||||
* \defgroup defines defines: Preprocessor definitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#define FD_TO_SOCKET(fd) ((SOCKET)_get_osfhandle((fd)))
|
||||
#define SOCKET_TO_FD(fh) (_open_osfhandle((intptr_t)(fh), O_RDWR | O_BINARY))
|
||||
#else
|
||||
#define FD_TO_SOCKET(fd) (fd)
|
||||
#define SOCKET_TO_FD(fh) (fh)
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, field) ((size_t) & ((type*)0)->field)
|
||||
#endif
|
||||
|
||||
#ifndef inrange
|
||||
#define inrange(value, min, max) ((value) >= (min) && (value) <= (max))
|
||||
#endif
|
||||
|
||||
#define trim_dotslash(str) (!strncmp((str), "./", 2) ? (str) + 2 : (str))
|
||||
|
||||
#ifndef thread_local
|
||||
#ifdef _Thread_local
|
||||
#define thread_local _Thread_local
|
||||
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#define thread_local __thread
|
||||
#elif defined(_WIN32)
|
||||
#define thread_local __declspec(thread)
|
||||
#else
|
||||
#error No TLS implementation found.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define PACK __attribute__((packed))
|
||||
#define ENDPACK
|
||||
#else
|
||||
#define PACK #pragma pack(push, 1)
|
||||
#define ENDPACK #pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define JS_CGETSET_ENUMERABLE_DEF(prop_name, fgetter, fsetter, magic_num) \
|
||||
{ \
|
||||
.name = prop_name, .prop_flags = JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE, .def_type = JS_DEF_CGETSET_MAGIC, .magic = magic_num, .u = { \
|
||||
.getset = {.get = {.getter_magic = fgetter}, .set = {.setter_magic = fsetter}} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define JS_CGETSET_MAGIC_FLAGS_DEF(prop_name, fgetter, fsetter, magic_num, flags) \
|
||||
{ \
|
||||
.name = prop_name, .prop_flags = flags, .def_type = JS_DEF_CGETSET_MAGIC, .magic = magic_num, .u = { \
|
||||
.getset = {.get = {.getter_magic = fgetter}, .set = {.setter_magic = fsetter}} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define JS_CFUNC_DEF_FLAGS(prop_name, length, func1, flags) \
|
||||
{ \
|
||||
.name = prop_name, .prop_flags = flags, .def_type = JS_DEF_CFUNC, .magic = 0, .u = {.func = {length, JS_CFUNC_generic, {.generic = func1}} } \
|
||||
}
|
||||
|
||||
#define JS_CONSTANT_FLAGS(name, flags) JS_PROP_INT32_DEF(#name, name, (flags))
|
||||
#define JS_CONSTANT(name) JS_PROP_INT32_DEF(#name, name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)
|
||||
#define JS_CONSTANT_NONENUMERABLE(name) JS_PROP_INT32_DEF(#name, name, JS_PROP_CONFIGURABLE)
|
||||
|
||||
#ifdef JS_SHARED_LIBRARY
|
||||
#if defined(_WIN32) || defined(__MINGW32__)
|
||||
#define VISIBLE __declspec(dllexport)
|
||||
#define HIDDEN
|
||||
#else
|
||||
#define VISIBLE __attribute__((visibility("default")))
|
||||
#define HIDDEN __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
#else
|
||||
#define VISIBLE
|
||||
#define HIDDEN
|
||||
#endif
|
||||
|
||||
#ifndef MAX_NUM
|
||||
#define MAX_NUM(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MIN_NUM
|
||||
#define MIN_NUM(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef ABS_NUM
|
||||
#define ABS_NUM(n) ((n) < 0 ? -(n) : (n))
|
||||
#endif
|
||||
#ifndef MOD_NUM
|
||||
#define MOD_NUM(n, divisor) ((((n) % (divisor)) + (divisor)) % (divisor))
|
||||
#endif
|
||||
#ifndef SIGN_NUM
|
||||
#define SIGN_NUM(n) ((n) < 0)
|
||||
#endif
|
||||
|
||||
#define COLOR_BLACK "\x1b[0;30m"
|
||||
#define COLOR_RED "\x1b[0;31m"
|
||||
#define COLOR_GREEN "\x1b[0;32m"
|
||||
#define COLOR_BROWN "\x1b[0;33m"
|
||||
#define COLOR_BLUE "\x1b[0;34m"
|
||||
#define COLOR_PURPLE "\x1b[0;35m"
|
||||
#define COLOR_MARINE "\x1b[0;36m"
|
||||
#define COLOR_LIGHTGRAY "\x1b[0;37m"
|
||||
#define COLOR_GRAY "\x1b[1;30m"
|
||||
#define COLOR_NONE "\x1b[0m"
|
||||
|
||||
#define COLOR_LIGHTRED "\x1b[1;31m"
|
||||
|
||||
#define COLOR_LIGHTGREEN "\x1b[1;32m"
|
||||
#define COLOR_YELLOW "\x1b[1;33m"
|
||||
#define COLOR_LIGHTBLUE "\x1b[1;34m"
|
||||
#define COLOR_MAGENTA "\x1b[1;35m"
|
||||
#define COLOR_CYAN "\x1b[1;36m"
|
||||
#define COLOR_WHITE "\x1b[1;37m"
|
||||
|
||||
#define BGCOLOR_RED "\x1b[48;5;124m"
|
||||
#define BGCOLOR_BLUE "\x1b[48;5;20m"
|
||||
#define BGCOLOR_YELLOW "\x1b[48;5;214m"
|
||||
#define BGCOLOR_GREEN "\x1b[48;5;28m"
|
||||
#define BGCOLOR_PINK "\x1b[48;5;165m"
|
||||
|
||||
#define JS_VALUE_FREE(ctx, value) \
|
||||
do { \
|
||||
JS_FreeValue((ctx), (value)); \
|
||||
(value) = JS_UNDEFINED; \
|
||||
} while(0);
|
||||
#define JS_VALUE_FREE_RT(ctx, value) \
|
||||
do { \
|
||||
JS_FreeValueRT((ctx), (value)); \
|
||||
(value) = JS_UNDEFINED; \
|
||||
} while(0);
|
||||
|
||||
#if 0
|
||||
#define js_object_tmpmark_set(value) \
|
||||
do { \
|
||||
((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] |= 0x40; \
|
||||
} while(0);
|
||||
#define js_object_tmpmark_clear(value) \
|
||||
do { \
|
||||
((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] &= ~0x40; \
|
||||
} while(0);
|
||||
#define js_object_tmpmark_isset(value) (((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] & 0x40)
|
||||
#else
|
||||
#define js_object_tmpmark_set(value) \
|
||||
do { \
|
||||
JS_VALUE_GET_OBJ((value))->tmp_mark |= 0x40; \
|
||||
} while(0);
|
||||
#define js_object_tmpmark_clear(value) \
|
||||
do { \
|
||||
JS_VALUE_GET_OBJ((value))->tmp_mark &= ~0x40; \
|
||||
} while(0);
|
||||
#define js_object_tmpmark_isset(value) (JS_VALUE_GET_OBJ((value))->tmp_mark & 0x40)
|
||||
#endif
|
||||
|
||||
#define js_runtime_exception_set(rt, value) \
|
||||
do { \
|
||||
*(JSValue*)((uint8_t*)(rt) + 216) = value; \
|
||||
} while(0);
|
||||
#define js_runtime_exception_get(rt) (*(JSValue*)((uint8_t*)(rt) + 216))
|
||||
#define js_runtime_exception_clear(rt) \
|
||||
do { \
|
||||
if(!JS_IsNull(js_runtime_exception_get(rt))) \
|
||||
JS_FreeValueRT((rt), js_runtime_exception_get(rt)); \
|
||||
js_runtime_exception_set(rt, JS_NULL); \
|
||||
} while(0)
|
||||
|
||||
#define JS_ATOM_TAG_INT (1U << 31)
|
||||
#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1)
|
||||
|
||||
#define JS_ATOM_ISINT(i) ((JSAtom)((i)&JS_ATOM_TAG_INT))
|
||||
#define JS_ATOM_FROMINT(i) ((JSAtom)((i)&JS_ATOM_MAX_INT) | JS_ATOM_TAG_INT)
|
||||
#define JS_ATOM_TOINT(i) (unsigned int)(((JSAtom)(i) & (~(JS_ATOM_TAG_INT))))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(DEFINES_H) */
|
||||
45
src/quickjs/hello.c
Normal file
45
src/quickjs/hello.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* File generated automatically by the QuickJS compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_hello_size = 87;
|
||||
|
||||
const uint8_t qjsc_hello[87] = {
|
||||
0x43, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
|
||||
0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,
|
||||
0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,
|
||||
0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,
|
||||
0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,
|
||||
0x6f, 0x2e, 0x6a, 0x73, 0x0c, 0x00, 0x06, 0x00,
|
||||
0xa2, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00,
|
||||
0x14, 0x01, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x38,
|
||||
0xe3, 0x00, 0x00, 0x00, 0x42, 0xe4, 0x00, 0x00,
|
||||
0x00, 0x04, 0xe5, 0x00, 0x00, 0x00, 0x24, 0x01,
|
||||
0x00, 0xcf, 0x28, 0xcc, 0x03, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContextRaw(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
JS_AddIntrinsicBaseObjects(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0);
|
||||
js_std_loop(ctx);
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 0;
|
||||
}
|
||||
27
src/quickjs/iso_8859_1.h
Normal file
27
src/quickjs/iso_8859_1.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_1_H
|
||||
#define TUTF8E_ISO_8859_1_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_1_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_1, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_1_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_1, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_1_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_1, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_1_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_1, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_10.h
Normal file
27
src/quickjs/iso_8859_10.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_10_H
|
||||
#define TUTF8E_ISO_8859_10_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_10_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_10, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_10_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_10, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_10_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_10, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_10_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_10, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_11.h
Normal file
27
src/quickjs/iso_8859_11.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_11_H
|
||||
#define TUTF8E_ISO_8859_11_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_11_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_11, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_11_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_11, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_11_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_11, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_11_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_11, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_13.h
Normal file
27
src/quickjs/iso_8859_13.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_13_H
|
||||
#define TUTF8E_ISO_8859_13_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_13_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_13, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_13_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_13, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_13_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_13, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_13_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_13, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_14.h
Normal file
27
src/quickjs/iso_8859_14.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_14_H
|
||||
#define TUTF8E_ISO_8859_14_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_14_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_14, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_14_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_14, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_14_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_14, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_14_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_14, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_15.h
Normal file
27
src/quickjs/iso_8859_15.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_15_H
|
||||
#define TUTF8E_ISO_8859_15_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_15_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_15, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_15_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_15, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_15_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_15, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_15_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_15, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_16.h
Normal file
27
src/quickjs/iso_8859_16.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_16_H
|
||||
#define TUTF8E_ISO_8859_16_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_16_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_16, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_16_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_16, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_16_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_16, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_16_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_16, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_2.h
Normal file
27
src/quickjs/iso_8859_2.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_2_H
|
||||
#define TUTF8E_ISO_8859_2_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_2_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_2, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_2_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_2, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_2_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_2, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_2_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_2, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_3.h
Normal file
27
src/quickjs/iso_8859_3.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_3_H
|
||||
#define TUTF8E_ISO_8859_3_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_3_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_3, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_3_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_3, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_3_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_3, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_3_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_3, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_4.h
Normal file
27
src/quickjs/iso_8859_4.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_4_H
|
||||
#define TUTF8E_ISO_8859_4_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_4_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_4, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_4_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_4, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_4_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_4, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_4_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_4, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_5.h
Normal file
27
src/quickjs/iso_8859_5.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_5_H
|
||||
#define TUTF8E_ISO_8859_5_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_5_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_5, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_5_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_5, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_5_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_5, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_5_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_5, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_6.h
Normal file
27
src/quickjs/iso_8859_6.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_6_H
|
||||
#define TUTF8E_ISO_8859_6_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_6_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_6, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_6_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_6, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_6_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_6, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_6_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_6, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_7.h
Normal file
27
src/quickjs/iso_8859_7.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_7_H
|
||||
#define TUTF8E_ISO_8859_7_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_7_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_7, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_7_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_7, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_7_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_7, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_7_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_7, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_8.h
Normal file
27
src/quickjs/iso_8859_8.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_8_H
|
||||
#define TUTF8E_ISO_8859_8_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_8_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_8, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_8_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_8, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_8_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_8, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_8_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_8, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/iso_8859_9.h
Normal file
27
src/quickjs/iso_8859_9.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_ISO_8859_9_H
|
||||
#define TUTF8E_ISO_8859_9_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_iso_8859_9_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_9, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_9_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_9, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_9_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_9, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_iso_8859_9_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_9, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
8473
src/quickjs/libbf.c
Normal file
8473
src/quickjs/libbf.c
Normal file
File diff suppressed because it is too large
Load Diff
535
src/quickjs/libbf.h
Normal file
535
src/quickjs/libbf.h
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
* Tiny arbitrary precision floating point library
|
||||
*
|
||||
* Copyright (c) 2017-2021 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBBF_H
|
||||
#define LIBBF_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
|
||||
#define LIMB_LOG2_BITS 6
|
||||
#else
|
||||
#define LIMB_LOG2_BITS 5
|
||||
#endif
|
||||
|
||||
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
|
||||
|
||||
#if LIMB_BITS == 64
|
||||
typedef __int128 int128_t;
|
||||
typedef unsigned __int128 uint128_t;
|
||||
typedef int64_t slimb_t;
|
||||
typedef uint64_t limb_t;
|
||||
typedef uint128_t dlimb_t;
|
||||
#define BF_RAW_EXP_MIN INT64_MIN
|
||||
#define BF_RAW_EXP_MAX INT64_MAX
|
||||
|
||||
#define LIMB_DIGITS 19
|
||||
#define BF_DEC_BASE UINT64_C(10000000000000000000)
|
||||
|
||||
#else
|
||||
|
||||
typedef int32_t slimb_t;
|
||||
typedef uint32_t limb_t;
|
||||
typedef uint64_t dlimb_t;
|
||||
#define BF_RAW_EXP_MIN INT32_MIN
|
||||
#define BF_RAW_EXP_MAX INT32_MAX
|
||||
|
||||
#define LIMB_DIGITS 9
|
||||
#define BF_DEC_BASE 1000000000U
|
||||
|
||||
#endif
|
||||
|
||||
/* in bits */
|
||||
/* minimum number of bits for the exponent */
|
||||
#define BF_EXP_BITS_MIN 3
|
||||
/* maximum number of bits for the exponent */
|
||||
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
|
||||
/* extended range for exponent, used internally */
|
||||
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
|
||||
/* minimum possible precision */
|
||||
#define BF_PREC_MIN 2
|
||||
/* minimum possible precision */
|
||||
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
|
||||
/* some operations support infinite precision */
|
||||
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
|
||||
|
||||
#if LIMB_BITS == 64
|
||||
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
|
||||
#else
|
||||
#define BF_CHKSUM_MOD 975620677U
|
||||
#endif
|
||||
|
||||
#define BF_EXP_ZERO BF_RAW_EXP_MIN
|
||||
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
|
||||
#define BF_EXP_NAN BF_RAW_EXP_MAX
|
||||
|
||||
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
|
||||
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
|
||||
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
|
||||
*/
|
||||
typedef struct {
|
||||
struct bf_context_t *ctx;
|
||||
int sign;
|
||||
slimb_t expn;
|
||||
limb_t len;
|
||||
limb_t *tab;
|
||||
} bf_t;
|
||||
|
||||
typedef struct {
|
||||
/* must be kept identical to bf_t */
|
||||
struct bf_context_t *ctx;
|
||||
int sign;
|
||||
slimb_t expn;
|
||||
limb_t len;
|
||||
limb_t *tab;
|
||||
} bfdec_t;
|
||||
|
||||
typedef enum {
|
||||
BF_RNDN, /* round to nearest, ties to even */
|
||||
BF_RNDZ, /* round to zero */
|
||||
BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
|
||||
BF_RNDU, /* round to +inf */
|
||||
BF_RNDNA, /* round to nearest, ties away from zero */
|
||||
BF_RNDA, /* round away from zero */
|
||||
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
|
||||
inexact flag is always set) */
|
||||
} bf_rnd_t;
|
||||
|
||||
/* allow subnormal numbers. Only available if the number of exponent
|
||||
bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
|
||||
#define BF_FLAG_SUBNORMAL (1 << 3)
|
||||
/* 'prec' is the precision after the radix point instead of the whole
|
||||
mantissa. Can only be used with bf_round() and
|
||||
bfdec_[add|sub|mul|div|sqrt|round](). */
|
||||
#define BF_FLAG_RADPNT_PREC (1 << 4)
|
||||
|
||||
#define BF_RND_MASK 0x7
|
||||
#define BF_EXP_BITS_SHIFT 5
|
||||
#define BF_EXP_BITS_MASK 0x3f
|
||||
|
||||
/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
|
||||
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
|
||||
|
||||
/* contains the rounding mode and number of exponents bits */
|
||||
typedef uint32_t bf_flags_t;
|
||||
|
||||
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
|
||||
|
||||
typedef struct {
|
||||
bf_t val;
|
||||
limb_t prec;
|
||||
} BFConstCache;
|
||||
|
||||
typedef struct bf_context_t {
|
||||
void *realloc_opaque;
|
||||
bf_realloc_func_t *realloc_func;
|
||||
BFConstCache log2_cache;
|
||||
BFConstCache pi_cache;
|
||||
struct BFNTTState *ntt_state;
|
||||
} bf_context_t;
|
||||
|
||||
static inline int bf_get_exp_bits(bf_flags_t flags)
|
||||
{
|
||||
int e;
|
||||
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
|
||||
if (e == BF_EXP_BITS_MASK)
|
||||
return BF_EXP_BITS_MAX + 1;
|
||||
else
|
||||
return BF_EXP_BITS_MAX - e;
|
||||
}
|
||||
|
||||
static inline bf_flags_t bf_set_exp_bits(int n)
|
||||
{
|
||||
return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
|
||||
}
|
||||
|
||||
/* returned status */
|
||||
#define BF_ST_INVALID_OP (1 << 0)
|
||||
#define BF_ST_DIVIDE_ZERO (1 << 1)
|
||||
#define BF_ST_OVERFLOW (1 << 2)
|
||||
#define BF_ST_UNDERFLOW (1 << 3)
|
||||
#define BF_ST_INEXACT (1 << 4)
|
||||
/* indicate that a memory allocation error occured. NaN is returned */
|
||||
#define BF_ST_MEM_ERROR (1 << 5)
|
||||
|
||||
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
|
||||
|
||||
static inline slimb_t bf_max(slimb_t a, slimb_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline slimb_t bf_min(slimb_t a, slimb_t b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
|
||||
void *realloc_opaque);
|
||||
void bf_context_end(bf_context_t *s);
|
||||
/* free memory allocated for the bf cache data */
|
||||
void bf_clear_cache(bf_context_t *s);
|
||||
|
||||
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
|
||||
{
|
||||
return s->realloc_func(s->realloc_opaque, ptr, size);
|
||||
}
|
||||
|
||||
/* 'size' must be != 0 */
|
||||
static inline void *bf_malloc(bf_context_t *s, size_t size)
|
||||
{
|
||||
return bf_realloc(s, NULL, size);
|
||||
}
|
||||
|
||||
static inline void bf_free(bf_context_t *s, void *ptr)
|
||||
{
|
||||
/* must test ptr otherwise equivalent to malloc(0) */
|
||||
if (ptr)
|
||||
bf_realloc(s, ptr, 0);
|
||||
}
|
||||
|
||||
void bf_init(bf_context_t *s, bf_t *r);
|
||||
|
||||
static inline void bf_delete(bf_t *r)
|
||||
{
|
||||
bf_context_t *s = r->ctx;
|
||||
/* we accept to delete a zeroed bf_t structure */
|
||||
if (s && r->tab) {
|
||||
bf_realloc(s, r->tab, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bf_neg(bf_t *r)
|
||||
{
|
||||
r->sign ^= 1;
|
||||
}
|
||||
|
||||
static inline int bf_is_finite(const bf_t *a)
|
||||
{
|
||||
return (a->expn < BF_EXP_INF);
|
||||
}
|
||||
|
||||
static inline int bf_is_nan(const bf_t *a)
|
||||
{
|
||||
return (a->expn == BF_EXP_NAN);
|
||||
}
|
||||
|
||||
static inline int bf_is_zero(const bf_t *a)
|
||||
{
|
||||
return (a->expn == BF_EXP_ZERO);
|
||||
}
|
||||
|
||||
static inline void bf_memcpy(bf_t *r, const bf_t *a)
|
||||
{
|
||||
*r = *a;
|
||||
}
|
||||
|
||||
int bf_set_ui(bf_t *r, uint64_t a);
|
||||
int bf_set_si(bf_t *r, int64_t a);
|
||||
void bf_set_nan(bf_t *r);
|
||||
void bf_set_zero(bf_t *r, int is_neg);
|
||||
void bf_set_inf(bf_t *r, int is_neg);
|
||||
int bf_set(bf_t *r, const bf_t *a);
|
||||
void bf_move(bf_t *r, bf_t *a);
|
||||
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
|
||||
int bf_set_float64(bf_t *a, double d);
|
||||
|
||||
int bf_cmpu(const bf_t *a, const bf_t *b);
|
||||
int bf_cmp_full(const bf_t *a, const bf_t *b);
|
||||
int bf_cmp(const bf_t *a, const bf_t *b);
|
||||
static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
|
||||
{
|
||||
return bf_cmp(a, b) == 0;
|
||||
}
|
||||
|
||||
static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
|
||||
{
|
||||
return bf_cmp(a, b) <= 0;
|
||||
}
|
||||
|
||||
static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
|
||||
{
|
||||
return bf_cmp(a, b) < 0;
|
||||
}
|
||||
|
||||
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
|
||||
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
#define BF_DIVREM_EUCLIDIAN BF_RNDF
|
||||
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
|
||||
limb_t prec, bf_flags_t flags, int rnd_mode);
|
||||
int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||
bf_flags_t flags, int rnd_mode);
|
||||
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||
bf_flags_t flags, int rnd_mode);
|
||||
/* round to integer with infinite precision */
|
||||
int bf_rint(bf_t *r, int rnd_mode);
|
||||
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
|
||||
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
|
||||
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
slimb_t bf_get_exp_min(const bf_t *a);
|
||||
int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
|
||||
int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
|
||||
int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
|
||||
|
||||
/* additional flags for bf_atof */
|
||||
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
|
||||
#define BF_ATOF_NO_HEX (1 << 16)
|
||||
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
|
||||
#define BF_ATOF_BIN_OCT (1 << 17)
|
||||
/* Do not parse NaN or Inf */
|
||||
#define BF_ATOF_NO_NAN_INF (1 << 18)
|
||||
/* return the exponent separately */
|
||||
#define BF_ATOF_EXPONENT (1 << 19)
|
||||
|
||||
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
|
||||
limb_t prec, bf_flags_t flags);
|
||||
/* this version accepts prec = BF_PREC_INF and returns the radix
|
||||
exponent */
|
||||
int bf_atof2(bf_t *r, slimb_t *pexponent,
|
||||
const char *str, const char **pnext, int radix,
|
||||
limb_t prec, bf_flags_t flags);
|
||||
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
|
||||
slimb_t expn, limb_t prec, bf_flags_t flags);
|
||||
|
||||
|
||||
/* Conversion of floating point number to string. Return a null
|
||||
terminated string or NULL if memory error. *plen contains its
|
||||
length if plen != NULL. The exponent letter is "e" for base 10,
|
||||
"p" for bases 2, 8, 16 with a binary exponent and "@" for the other
|
||||
bases. */
|
||||
|
||||
#define BF_FTOA_FORMAT_MASK (3 << 16)
|
||||
|
||||
/* fixed format: prec significant digits rounded with (flags &
|
||||
BF_RND_MASK). Exponential notation is used if too many zeros are
|
||||
needed.*/
|
||||
#define BF_FTOA_FORMAT_FIXED (0 << 16)
|
||||
/* fractional format: prec digits after the decimal point rounded with
|
||||
(flags & BF_RND_MASK) */
|
||||
#define BF_FTOA_FORMAT_FRAC (1 << 16)
|
||||
/* free format:
|
||||
|
||||
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
|
||||
number of digits to represent 'a'. The precision and the rounding
|
||||
mode are ignored.
|
||||
|
||||
For the non binary radices with bf_ftoa(): use as many digits as
|
||||
necessary so that bf_atof() return the same number when using
|
||||
precision 'prec', rounding to nearest and the subnormal
|
||||
configuration of 'flags'. The result is meaningful only if 'a' is
|
||||
already rounded to 'prec' bits. If the subnormal flag is set, the
|
||||
exponent in 'flags' must also be set to the desired exponent range.
|
||||
*/
|
||||
#define BF_FTOA_FORMAT_FREE (2 << 16)
|
||||
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
|
||||
(takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
|
||||
binary radices with bf_ftoa() and for bfdec_ftoa(). */
|
||||
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
|
||||
|
||||
/* force exponential notation for fixed or free format */
|
||||
#define BF_FTOA_FORCE_EXP (1 << 20)
|
||||
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
|
||||
base 2 if non zero value */
|
||||
#define BF_FTOA_ADD_PREFIX (1 << 21)
|
||||
/* return "Infinity" instead of "Inf" and add a "+" for positive
|
||||
exponents */
|
||||
#define BF_FTOA_JS_QUIRKS (1 << 22)
|
||||
|
||||
char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
|
||||
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
|
||||
#define BF_GET_INT_MOD (1 << 0)
|
||||
int bf_get_int32(int *pres, const bf_t *a, int flags);
|
||||
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
|
||||
int bf_get_uint64(uint64_t *pres, const bf_t *a);
|
||||
|
||||
/* the following functions are exported for testing only. */
|
||||
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
|
||||
void bf_print_str(const char *str, const bf_t *a);
|
||||
int bf_resize(bf_t *r, limb_t len);
|
||||
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
|
||||
int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
|
||||
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
|
||||
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
|
||||
int is_ceil1);
|
||||
int mp_mul(bf_context_t *s, limb_t *result,
|
||||
const limb_t *op1, limb_t op1_size,
|
||||
const limb_t *op2, limb_t op2_size);
|
||||
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
|
||||
limb_t n, limb_t carry);
|
||||
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
|
||||
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
|
||||
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
|
||||
limb_t bf_isqrt(limb_t a);
|
||||
|
||||
/* transcendental functions */
|
||||
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
|
||||
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
|
||||
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
|
||||
limb_t prec, bf_flags_t flags);
|
||||
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||
|
||||
/* decimal floating point */
|
||||
|
||||
static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
|
||||
{
|
||||
bf_init(s, (bf_t *)r);
|
||||
}
|
||||
static inline void bfdec_delete(bfdec_t *r)
|
||||
{
|
||||
bf_delete((bf_t *)r);
|
||||
}
|
||||
|
||||
static inline void bfdec_neg(bfdec_t *r)
|
||||
{
|
||||
r->sign ^= 1;
|
||||
}
|
||||
|
||||
static inline int bfdec_is_finite(const bfdec_t *a)
|
||||
{
|
||||
return (a->expn < BF_EXP_INF);
|
||||
}
|
||||
|
||||
static inline int bfdec_is_nan(const bfdec_t *a)
|
||||
{
|
||||
return (a->expn == BF_EXP_NAN);
|
||||
}
|
||||
|
||||
static inline int bfdec_is_zero(const bfdec_t *a)
|
||||
{
|
||||
return (a->expn == BF_EXP_ZERO);
|
||||
}
|
||||
|
||||
static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
|
||||
{
|
||||
bf_memcpy((bf_t *)r, (const bf_t *)a);
|
||||
}
|
||||
|
||||
int bfdec_set_ui(bfdec_t *r, uint64_t a);
|
||||
int bfdec_set_si(bfdec_t *r, int64_t a);
|
||||
|
||||
static inline void bfdec_set_nan(bfdec_t *r)
|
||||
{
|
||||
bf_set_nan((bf_t *)r);
|
||||
}
|
||||
static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
|
||||
{
|
||||
bf_set_zero((bf_t *)r, is_neg);
|
||||
}
|
||||
static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
|
||||
{
|
||||
bf_set_inf((bf_t *)r, is_neg);
|
||||
}
|
||||
static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
|
||||
{
|
||||
return bf_set((bf_t *)r, (bf_t *)a);
|
||||
}
|
||||
static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
|
||||
{
|
||||
bf_move((bf_t *)r, (bf_t *)a);
|
||||
}
|
||||
static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bf_cmpu((const bf_t *)a, (const bf_t *)b);
|
||||
}
|
||||
static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
|
||||
}
|
||||
static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bf_cmp((const bf_t *)a, (const bf_t *)b);
|
||||
}
|
||||
static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bfdec_cmp(a, b) == 0;
|
||||
}
|
||||
static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bfdec_cmp(a, b) <= 0;
|
||||
}
|
||||
static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
|
||||
{
|
||||
return bfdec_cmp(a, b) < 0;
|
||||
}
|
||||
|
||||
int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
|
||||
limb_t prec, bf_flags_t flags, int rnd_mode);
|
||||
int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||
bf_flags_t flags, int rnd_mode);
|
||||
int bfdec_rint(bfdec_t *r, int rnd_mode);
|
||||
int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
|
||||
int bfdec_get_int32(int *pres, const bfdec_t *a);
|
||||
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
|
||||
|
||||
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
|
||||
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
|
||||
limb_t prec, bf_flags_t flags);
|
||||
|
||||
/* the following functions are exported for testing only. */
|
||||
extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
|
||||
void bfdec_print_str(const char *str, const bfdec_t *a);
|
||||
static inline int bfdec_resize(bfdec_t *r, limb_t len)
|
||||
{
|
||||
return bf_resize((bf_t *)r, len);
|
||||
}
|
||||
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
|
||||
|
||||
#endif /* LIBBF_H */
|
||||
57
src/quickjs/libregexp-opcode.h
Normal file
57
src/quickjs/libregexp-opcode.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
DEF(invalid, 1) /* never used */
|
||||
DEF(char, 3)
|
||||
DEF(char32, 5)
|
||||
DEF(dot, 1)
|
||||
DEF(any, 1) /* same as dot but match any character including line terminator */
|
||||
DEF(line_start, 1)
|
||||
DEF(line_end, 1)
|
||||
DEF(goto, 5)
|
||||
DEF(split_goto_first, 5)
|
||||
DEF(split_next_first, 5)
|
||||
DEF(match, 1)
|
||||
DEF(save_start, 2) /* save start position */
|
||||
DEF(save_end, 2) /* save end position, must come after saved_start */
|
||||
DEF(save_reset, 3) /* reset save positions */
|
||||
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
|
||||
DEF(push_i32, 5) /* push integer on the stack */
|
||||
DEF(drop, 1)
|
||||
DEF(word_boundary, 1)
|
||||
DEF(not_word_boundary, 1)
|
||||
DEF(back_reference, 2)
|
||||
DEF(backward_back_reference, 2) /* must come after back_reference */
|
||||
DEF(range, 3) /* variable length */
|
||||
DEF(range32, 3) /* variable length */
|
||||
DEF(lookahead, 5)
|
||||
DEF(negative_lookahead, 5)
|
||||
DEF(push_char_pos, 1) /* push the character position on the stack */
|
||||
DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
|
||||
DEF(prev, 1) /* go to the previous char */
|
||||
DEF(simple_greedy_quant, 17)
|
||||
|
||||
#endif /* DEF */
|
||||
2528
src/quickjs/libregexp.c
Normal file
2528
src/quickjs/libregexp.c
Normal file
File diff suppressed because it is too large
Load Diff
92
src/quickjs/libregexp.h
Normal file
92
src/quickjs/libregexp.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBREGEXP_H
|
||||
#define LIBREGEXP_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libunicode.h"
|
||||
|
||||
#define LRE_BOOL int /* for documentation purposes */
|
||||
|
||||
#define LRE_FLAG_GLOBAL (1 << 0)
|
||||
#define LRE_FLAG_IGNORECASE (1 << 1)
|
||||
#define LRE_FLAG_MULTILINE (1 << 2)
|
||||
#define LRE_FLAG_DOTALL (1 << 3)
|
||||
#define LRE_FLAG_UNICODE (1 << 4)
|
||||
#define LRE_FLAG_STICKY (1 << 5)
|
||||
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
|
||||
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
||||
|
||||
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
|
||||
const char *buf, size_t buf_len, int re_flags,
|
||||
void *opaque);
|
||||
int lre_get_capture_count(const uint8_t *bc_buf);
|
||||
int lre_get_flags(const uint8_t *bc_buf);
|
||||
const char *lre_get_groupnames(const uint8_t *bc_buf);
|
||||
int lre_exec(uint8_t **capture,
|
||||
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
|
||||
int cbuf_type, void *opaque);
|
||||
|
||||
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
||||
LRE_BOOL lre_is_space(int c);
|
||||
|
||||
/* must be provided by the user */
|
||||
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||
|
||||
/* JS identifier test */
|
||||
extern uint32_t const lre_id_start_table_ascii[4];
|
||||
extern uint32_t const lre_id_continue_table_ascii[4];
|
||||
|
||||
static inline int lre_js_is_ident_first(int c)
|
||||
{
|
||||
if ((uint32_t)c < 128) {
|
||||
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||
} else {
|
||||
#ifdef CONFIG_ALL_UNICODE
|
||||
return lre_is_id_start(c);
|
||||
#else
|
||||
return !lre_is_space(c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline int lre_js_is_ident_next(int c)
|
||||
{
|
||||
if ((uint32_t)c < 128) {
|
||||
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||
} else {
|
||||
/* ZWNJ and ZWJ are accepted in identifiers */
|
||||
#ifdef CONFIG_ALL_UNICODE
|
||||
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
|
||||
#else
|
||||
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef LRE_BOOL
|
||||
|
||||
#endif /* LIBREGEXP_H */
|
||||
4486
src/quickjs/libunicode-table.h
Normal file
4486
src/quickjs/libunicode-table.h
Normal file
File diff suppressed because it is too large
Load Diff
1788
src/quickjs/libunicode.c
Normal file
1788
src/quickjs/libunicode.c
Normal file
File diff suppressed because it is too large
Load Diff
127
src/quickjs/libunicode.h
Normal file
127
src/quickjs/libunicode.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Unicode utilities
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBUNICODE_H
|
||||
#define LIBUNICODE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define LRE_BOOL int /* for documentation purposes */
|
||||
|
||||
/* define it to include all the unicode tables (40KB larger) */
|
||||
#define CONFIG_ALL_UNICODE
|
||||
|
||||
#define LRE_CC_RES_LEN_MAX 3
|
||||
|
||||
typedef enum {
|
||||
UNICODE_NFC,
|
||||
UNICODE_NFD,
|
||||
UNICODE_NFKC,
|
||||
UNICODE_NFKD,
|
||||
} UnicodeNormalizationEnum;
|
||||
|
||||
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||
int lre_canonicalize(uint32_t c, LRE_BOOL is_unicode);
|
||||
LRE_BOOL lre_is_cased(uint32_t c);
|
||||
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
||||
|
||||
/* char ranges */
|
||||
|
||||
typedef struct {
|
||||
int len; /* in points, always even */
|
||||
int size;
|
||||
uint32_t *points; /* points sorted by increasing value */
|
||||
void *mem_opaque;
|
||||
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
|
||||
} CharRange;
|
||||
|
||||
typedef enum {
|
||||
CR_OP_UNION,
|
||||
CR_OP_INTER,
|
||||
CR_OP_XOR,
|
||||
} CharRangeOpEnum;
|
||||
|
||||
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||
void cr_free(CharRange *cr);
|
||||
int cr_realloc(CharRange *cr, int size);
|
||||
int cr_copy(CharRange *cr, const CharRange *cr1);
|
||||
|
||||
static inline int cr_add_point(CharRange *cr, uint32_t v)
|
||||
{
|
||||
if (cr->len >= cr->size) {
|
||||
if (cr_realloc(cr, cr->len + 1))
|
||||
return -1;
|
||||
}
|
||||
cr->points[cr->len++] = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
if ((cr->len + 2) > cr->size) {
|
||||
if (cr_realloc(cr, cr->len + 2))
|
||||
return -1;
|
||||
}
|
||||
cr->points[cr->len++] = c1;
|
||||
cr->points[cr->len++] = c2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
|
||||
|
||||
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
uint32_t b_pt[2];
|
||||
b_pt[0] = c1;
|
||||
b_pt[1] = c2 + 1;
|
||||
return cr_union1(cr, b_pt, 2);
|
||||
}
|
||||
|
||||
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||
const uint32_t *b_pt, int b_len, int op);
|
||||
|
||||
int cr_invert(CharRange *cr);
|
||||
|
||||
int cr_regexp_canonicalize(CharRange *cr, LRE_BOOL is_unicode);
|
||||
|
||||
#ifdef CONFIG_ALL_UNICODE
|
||||
|
||||
LRE_BOOL lre_is_id_start(uint32_t c);
|
||||
LRE_BOOL lre_is_id_continue(uint32_t c);
|
||||
|
||||
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||
UnicodeNormalizationEnum n_type,
|
||||
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||
|
||||
/* Unicode character range functions */
|
||||
|
||||
int unicode_script(CharRange *cr,
|
||||
const char *script_name, LRE_BOOL is_ext);
|
||||
int unicode_general_category(CharRange *cr, const char *gc_name);
|
||||
int unicode_prop(CharRange *cr, const char *prop_name);
|
||||
|
||||
#endif /* CONFIG_ALL_UNICODE */
|
||||
|
||||
#undef LRE_BOOL
|
||||
|
||||
#endif /* LIBUNICODE_H */
|
||||
153
src/quickjs/libutf.c
Normal file
153
src/quickjs/libutf.c
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <libutf.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
LibutfC16Type libutf_c16_type(uint_least16_t c16) {
|
||||
if (0xD800 != (0xF800 & c16)) {
|
||||
return LIBUTF_UTF16_NOT_SURROGATE;
|
||||
}
|
||||
return (c16 & 0x0400) ? LIBUTF_UTF16_SURROGATE_LOW : LIBUTF_UTF16_SURROGATE_HIGH;
|
||||
}
|
||||
|
||||
LibutfC8Type libutf_c8_type(char c) {
|
||||
static const LibutfC8Type lookup_table[256] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,-2,-2,-2,-2,-2,-2,-2,-2,
|
||||
};
|
||||
return lookup_table[(unsigned char) c];
|
||||
}
|
||||
|
||||
bool libutf_c32_to_c8(uint_least32_t c32, int *length, char c8[4]) {
|
||||
if (!libutf_c32_is_valid(c32)) {
|
||||
*length = 3;
|
||||
c8[0] = (char) 0xEF;
|
||||
c8[1] = (char) 0xBF;
|
||||
c8[2] = (char) 0xBD;
|
||||
return false;
|
||||
}
|
||||
if (c32 <= 0x007F) {
|
||||
c8[0] = c32;
|
||||
*length = 1;
|
||||
return true;
|
||||
} else if (c32 <= 0x07FF) {
|
||||
c8[0] = (char) (0xC0 | (c32 >> 6));
|
||||
c8[1] = (char) (0x80 | (c32 & 0x3F));
|
||||
*length = 2;
|
||||
return true;
|
||||
} else if (c32 <= 0xFFFF) {
|
||||
c8[0] = (char) (0xE0 | (c32 >> 12));
|
||||
c8[1] = (char) (0x80 | ((c32 >> 6) & 0x3F));
|
||||
c8[2] = (char) (0x80 | (c32 & 0x3F));
|
||||
*length = 3;
|
||||
return true;
|
||||
}
|
||||
assert(c32 <= 0x10FFFF);
|
||||
c8[0] = (char) (0xF0 | (c32 >> 18));
|
||||
c8[1] = (char) (0x80 | ((c32 >> 12) & 0x3F));
|
||||
c8[2] = (char) (0x80 | ((c32 >> 6) & 0x3F));
|
||||
c8[3] = (char) (0x80 | (c32 & 0x3F));
|
||||
*length = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libutf_c8_to_c32(const char *c8, uint_least32_t *c32) {
|
||||
if (!c8 || !c32) {
|
||||
return false;
|
||||
}
|
||||
unsigned char c = *c8;
|
||||
*c32 = 0xFFFD;
|
||||
LibutfC8Type type = libutf_c8_type(c);
|
||||
if (type < 0) {
|
||||
return false;
|
||||
}
|
||||
int len = type;
|
||||
uint_least32_t result;
|
||||
switch (len) {
|
||||
case 1:
|
||||
*c32 = c;
|
||||
return true;
|
||||
case 2:
|
||||
result = c & 0x1F;
|
||||
break;
|
||||
case 3:
|
||||
result = c & 0x0F;
|
||||
break;
|
||||
case 4:
|
||||
result = c & 0x07;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
for (int i = 1; i < len; ++i) {
|
||||
c = *++c8;
|
||||
if ((0xC0 & c) != 0x80) {
|
||||
return false;
|
||||
}
|
||||
result = (result << 6) + (c & 0x3F);
|
||||
}
|
||||
if (!libutf_c32_is_valid(result)) {
|
||||
return false;
|
||||
}
|
||||
char c8seq[4];
|
||||
int n;
|
||||
bool ok = libutf_c32_to_c8(result, &n, c8seq);
|
||||
assert(ok);
|
||||
if (n < (int) len) {
|
||||
return false;
|
||||
}
|
||||
*c32 = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libutf_c32_to_c16(uint_least32_t c32, int *length, uint_least16_t c16[2]) {
|
||||
if (!libutf_c32_is_valid(c32)) {
|
||||
c16[0] = 0xFFFD;
|
||||
c16[1] = 0;
|
||||
*length = 1;
|
||||
return false;
|
||||
}
|
||||
if (c32 < 0x10000) {
|
||||
c16[0] = c32;
|
||||
c16[1] = 0;
|
||||
*length = 1;
|
||||
} else {
|
||||
c32 -= 0x10000;
|
||||
c16[0] = 0xD800 | (c32 >> 10);
|
||||
c16[1] = 0xDC00 | (c32 & 0x3FF);
|
||||
*length = 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libutf_c16_to_c32(uint_least16_t c16[2], uint_least32_t *c32) {
|
||||
LibutfC16Type type = libutf_c16_type(c16[0]);
|
||||
if (LIBUTF_UTF16_NOT_SURROGATE == type) {
|
||||
*c32 = c16[0];
|
||||
return true;
|
||||
}
|
||||
if (LIBUTF_UTF16_SURROGATE_HIGH != type || LIBUTF_UTF16_SURROGATE_LOW != libutf_c16_type(c16[1])) {
|
||||
*c32 = 0xFFFD;
|
||||
return false;
|
||||
}
|
||||
*c32 = 0x10000 + ((c16[0] & 0x3FF) << 10) + (c16[1] & 0x3ff);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libutf_c32_is_valid(uint_least32_t c32) {
|
||||
return c32 < 0xD800 || (0xDFFF < c32 && c32 < 0x110000);
|
||||
}
|
||||
109
src/quickjs/libutf.h
Normal file
109
src/quickjs/libutf.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* LIBrary of UTF-(8,16,32) helper utility functions.
|
||||
*
|
||||
* Terminology:
|
||||
* code point = number of a Unicode character
|
||||
* code unit
|
||||
* = 1 byte for UTF-8
|
||||
* = 2 bytes for UTF-16
|
||||
* = 4 bytes for UTF-32
|
||||
* sequence = sequence of code units encoding SINGLE Unicode character
|
||||
*
|
||||
* Unicode has code points 0x000000..0x10FFFF except for the codes 0xD800..0xDFFF which are
|
||||
* reserved for UTF-16 surrogate pairs.
|
||||
*
|
||||
* UTF-32 is the simplest Unicode encoding. It encodes Unicode code points as is. Thus we may use
|
||||
* UTF-32 as a synonym for Unicode code point.
|
||||
* + O(1) indexing
|
||||
* - the text is 2-4 times bigger than in other encodings
|
||||
*
|
||||
* UTF-16 is variable width encoding. Each Unicode code point is represented as either single
|
||||
* code unit (two-byte number) or two code units which are called surrogate pairs.
|
||||
* - ASCII-only texts will be twice as big as in ASCII
|
||||
* - O(n) indexing
|
||||
*
|
||||
* UTF-8 is a variable width encoding. Each Unicode code point is represented as a sequence
|
||||
* of up to 4 bytes. The first byte determines the length of the sequence.
|
||||
* + is a superset of ASCII
|
||||
* + ASCII-only texts will have the same size
|
||||
* - O(n) indexing
|
||||
* - single Unicode code point can have different representations in
|
||||
* UTF-8, only the shortest one is considered valid
|
||||
*/
|
||||
|
||||
#ifndef LIBUTF_H
|
||||
#define LIBUTF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// UTF-8 code unit type
|
||||
typedef enum {
|
||||
LIBUTF_UTF8_OVERLONG = -2,
|
||||
LIBUTF_UTF8_TRAILING = -1,
|
||||
LIBUTF_UTF8_ONE_BYTE = 1,
|
||||
LIBUTF_UTF8_TWO_BYTE = 2,
|
||||
LIBUTF_UTF8_THREE_BYTE = 3,
|
||||
LIBUTF_UTF8_FOUR_BYTE = 4,
|
||||
} LibutfC8Type;
|
||||
|
||||
// UTF-16 code unit type
|
||||
typedef enum {
|
||||
LIBUTF_UTF16_SURROGATE_LOW = -1,
|
||||
LIBUTF_UTF16_NOT_SURROGATE = 1,
|
||||
LIBUTF_UTF16_SURROGATE_HIGH = 2,
|
||||
} LibutfC16Type;
|
||||
|
||||
/* Determine type of UTF-16 code unit. type = length of UTF-16 sequence starting with the specified code unit
|
||||
* or negative value if sequence cannot start with this code unit. */
|
||||
LibutfC16Type libutf_c16_type(uint_least16_t c16);
|
||||
|
||||
/* Determine type of UTF-8 sequence based on the first byte. type = length of UTF-8 sequence starting
|
||||
* with this byte or negative value if the byte cannot be first. UTF-8 may be up to 4 bytes long.
|
||||
* Common idiom for using this function:
|
||||
* >>> LibutfC8Type type = libutf_c8_type(c);
|
||||
* >>> if (type < 0) {
|
||||
* >>> return ERROR_CODE;
|
||||
* >>> }
|
||||
* >>> int length = type;
|
||||
* */
|
||||
LibutfC8Type libutf_c8_type(char c);
|
||||
|
||||
/* Convert Unicode code point into UTF-8 sequence. If c32 is not a valid
|
||||
* Unicode code point c8 will be filled with UTF-8 representation of special
|
||||
* replacement character U+FFFD, *length will be set to its length and false will be returned.
|
||||
* c32 -- UTF-32 Unicode code point
|
||||
* length -- where to put length of the UTF-8 sequence.
|
||||
* c8 -- where to put UTF-8 sequence. Make sure string has enough space.
|
||||
* result -- true if c32 is a valid Unicode code point or false otherwise. */
|
||||
bool libutf_c32_to_c8(uint_least32_t c32, int *length, char c8[4]);
|
||||
|
||||
/* Convert UTF-8 sequence into a UTF-32 Unicode code point. If c8 does not
|
||||
* point to a valid UTF-8 sequence c32 will be filled with special replacement
|
||||
* character U+FFFD and false will be returned.
|
||||
* c8 -- pointer to UTF-8 sequence.
|
||||
* c32 -- where to save UTF-32 Unicode code point.
|
||||
* result -- true if c8 points to a valid UTF-8 sequence or false otherwise. */
|
||||
bool libutf_c8_to_c32(const char *c8, uint_least32_t *c32);
|
||||
|
||||
/* Convert UTF-32 Unicode code point into UTF-16 sequence. If c32 is not a valid
|
||||
* Unicode code point c16 will be filled with UTF-16 representation of special
|
||||
* replacement character U+FFFD and false will be returned.
|
||||
* c32 -- UTF-32 Unicode code point.
|
||||
* length -- were to put length of UTF-16 sequence.
|
||||
* c16 -- where to put UTF-16 sequence (c16[0] -- high surrogate, c16[1] -- low surrogate)
|
||||
* result -- true if c32 is a valid Unicode code point or false otherwise. */
|
||||
bool libutf_c32_to_c16(uint_least32_t c32, int *length, uint_least16_t c16[2]);
|
||||
|
||||
/* Construct UTF-32 Unicode code point from UTF-16 surrogate pair. high
|
||||
* must be high surrogate and low must be low surrogate otherwise *c32 will
|
||||
* be filled with special replacement character U+FFFD and false will be returned.
|
||||
* c16 -- where to put UTF-16 sequence (c32[0] -- high surrogate, c32[1] -- low surrogate)
|
||||
* result -- true if c16 points to a valid UTF-16 sequence (single not surrogate
|
||||
* or valid surrogate pair) or false otherwise. */
|
||||
bool libutf_c16_to_c32(uint_least16_t c16[2], uint_least32_t *c32);
|
||||
|
||||
/* Check whether given value is a valid Unicode code point i.e. below 0x110000 and is not
|
||||
* a UTF-16 surrogate. */
|
||||
bool libutf_c32_is_valid(uint_least32_t c32);
|
||||
|
||||
#endif
|
||||
99
src/quickjs/list.h
Normal file
99
src/quickjs/list.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Linux klist like system
|
||||
*
|
||||
* Copyright (c) 2016-2017 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#ifndef NULL
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
struct list_head {
|
||||
struct list_head *prev;
|
||||
struct list_head *next;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
||||
|
||||
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
||||
#define list_entry(el, type, member) container_of(el, type, member)
|
||||
|
||||
static inline void init_list_head(struct list_head *head)
|
||||
{
|
||||
head->prev = head;
|
||||
head->next = head;
|
||||
}
|
||||
|
||||
/* insert 'el' between 'prev' and 'next' */
|
||||
static inline void __list_add(struct list_head *el,
|
||||
struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
prev->next = el;
|
||||
el->prev = prev;
|
||||
el->next = next;
|
||||
next->prev = el;
|
||||
}
|
||||
|
||||
/* add 'el' at the head of the list 'head' (= after element head) */
|
||||
static inline void list_add(struct list_head *el, struct list_head *head)
|
||||
{
|
||||
__list_add(el, head, head->next);
|
||||
}
|
||||
|
||||
/* add 'el' at the end of the list 'head' (= before element head) */
|
||||
static inline void list_add_tail(struct list_head *el, struct list_head *head)
|
||||
{
|
||||
__list_add(el, head->prev, head);
|
||||
}
|
||||
|
||||
static inline void list_del(struct list_head *el)
|
||||
{
|
||||
struct list_head *prev, *next;
|
||||
prev = el->prev;
|
||||
next = el->next;
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
el->prev = NULL; /* fail safe */
|
||||
el->next = NULL; /* fail safe */
|
||||
}
|
||||
|
||||
static inline int list_empty(struct list_head *el)
|
||||
{
|
||||
return el->next == el;
|
||||
}
|
||||
|
||||
#define list_for_each(el, head) \
|
||||
for(el = (head)->next; el != (head); el = el->next)
|
||||
|
||||
#define list_for_each_safe(el, el1, head) \
|
||||
for(el = (head)->next, el1 = el->next; el != (head); \
|
||||
el = el1, el1 = el->next)
|
||||
|
||||
#define list_for_each_prev(el, head) \
|
||||
for(el = (head)->prev; el != (head); el = el->prev)
|
||||
|
||||
#define list_for_each_prev_safe(el, el1, head) \
|
||||
for(el = (head)->prev, el1 = el->prev; el != (head); \
|
||||
el = el1, el1 = el->prev)
|
||||
|
||||
#endif /* LIST_H */
|
||||
552
src/quickjs/qjs.c
Normal file
552
src/quickjs/qjs.c
Normal file
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* QuickJS stand alone interpreter
|
||||
*
|
||||
* Copyright (c) 2017-2021 Fabrice Bellard
|
||||
* Copyright (c) 2017-2021 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if defined(__APPLE__)
|
||||
#include <malloc/malloc.h>
|
||||
#elif defined(__linux__)
|
||||
#include <malloc.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <malloc_np.h>
|
||||
#endif
|
||||
|
||||
#include "cutils.h"
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
#ifdef CONFIG_BIGNUM
|
||||
static int bignum_ext;
|
||||
#endif
|
||||
|
||||
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||
const char *filename, int eval_flags)
|
||||
{
|
||||
JSValue val;
|
||||
int ret;
|
||||
|
||||
if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) {
|
||||
/* for the modules, we compile then run to be able to set
|
||||
import.meta */
|
||||
val = JS_Eval(ctx, buf, buf_len, filename,
|
||||
eval_flags | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
if (!JS_IsException(val)) {
|
||||
js_module_set_import_meta(ctx, val, TRUE, TRUE);
|
||||
val = JS_EvalFunction(ctx, val);
|
||||
}
|
||||
val = js_std_await(ctx, val);
|
||||
} else {
|
||||
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
||||
}
|
||||
if (JS_IsException(val)) {
|
||||
js_std_dump_error(ctx);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
JS_FreeValue(ctx, val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eval_file(JSContext *ctx, const char *filename, int module)
|
||||
{
|
||||
uint8_t *buf;
|
||||
int ret, eval_flags;
|
||||
size_t buf_len;
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (module < 0) {
|
||||
module = (has_suffix(filename, ".mjs") ||
|
||||
JS_DetectModule((const char *)buf, buf_len));
|
||||
}
|
||||
if (module)
|
||||
eval_flags = JS_EVAL_TYPE_MODULE;
|
||||
else
|
||||
eval_flags = JS_EVAL_TYPE_GLOBAL;
|
||||
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
|
||||
js_free(ctx, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* also used to initialize the worker context */
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx;
|
||||
ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (bignum_ext) {
|
||||
JS_AddIntrinsicBigFloat(ctx);
|
||||
JS_AddIntrinsicBigDecimal(ctx);
|
||||
JS_AddIntrinsicOperators(ctx);
|
||||
JS_EnableBignumExt(ctx, TRUE);
|
||||
}
|
||||
#endif
|
||||
/* system modules */
|
||||
js_init_module_std(ctx, "std");
|
||||
js_init_module_os(ctx, "os");
|
||||
return ctx;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define MALLOC_OVERHEAD 0
|
||||
#else
|
||||
#define MALLOC_OVERHEAD 8
|
||||
#endif
|
||||
|
||||
struct trace_malloc_data {
|
||||
uint8_t *base;
|
||||
};
|
||||
|
||||
static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
|
||||
struct trace_malloc_data *dp)
|
||||
{
|
||||
return ptr - dp->base;
|
||||
}
|
||||
|
||||
/* default memory allocation functions with memory limitation */
|
||||
static size_t js_trace_malloc_usable_size(const void *ptr)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
return malloc_size(ptr);
|
||||
#elif defined(_WIN32)
|
||||
return _msize((void *)ptr);
|
||||
#elif defined(EMSCRIPTEN)
|
||||
return 0;
|
||||
#elif defined(__linux__)
|
||||
return malloc_usable_size((void *)ptr);
|
||||
#else
|
||||
/* change this to `return 0;` if compilation fails */
|
||||
return malloc_usable_size((void *)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef _WIN32
|
||||
/* mingw printf is used */
|
||||
__attribute__((format(gnu_printf, 2, 3)))
|
||||
#else
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int c;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while ((c = *fmt++) != '\0') {
|
||||
if (c == '%') {
|
||||
/* only handle %p and %zd */
|
||||
if (*fmt == 'p') {
|
||||
uint8_t *ptr = va_arg(ap, void *);
|
||||
if (ptr == NULL) {
|
||||
printf("NULL");
|
||||
} else {
|
||||
printf("H%+06lld.%zd",
|
||||
js_trace_malloc_ptr_offset(ptr, s->opaque),
|
||||
js_trace_malloc_usable_size(ptr));
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
if (fmt[0] == 'z' && fmt[1] == 'd') {
|
||||
size_t sz = va_arg(ap, size_t);
|
||||
printf("%zd", sz);
|
||||
fmt += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
putc(c, stdout);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void js_trace_malloc_init(struct trace_malloc_data *s)
|
||||
{
|
||||
free(s->base = malloc(8));
|
||||
}
|
||||
|
||||
static void *js_trace_malloc(JSMallocState *s, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
/* Do not allocate zero bytes: behavior is platform dependent */
|
||||
assert(size != 0);
|
||||
|
||||
if (unlikely(s->malloc_size + size > s->malloc_limit))
|
||||
return NULL;
|
||||
ptr = malloc(size);
|
||||
js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr);
|
||||
if (ptr) {
|
||||
s->malloc_count++;
|
||||
s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void js_trace_free(JSMallocState *s, void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
js_trace_malloc_printf(s, "F %p\n", ptr);
|
||||
s->malloc_count--;
|
||||
s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
|
||||
{
|
||||
size_t old_size;
|
||||
|
||||
if (!ptr) {
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
return js_trace_malloc(s, size);
|
||||
}
|
||||
old_size = js_trace_malloc_usable_size(ptr);
|
||||
if (size == 0) {
|
||||
js_trace_malloc_printf(s, "R %zd %p\n", size, ptr);
|
||||
s->malloc_count--;
|
||||
s->malloc_size -= old_size + MALLOC_OVERHEAD;
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
if (s->malloc_size + size - old_size > s->malloc_limit)
|
||||
return NULL;
|
||||
|
||||
js_trace_malloc_printf(s, "R %zd %p", size, ptr);
|
||||
|
||||
ptr = realloc(ptr, size);
|
||||
js_trace_malloc_printf(s, " -> %p\n", ptr);
|
||||
if (ptr) {
|
||||
s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static const JSMallocFunctions trace_mf = {
|
||||
js_trace_malloc,
|
||||
js_trace_free,
|
||||
js_trace_realloc,
|
||||
js_trace_malloc_usable_size,
|
||||
};
|
||||
|
||||
#define PROG_NAME "qjs"
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("QuickJS lite\n"
|
||||
"usage: " PROG_NAME " [options] [file [args]]\n"
|
||||
"-h --help list options\n"
|
||||
"-e --eval EXPR evaluate EXPR\n"
|
||||
"-i --interactive go to interactive mode\n"
|
||||
"-m --module load as ES6 module (default=autodetect)\n"
|
||||
" --script load as ES6 script (default=autodetect)\n"
|
||||
"-I --include file include an additional file\n"
|
||||
" --std make 'std' and 'os' available to the loaded script\n"
|
||||
#ifdef CONFIG_BIGNUM
|
||||
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
|
||||
" --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n"
|
||||
#endif
|
||||
"-T --trace trace memory allocation\n"
|
||||
"-d --dump dump the memory usage stats\n"
|
||||
" --memory-limit n limit the memory usage to 'n' bytes\n"
|
||||
" --stack-size n limit the stack size to 'n' bytes\n"
|
||||
" --unhandled-rejection dump unhandled promise rejections\n"
|
||||
"-q --quit just instantiate the interpreter and quit\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
struct trace_malloc_data trace_data = { NULL };
|
||||
int optind;
|
||||
char *expr = NULL;
|
||||
int interactive = 0;
|
||||
int dump_memory = 0;
|
||||
int trace_memory = 0;
|
||||
int empty_run = 0;
|
||||
int module = -1;
|
||||
int load_std = 0;
|
||||
int dump_unhandled_promise_rejection = 0;
|
||||
size_t memory_limit = 0;
|
||||
char *include_list[32];
|
||||
int i, include_count = 0;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
int load_jscalc;
|
||||
#endif
|
||||
size_t stack_size = 0;
|
||||
|
||||
#ifdef CONFIG_BIGNUM
|
||||
/* load jscalc runtime if invoked as 'qjscalc' */
|
||||
{
|
||||
const char *p, *exename;
|
||||
exename = argv[0];
|
||||
p = strrchr(exename, '/');
|
||||
if (p)
|
||||
exename = p + 1;
|
||||
load_jscalc = !strcmp(exename, "qjscalc");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* cannot use getopt because we want to pass the command line to
|
||||
the script */
|
||||
optind = 1;
|
||||
while (optind < argc && *argv[optind] == '-') {
|
||||
char *arg = argv[optind] + 1;
|
||||
const char *longopt = "";
|
||||
/* a single - is not an option, it also stops argument scanning */
|
||||
if (!*arg)
|
||||
break;
|
||||
optind++;
|
||||
if (*arg == '-') {
|
||||
longopt = arg + 1;
|
||||
arg += strlen(arg);
|
||||
/* -- stops argument scanning */
|
||||
if (!*longopt)
|
||||
break;
|
||||
}
|
||||
for (; *arg || *longopt; longopt = "") {
|
||||
char opt = *arg;
|
||||
if (opt)
|
||||
arg++;
|
||||
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
|
||||
help();
|
||||
continue;
|
||||
}
|
||||
if (opt == 'e' || !strcmp(longopt, "eval")) {
|
||||
if (*arg) {
|
||||
expr = arg;
|
||||
break;
|
||||
}
|
||||
if (optind < argc) {
|
||||
expr = argv[optind++];
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "qjs: missing expression for -e\n");
|
||||
exit(2);
|
||||
}
|
||||
if (opt == 'I' || !strcmp(longopt, "include")) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting filename");
|
||||
exit(1);
|
||||
}
|
||||
if (include_count >= countof(include_list)) {
|
||||
fprintf(stderr, "too many included files");
|
||||
exit(1);
|
||||
}
|
||||
include_list[include_count++] = argv[optind++];
|
||||
continue;
|
||||
}
|
||||
if (opt == 'i' || !strcmp(longopt, "interactive")) {
|
||||
interactive++;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'm' || !strcmp(longopt, "module")) {
|
||||
module = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "script")) {
|
||||
module = 0;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'd' || !strcmp(longopt, "dump")) {
|
||||
dump_memory++;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'T' || !strcmp(longopt, "trace")) {
|
||||
trace_memory++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "std")) {
|
||||
load_std = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "unhandled-rejection")) {
|
||||
dump_unhandled_promise_rejection = 1;
|
||||
continue;
|
||||
}
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (!strcmp(longopt, "bignum")) {
|
||||
bignum_ext = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "qjscalc")) {
|
||||
load_jscalc = 1;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (opt == 'q' || !strcmp(longopt, "quit")) {
|
||||
empty_run++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "memory-limit")) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting memory limit");
|
||||
exit(1);
|
||||
}
|
||||
memory_limit = (size_t)strtod(argv[optind++], NULL);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "stack-size")) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting stack size");
|
||||
exit(1);
|
||||
}
|
||||
stack_size = (size_t)strtod(argv[optind++], NULL);
|
||||
continue;
|
||||
}
|
||||
if (opt) {
|
||||
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
|
||||
} else {
|
||||
fprintf(stderr, "qjs: unknown option '--%s'\n", longopt);
|
||||
}
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (load_jscalc)
|
||||
bignum_ext = 1;
|
||||
#endif
|
||||
|
||||
if (trace_memory) {
|
||||
js_trace_malloc_init(&trace_data);
|
||||
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
||||
} else {
|
||||
rt = JS_NewRuntime();
|
||||
}
|
||||
if (!rt) {
|
||||
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
|
||||
exit(2);
|
||||
}
|
||||
if (memory_limit != 0)
|
||||
JS_SetMemoryLimit(rt, memory_limit);
|
||||
if (stack_size != 0)
|
||||
JS_SetMaxStackSize(rt, stack_size);
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "qjs: cannot allocate JS context\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* loader for ES6 modules */
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
|
||||
if (dump_unhandled_promise_rejection) {
|
||||
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!empty_run) {
|
||||
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
||||
|
||||
/* make 'std' and 'os' visible to non module code */
|
||||
if (load_std) {
|
||||
const char *str = "import * as std from 'std';\n"
|
||||
"import * as os from 'os';\n"
|
||||
"globalThis.std = std;\n"
|
||||
"globalThis.os = os;\n";
|
||||
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
}
|
||||
|
||||
for(i = 0; i < include_count; i++) {
|
||||
if (eval_file(ctx, include_list[i], module))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (expr) {
|
||||
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0))
|
||||
goto fail;
|
||||
} else
|
||||
if (optind >= argc) {
|
||||
/* interactive mode */
|
||||
interactive = 1;
|
||||
} else {
|
||||
const char *filename;
|
||||
filename = argv[optind];
|
||||
if (eval_file(ctx, filename, module))
|
||||
goto fail;
|
||||
}
|
||||
js_std_loop(ctx);
|
||||
}
|
||||
|
||||
if (dump_memory) {
|
||||
JSMemoryUsage stats;
|
||||
JS_ComputeMemoryUsage(rt, &stats);
|
||||
JS_DumpMemoryUsage(stdout, &stats, rt);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
if (empty_run && dump_memory) {
|
||||
clock_t t[5];
|
||||
double best[5];
|
||||
int i, j;
|
||||
for (i = 0; i < 100; i++) {
|
||||
t[0] = clock();
|
||||
rt = JS_NewRuntime();
|
||||
t[1] = clock();
|
||||
ctx = JS_NewContext(rt);
|
||||
t[2] = clock();
|
||||
JS_FreeContext(ctx);
|
||||
t[3] = clock();
|
||||
JS_FreeRuntime(rt);
|
||||
t[4] = clock();
|
||||
for (j = 4; j > 0; j--) {
|
||||
double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC;
|
||||
if (i == 0 || best[j] > ms)
|
||||
best[j] = ms;
|
||||
}
|
||||
}
|
||||
printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n",
|
||||
best[1] + best[2] + best[3] + best[4],
|
||||
best[1], best[2], best[3], best[4]);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 1;
|
||||
}
|
||||
761
src/quickjs/qjsc.c
Normal file
761
src/quickjs/qjsc.c
Normal file
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
* QuickJS command line compiler
|
||||
*
|
||||
* Copyright (c) 2018-2021 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include "cutils.h"
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *short_name;
|
||||
int flags;
|
||||
} namelist_entry_t;
|
||||
|
||||
typedef struct namelist_t {
|
||||
namelist_entry_t *array;
|
||||
int count;
|
||||
int size;
|
||||
} namelist_t;
|
||||
|
||||
typedef struct {
|
||||
const char *option_name;
|
||||
const char *init_name;
|
||||
} FeatureEntry;
|
||||
|
||||
static namelist_t cname_list;
|
||||
static namelist_t cmodule_list;
|
||||
static namelist_t init_module_list;
|
||||
static uint64_t feature_bitmap;
|
||||
static FILE *outfile;
|
||||
static BOOL byte_swap;
|
||||
static BOOL dynamic_export;
|
||||
static const char *c_ident_prefix = "qjsc_";
|
||||
|
||||
#define FE_ALL (-1)
|
||||
|
||||
static const FeatureEntry feature_list[] = {
|
||||
{ "date", "Date" },
|
||||
{ "eval", "Eval" },
|
||||
{ "string-normalize", "StringNormalize" },
|
||||
{ "regexp", "RegExp" },
|
||||
{ "json", "JSON" },
|
||||
{ "proxy", "Proxy" },
|
||||
{ "map", "MapSet" },
|
||||
{ "typedarray", "TypedArrays" },
|
||||
{ "promise", "Promise" },
|
||||
#define FE_MODULE_LOADER 9
|
||||
{ "module-loader", NULL },
|
||||
{ "bigint", "BigInt" },
|
||||
};
|
||||
|
||||
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||
int flags)
|
||||
{
|
||||
namelist_entry_t *e;
|
||||
if (lp->count == lp->size) {
|
||||
size_t newsize = lp->size + (lp->size >> 1) + 4;
|
||||
namelist_entry_t *a =
|
||||
realloc(lp->array, sizeof(lp->array[0]) * newsize);
|
||||
/* XXX: check for realloc failure */
|
||||
lp->array = a;
|
||||
lp->size = newsize;
|
||||
}
|
||||
e = &lp->array[lp->count++];
|
||||
e->name = strdup(name);
|
||||
if (short_name)
|
||||
e->short_name = strdup(short_name);
|
||||
else
|
||||
e->short_name = NULL;
|
||||
e->flags = flags;
|
||||
}
|
||||
|
||||
void namelist_free(namelist_t *lp)
|
||||
{
|
||||
while (lp->count > 0) {
|
||||
namelist_entry_t *e = &lp->array[--lp->count];
|
||||
free(e->name);
|
||||
free(e->short_name);
|
||||
}
|
||||
free(lp->array);
|
||||
lp->array = NULL;
|
||||
lp->size = 0;
|
||||
}
|
||||
|
||||
namelist_entry_t *namelist_find(namelist_t *lp, const char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < lp->count; i++) {
|
||||
namelist_entry_t *e = &lp->array[i];
|
||||
if (!strcmp(e->name, name))
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_c_name(char *buf, size_t buf_size, const char *file)
|
||||
{
|
||||
const char *p, *r;
|
||||
size_t len, i;
|
||||
int c;
|
||||
char *q;
|
||||
|
||||
p = strrchr(file, '/');
|
||||
if (!p)
|
||||
p = file;
|
||||
else
|
||||
p++;
|
||||
r = strrchr(p, '.');
|
||||
if (!r)
|
||||
len = strlen(p);
|
||||
else
|
||||
len = r - p;
|
||||
pstrcpy(buf, buf_size, c_ident_prefix);
|
||||
q = buf + strlen(buf);
|
||||
for(i = 0; i < len; i++) {
|
||||
c = p[i];
|
||||
if (!((c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z'))) {
|
||||
c = '_';
|
||||
}
|
||||
if ((q - buf) < buf_size - 1)
|
||||
*q++ = c;
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
|
||||
{
|
||||
size_t i, col;
|
||||
col = 0;
|
||||
for(i = 0; i < len; i++) {
|
||||
fprintf(f, " 0x%02x,", buf[i]);
|
||||
if (++col == 8) {
|
||||
fprintf(f, "\n");
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
if (col != 0)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static void output_object_code(JSContext *ctx,
|
||||
FILE *fo, JSValueConst obj, const char *c_name,
|
||||
BOOL load_only)
|
||||
{
|
||||
uint8_t *out_buf;
|
||||
size_t out_buf_len;
|
||||
int flags;
|
||||
flags = JS_WRITE_OBJ_BYTECODE;
|
||||
if (byte_swap)
|
||||
flags |= JS_WRITE_OBJ_BSWAP;
|
||||
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
||||
if (!out_buf) {
|
||||
js_std_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
namelist_add(&cname_list, c_name, NULL, load_only);
|
||||
|
||||
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
dump_hex(fo, out_buf, out_buf_len);
|
||||
fprintf(fo, "};\n\n");
|
||||
|
||||
js_free(ctx, out_buf);
|
||||
}
|
||||
|
||||
static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
/* should never be called when compiling JS code */
|
||||
abort();
|
||||
}
|
||||
|
||||
static void find_unique_cname(char *cname, size_t cname_size)
|
||||
{
|
||||
char cname1[1024];
|
||||
int suffix_num;
|
||||
size_t len, max_len;
|
||||
assert(cname_size >= 32);
|
||||
/* find a C name not matching an existing module C name by
|
||||
adding a numeric suffix */
|
||||
len = strlen(cname);
|
||||
max_len = cname_size - 16;
|
||||
if (len > max_len)
|
||||
cname[max_len] = '\0';
|
||||
suffix_num = 1;
|
||||
for(;;) {
|
||||
snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num);
|
||||
if (!namelist_find(&cname_list, cname1))
|
||||
break;
|
||||
suffix_num++;
|
||||
}
|
||||
pstrcpy(cname, cname_size, cname1);
|
||||
}
|
||||
|
||||
JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
const char *module_name, void *opaque)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
namelist_entry_t *e;
|
||||
|
||||
/* check if it is a declared C or system module */
|
||||
e = namelist_find(&cmodule_list, module_name);
|
||||
if (e) {
|
||||
/* add in the static init module list */
|
||||
namelist_add(&init_module_list, e->name, e->short_name, 0);
|
||||
/* create a dummy module */
|
||||
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||
} else if (has_suffix(module_name, ".so")) {
|
||||
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
|
||||
/* create a dummy module */
|
||||
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||
/* the resulting executable will export its symbols for the
|
||||
dynamic library */
|
||||
dynamic_export = TRUE;
|
||||
} else {
|
||||
size_t buf_len;
|
||||
uint8_t *buf;
|
||||
JSValue func_val;
|
||||
char cname[1024];
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, module_name);
|
||||
if (!buf) {
|
||||
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||
module_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* compile the module */
|
||||
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
js_free(ctx, buf);
|
||||
if (JS_IsException(func_val))
|
||||
return NULL;
|
||||
get_c_name(cname, sizeof(cname), module_name);
|
||||
if (namelist_find(&cname_list, cname)) {
|
||||
find_unique_cname(cname, sizeof(cname));
|
||||
}
|
||||
output_object_code(ctx, outfile, func_val, cname, TRUE);
|
||||
|
||||
/* the module is already referenced, so we must free it */
|
||||
m = JS_VALUE_GET_PTR(func_val);
|
||||
JS_FreeValue(ctx, func_val);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void compile_file(JSContext *ctx, FILE *fo,
|
||||
const char *filename,
|
||||
const char *c_name1,
|
||||
int module)
|
||||
{
|
||||
uint8_t *buf;
|
||||
char c_name[1024];
|
||||
int eval_flags;
|
||||
JSValue obj;
|
||||
size_t buf_len;
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
|
||||
if (module < 0) {
|
||||
module = (has_suffix(filename, ".mjs") ||
|
||||
JS_DetectModule((const char *)buf, buf_len));
|
||||
}
|
||||
if (module)
|
||||
eval_flags |= JS_EVAL_TYPE_MODULE;
|
||||
else
|
||||
eval_flags |= JS_EVAL_TYPE_GLOBAL;
|
||||
obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags);
|
||||
if (JS_IsException(obj)) {
|
||||
js_std_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
js_free(ctx, buf);
|
||||
if (c_name1) {
|
||||
pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||
} else {
|
||||
get_c_name(c_name, sizeof(c_name), filename);
|
||||
}
|
||||
output_object_code(ctx, fo, obj, c_name, FALSE);
|
||||
JS_FreeValue(ctx, obj);
|
||||
}
|
||||
|
||||
static const char main_c_template1[] =
|
||||
"int main(int argc, char **argv)\n"
|
||||
"{\n"
|
||||
" JSRuntime *rt;\n"
|
||||
" JSContext *ctx;\n"
|
||||
" rt = JS_NewRuntime();\n"
|
||||
" js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
|
||||
" js_std_init_handlers(rt);\n"
|
||||
;
|
||||
|
||||
static const char main_c_template2[] =
|
||||
" js_std_loop(ctx);\n"
|
||||
" js_std_free_handlers(rt);\n"
|
||||
" JS_FreeContext(ctx);\n"
|
||||
" JS_FreeRuntime(rt);\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
|
||||
#define PROG_NAME "qjsc"
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
|
||||
"usage: " PROG_NAME " [options] [files]\n"
|
||||
"\n"
|
||||
"options are:\n"
|
||||
"-c only output bytecode to a C file\n"
|
||||
"-e output main() and bytecode to a C file (default = executable output)\n"
|
||||
"-o output set the output filename\n"
|
||||
"-N cname set the C name of the generated data\n"
|
||||
"-m compile as Javascript module (default=autodetect)\n"
|
||||
"-D module_name compile a dynamically loaded module or worker\n"
|
||||
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||
"-x byte swapped output\n"
|
||||
"-p prefix set the prefix of the generated C names\n"
|
||||
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
||||
JS_DEFAULT_STACK_SIZE);
|
||||
#ifdef CONFIG_LTO
|
||||
{
|
||||
int i;
|
||||
printf("-flto use link time optimization\n");
|
||||
printf("-fbignum enable bignum extensions\n");
|
||||
printf("-fno-[");
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if (i != 0)
|
||||
printf("|");
|
||||
printf("%s", feature_list[i].option_name);
|
||||
}
|
||||
printf("]\n"
|
||||
" disable selected language features (smaller code size)\n");
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CC) && !defined(_WIN32)
|
||||
|
||||
int exec_cmd(char **argv)
|
||||
{
|
||||
int pid, status, ret;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
execvp(argv[0], argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
ret = waitpid(pid, &status, 0);
|
||||
if (ret == pid && WIFEXITED(status))
|
||||
break;
|
||||
}
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
static int output_executable(const char *out_filename, const char *cfilename,
|
||||
BOOL use_lto, BOOL verbose, const char *exename)
|
||||
{
|
||||
const char *argv[64];
|
||||
const char **arg, *bn_suffix, *lto_suffix;
|
||||
char libjsname[1024];
|
||||
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
|
||||
int ret;
|
||||
|
||||
/* get the directory of the executable */
|
||||
pstrcpy(exe_dir, sizeof(exe_dir), exename);
|
||||
p = strrchr(exe_dir, '/');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
} else {
|
||||
pstrcpy(exe_dir, sizeof(exe_dir), ".");
|
||||
}
|
||||
|
||||
/* if 'quickjs.h' is present at the same path as the executable, we
|
||||
use it as include and lib directory */
|
||||
snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir);
|
||||
if (access(buf, R_OK) == 0) {
|
||||
pstrcpy(inc_dir, sizeof(inc_dir), exe_dir);
|
||||
pstrcpy(lib_dir, sizeof(lib_dir), exe_dir);
|
||||
} else {
|
||||
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
|
||||
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
|
||||
}
|
||||
|
||||
lto_suffix = "";
|
||||
bn_suffix = "";
|
||||
|
||||
arg = argv;
|
||||
*arg++ = CONFIG_CC;
|
||||
*arg++ = "-O2";
|
||||
#ifdef CONFIG_LTO
|
||||
if (use_lto) {
|
||||
*arg++ = "-flto";
|
||||
lto_suffix = ".lto";
|
||||
}
|
||||
#endif
|
||||
/* XXX: use the executable path to find the includes files and
|
||||
libraries */
|
||||
*arg++ = "-D";
|
||||
*arg++ = "_GNU_SOURCE";
|
||||
*arg++ = "-I";
|
||||
*arg++ = inc_dir;
|
||||
*arg++ = "-o";
|
||||
*arg++ = out_filename;
|
||||
if (dynamic_export)
|
||||
*arg++ = "-rdynamic";
|
||||
*arg++ = cfilename;
|
||||
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
|
||||
lib_dir, bn_suffix, lto_suffix);
|
||||
*arg++ = libjsname;
|
||||
*arg++ = "-lm";
|
||||
*arg++ = "-ldl";
|
||||
*arg++ = "-lpthread";
|
||||
*arg = NULL;
|
||||
|
||||
if (verbose) {
|
||||
for(arg = argv; *arg != NULL; arg++)
|
||||
printf("%s ", *arg);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
ret = exec_cmd((char **)argv);
|
||||
unlink(cfilename);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int output_executable(const char *out_filename, const char *cfilename,
|
||||
BOOL use_lto, BOOL verbose, const char *exename)
|
||||
{
|
||||
fprintf(stderr, "Executable output is not supported for this target\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
OUTPUT_C,
|
||||
OUTPUT_C_MAIN,
|
||||
OUTPUT_EXECUTABLE,
|
||||
} OutputTypeEnum;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c, i, verbose;
|
||||
const char *out_filename, *cname;
|
||||
char cfilename[1024];
|
||||
FILE *fo;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
BOOL use_lto;
|
||||
int module;
|
||||
OutputTypeEnum output_type;
|
||||
size_t stack_size;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
BOOL bignum_ext = FALSE;
|
||||
#endif
|
||||
namelist_t dynamic_module_list;
|
||||
|
||||
out_filename = NULL;
|
||||
output_type = OUTPUT_EXECUTABLE;
|
||||
cname = NULL;
|
||||
feature_bitmap = FE_ALL;
|
||||
module = -1;
|
||||
byte_swap = FALSE;
|
||||
verbose = 0;
|
||||
use_lto = FALSE;
|
||||
stack_size = 0;
|
||||
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
|
||||
|
||||
/* add system modules */
|
||||
namelist_add(&cmodule_list, "std", "std", 0);
|
||||
namelist_add(&cmodule_list, "os", "os", 0);
|
||||
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch(c) {
|
||||
case 'h':
|
||||
help();
|
||||
case 'o':
|
||||
out_filename = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
output_type = OUTPUT_C;
|
||||
break;
|
||||
case 'e':
|
||||
output_type = OUTPUT_C_MAIN;
|
||||
break;
|
||||
case 'N':
|
||||
cname = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
{
|
||||
const char *p;
|
||||
p = optarg;
|
||||
if (!strcmp(optarg, "lto")) {
|
||||
use_lto = TRUE;
|
||||
} else if (strstart(p, "no-", &p)) {
|
||||
use_lto = TRUE;
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if (!strcmp(p, feature_list[i].option_name)) {
|
||||
feature_bitmap &= ~((uint64_t)1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == countof(feature_list))
|
||||
goto bad_feature;
|
||||
} else
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (!strcmp(optarg, "bignum")) {
|
||||
bignum_ext = TRUE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bad_feature:
|
||||
fprintf(stderr, "unsupported feature: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
module = 1;
|
||||
break;
|
||||
case 'M':
|
||||
{
|
||||
char *p;
|
||||
char path[1024];
|
||||
char cname[1024];
|
||||
pstrcpy(path, sizeof(path), optarg);
|
||||
p = strchr(path, ',');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
pstrcpy(cname, sizeof(cname), p + 1);
|
||||
} else {
|
||||
get_c_name(cname, sizeof(cname), path);
|
||||
}
|
||||
namelist_add(&cmodule_list, path, cname, 0);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
namelist_add(&dynamic_module_list, optarg, NULL, 0);
|
||||
break;
|
||||
case 'x':
|
||||
byte_swap = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'p':
|
||||
c_ident_prefix = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
stack_size = (size_t)strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
help();
|
||||
|
||||
if (!out_filename) {
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
out_filename = "a.out";
|
||||
} else {
|
||||
out_filename = "out.c";
|
||||
}
|
||||
}
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
/* XXX: find a /tmp directory ? */
|
||||
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
|
||||
#else
|
||||
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
|
||||
#endif
|
||||
} else {
|
||||
pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
}
|
||||
|
||||
fo = fopen(cfilename, "w");
|
||||
if (!fo) {
|
||||
perror(cfilename);
|
||||
exit(1);
|
||||
}
|
||||
outfile = fo;
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_NewContext(rt);
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (bignum_ext) {
|
||||
JS_AddIntrinsicBigFloat(ctx);
|
||||
JS_AddIntrinsicBigDecimal(ctx);
|
||||
JS_AddIntrinsicOperators(ctx);
|
||||
JS_EnableBignumExt(ctx, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* loader for ES6 modules */
|
||||
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
|
||||
|
||||
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
if (output_type != OUTPUT_C) {
|
||||
fprintf(fo, "#include \"quickjs-libc.h\"\n"
|
||||
"\n"
|
||||
);
|
||||
} else {
|
||||
fprintf(fo, "#include <inttypes.h>\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
for(i = optind; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
compile_file(ctx, fo, filename, cname, module);
|
||||
cname = NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < dynamic_module_list.count; i++) {
|
||||
if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
|
||||
fprintf(stderr, "Could not load dynamic module '%s'\n",
|
||||
dynamic_module_list.array[i].name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_type != OUTPUT_C) {
|
||||
fprintf(fo,
|
||||
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
|
||||
"{\n"
|
||||
" JSContext *ctx = JS_NewContextRaw(rt);\n"
|
||||
" if (!ctx)\n"
|
||||
" return NULL;\n");
|
||||
/* add the basic objects */
|
||||
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if ((feature_bitmap & ((uint64_t)1 << i)) &&
|
||||
feature_list[i].init_name) {
|
||||
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
|
||||
feature_list[i].init_name);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (bignum_ext) {
|
||||
fprintf(fo,
|
||||
" JS_AddIntrinsicBigFloat(ctx);\n"
|
||||
" JS_AddIntrinsicBigDecimal(ctx);\n"
|
||||
" JS_AddIntrinsicOperators(ctx);\n"
|
||||
" JS_EnableBignumExt(ctx, 1);\n");
|
||||
}
|
||||
#endif
|
||||
/* add the precompiled modules (XXX: could modify the module
|
||||
loader instead) */
|
||||
for(i = 0; i < init_module_list.count; i++) {
|
||||
namelist_entry_t *e = &init_module_list.array[i];
|
||||
/* initialize the static C modules */
|
||||
|
||||
fprintf(fo,
|
||||
" {\n"
|
||||
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||
" js_init_module_%s(ctx, \"%s\");\n"
|
||||
" }\n",
|
||||
e->short_name, e->short_name, e->name);
|
||||
}
|
||||
for(i = 0; i < cname_list.count; i++) {
|
||||
namelist_entry_t *e = &cname_list.array[i];
|
||||
if (e->flags) {
|
||||
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n",
|
||||
e->name, e->name);
|
||||
}
|
||||
}
|
||||
fprintf(fo,
|
||||
" return ctx;\n"
|
||||
"}\n\n");
|
||||
|
||||
fputs(main_c_template1, fo);
|
||||
|
||||
if (stack_size != 0) {
|
||||
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
|
||||
(unsigned int)stack_size);
|
||||
}
|
||||
|
||||
/* add the module loader if necessary */
|
||||
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
|
||||
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
|
||||
}
|
||||
|
||||
fprintf(fo,
|
||||
" ctx = JS_NewCustomContext(rt);\n"
|
||||
" js_std_add_helpers(ctx, argc, argv);\n");
|
||||
|
||||
for(i = 0; i < cname_list.count; i++) {
|
||||
namelist_entry_t *e = &cname_list.array[i];
|
||||
if (!e->flags) {
|
||||
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
|
||||
e->name, e->name);
|
||||
}
|
||||
}
|
||||
fputs(main_c_template2, fo);
|
||||
}
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
fclose(fo);
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
return output_executable(out_filename, cfilename, use_lto, verbose,
|
||||
argv[0]);
|
||||
}
|
||||
namelist_free(&cname_list);
|
||||
namelist_free(&cmodule_list);
|
||||
namelist_free(&init_module_list);
|
||||
return 0;
|
||||
}
|
||||
87
src/quickjs/qsort_r.c
Normal file
87
src/quickjs/qsort_r.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void
|
||||
exch(char* base, size_t size, size_t a, size_t b) {
|
||||
char* x = base + a * size;
|
||||
char* y = base + b * size;
|
||||
while(size) {
|
||||
char z = *x;
|
||||
*x = *y;
|
||||
*y = z;
|
||||
--size;
|
||||
++x;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
#define RAND
|
||||
|
||||
/* Quicksort with 3-way partitioning, ala Sedgewick */
|
||||
/* Blame him for the scary variable names */
|
||||
/* http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf */
|
||||
static void
|
||||
quicksort(char* base, size_t size, ssize_t l, ssize_t r, int (*compar)(const void*, const void*, void*), void* ptr) {
|
||||
ssize_t i = l - 1, j = r, p = l - 1, q = r, k;
|
||||
char* v = base + r * size;
|
||||
if(r <= l)
|
||||
return;
|
||||
|
||||
#ifdef RAND
|
||||
/*
|
||||
We chose the rightmost element in the array to be sorted as pivot,
|
||||
which is OK if the data is random, but which is horrible if the
|
||||
data is already sorted. Try to improve by exchanging it with a
|
||||
random other pivot.
|
||||
*/
|
||||
exch(base, size, l + (rand() % (r - l)), r);
|
||||
#elif defined MID
|
||||
/*
|
||||
We chose the rightmost element in the array to be sorted as pivot,
|
||||
which is OK if the data is random, but which is horrible if the
|
||||
data is already sorted. Try to improve by chosing the middle
|
||||
element instead.
|
||||
*/
|
||||
exch(base, size, l + (r - l) / 2, r);
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
while(++i != r && compar(base + i * size, v, ptr) < 0)
|
||||
;
|
||||
while(compar(v, base + (--j) * size, ptr) < 0)
|
||||
if(j == l)
|
||||
break;
|
||||
if(i >= j)
|
||||
break;
|
||||
exch(base, size, i, j);
|
||||
if(compar(base + i * size, v, ptr) == 0)
|
||||
exch(base, size, ++p, i);
|
||||
if(compar(v, base + j * size, ptr) == 0)
|
||||
exch(base, size, j, --q);
|
||||
}
|
||||
exch(base, size, i, r);
|
||||
j = i - 1;
|
||||
++i;
|
||||
for(k = l; k < p; k++, j--)
|
||||
exch(base, size, k, j);
|
||||
for(k = r - 1; k > q; k--, i++)
|
||||
exch(base, size, i, k);
|
||||
quicksort(base, size, l, j, compar, ptr);
|
||||
quicksort(base, size, i, r, compar, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
quicksort_r(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* ptr) {
|
||||
/* check for integer overflows */
|
||||
if(nmemb >= (((size_t)-1) >> 1) || size >= (((size_t)-1) >> 1))
|
||||
return;
|
||||
#if 0
|
||||
if (sizeof(size_t) < sizeof(unsigned long long)) {
|
||||
if ((unsigned long long)size * nmemb > (size_t)-1) return;
|
||||
} else {
|
||||
if (size*nmemb/nmemb != size) return;
|
||||
}
|
||||
#endif
|
||||
if(nmemb > 1)
|
||||
quicksort(base, size, 0, nmemb - 1, compar, ptr);
|
||||
}
|
||||
273
src/quickjs/quickjs-atom.h
Normal file
273
src/quickjs/quickjs-atom.h
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* QuickJS atom definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
/* Note: first atoms are considered as keywords in the parser */
|
||||
DEF(null, "null") /* must be first */
|
||||
DEF(false, "false")
|
||||
DEF(true, "true")
|
||||
DEF(if, "if")
|
||||
DEF(else, "else")
|
||||
DEF(return, "return")
|
||||
DEF(var, "var")
|
||||
DEF(this, "this")
|
||||
DEF(delete, "delete")
|
||||
DEF(void, "void")
|
||||
DEF(typeof, "typeof")
|
||||
DEF(new, "new")
|
||||
DEF(in, "in")
|
||||
DEF(instanceof, "instanceof")
|
||||
DEF(do, "do")
|
||||
DEF(while, "while")
|
||||
DEF(for, "for")
|
||||
DEF(break, "break")
|
||||
DEF(continue, "continue")
|
||||
DEF(switch, "switch")
|
||||
DEF(case, "case")
|
||||
DEF(default, "default")
|
||||
DEF(throw, "throw")
|
||||
DEF(try, "try")
|
||||
DEF(catch, "catch")
|
||||
DEF(finally, "finally")
|
||||
DEF(function, "function")
|
||||
DEF(debugger, "debugger")
|
||||
DEF(with, "with")
|
||||
/* FutureReservedWord */
|
||||
DEF(class, "class")
|
||||
DEF(const, "const")
|
||||
DEF(enum, "enum")
|
||||
DEF(export, "export")
|
||||
DEF(extends, "extends")
|
||||
DEF(import, "import")
|
||||
DEF(super, "super")
|
||||
/* FutureReservedWords when parsing strict mode code */
|
||||
DEF(implements, "implements")
|
||||
DEF(interface, "interface")
|
||||
DEF(let, "let")
|
||||
DEF(package, "package")
|
||||
DEF(private, "private")
|
||||
DEF(protected, "protected")
|
||||
DEF(public, "public")
|
||||
DEF(static, "static")
|
||||
DEF(yield, "yield")
|
||||
DEF(await, "await")
|
||||
|
||||
/* empty string */
|
||||
DEF(empty_string, "")
|
||||
/* identifiers */
|
||||
DEF(length, "length")
|
||||
DEF(fileName, "fileName")
|
||||
DEF(lineNumber, "lineNumber")
|
||||
DEF(message, "message")
|
||||
DEF(cause, "cause")
|
||||
DEF(errors, "errors")
|
||||
DEF(stack, "stack")
|
||||
DEF(name, "name")
|
||||
DEF(toString, "toString")
|
||||
DEF(toLocaleString, "toLocaleString")
|
||||
DEF(valueOf, "valueOf")
|
||||
DEF(eval, "eval")
|
||||
DEF(prototype, "prototype")
|
||||
DEF(constructor, "constructor")
|
||||
DEF(configurable, "configurable")
|
||||
DEF(writable, "writable")
|
||||
DEF(enumerable, "enumerable")
|
||||
DEF(value, "value")
|
||||
DEF(get, "get")
|
||||
DEF(set, "set")
|
||||
DEF(of, "of")
|
||||
DEF(__proto__, "__proto__")
|
||||
DEF(undefined, "undefined")
|
||||
DEF(number, "number")
|
||||
DEF(boolean, "boolean")
|
||||
DEF(string, "string")
|
||||
DEF(object, "object")
|
||||
DEF(symbol, "symbol")
|
||||
DEF(integer, "integer")
|
||||
DEF(unknown, "unknown")
|
||||
DEF(arguments, "arguments")
|
||||
DEF(callee, "callee")
|
||||
DEF(caller, "caller")
|
||||
DEF(_eval_, "<eval>")
|
||||
DEF(_ret_, "<ret>")
|
||||
DEF(_var_, "<var>")
|
||||
DEF(_arg_var_, "<arg_var>")
|
||||
DEF(_with_, "<with>")
|
||||
DEF(lastIndex, "lastIndex")
|
||||
DEF(target, "target")
|
||||
DEF(index, "index")
|
||||
DEF(input, "input")
|
||||
DEF(defineProperties, "defineProperties")
|
||||
DEF(apply, "apply")
|
||||
DEF(join, "join")
|
||||
DEF(concat, "concat")
|
||||
DEF(split, "split")
|
||||
DEF(construct, "construct")
|
||||
DEF(getPrototypeOf, "getPrototypeOf")
|
||||
DEF(setPrototypeOf, "setPrototypeOf")
|
||||
DEF(isExtensible, "isExtensible")
|
||||
DEF(preventExtensions, "preventExtensions")
|
||||
DEF(has, "has")
|
||||
DEF(deleteProperty, "deleteProperty")
|
||||
DEF(defineProperty, "defineProperty")
|
||||
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
|
||||
DEF(ownKeys, "ownKeys")
|
||||
DEF(add, "add")
|
||||
DEF(done, "done")
|
||||
DEF(next, "next")
|
||||
DEF(values, "values")
|
||||
DEF(source, "source")
|
||||
DEF(flags, "flags")
|
||||
DEF(global, "global")
|
||||
DEF(unicode, "unicode")
|
||||
DEF(raw, "raw")
|
||||
DEF(new_target, "new.target")
|
||||
DEF(this_active_func, "this.active_func")
|
||||
DEF(home_object, "<home_object>")
|
||||
DEF(computed_field, "<computed_field>")
|
||||
DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */
|
||||
DEF(class_fields_init, "<class_fields_init>")
|
||||
DEF(brand, "<brand>")
|
||||
DEF(hash_constructor, "#constructor")
|
||||
DEF(as, "as")
|
||||
DEF(from, "from")
|
||||
DEF(meta, "meta")
|
||||
DEF(_default_, "*default*")
|
||||
DEF(_star_, "*")
|
||||
DEF(Module, "Module")
|
||||
DEF(then, "then")
|
||||
DEF(resolve, "resolve")
|
||||
DEF(reject, "reject")
|
||||
DEF(promise, "promise")
|
||||
DEF(proxy, "proxy")
|
||||
DEF(revoke, "revoke")
|
||||
DEF(async, "async")
|
||||
DEF(exec, "exec")
|
||||
DEF(groups, "groups")
|
||||
DEF(indices, "indices")
|
||||
DEF(status, "status")
|
||||
DEF(reason, "reason")
|
||||
DEF(globalThis, "globalThis")
|
||||
DEF(bigint, "bigint")
|
||||
#ifdef CONFIG_BIGNUM
|
||||
DEF(bigfloat, "bigfloat")
|
||||
DEF(bigdecimal, "bigdecimal")
|
||||
DEF(roundingMode, "roundingMode")
|
||||
DEF(maximumSignificantDigits, "maximumSignificantDigits")
|
||||
DEF(maximumFractionDigits, "maximumFractionDigits")
|
||||
#endif
|
||||
/* the following 3 atoms are only used with CONFIG_ATOMICS */
|
||||
DEF(not_equal, "not-equal")
|
||||
DEF(timed_out, "timed-out")
|
||||
DEF(ok, "ok")
|
||||
/* */
|
||||
DEF(toJSON, "toJSON")
|
||||
/* class names */
|
||||
DEF(Object, "Object")
|
||||
DEF(Array, "Array")
|
||||
DEF(Error, "Error")
|
||||
DEF(Number, "Number")
|
||||
DEF(String, "String")
|
||||
DEF(Boolean, "Boolean")
|
||||
DEF(Symbol, "Symbol")
|
||||
DEF(Arguments, "Arguments")
|
||||
DEF(Math, "Math")
|
||||
DEF(JSON, "JSON")
|
||||
DEF(Date, "Date")
|
||||
DEF(Function, "Function")
|
||||
DEF(GeneratorFunction, "GeneratorFunction")
|
||||
DEF(ForInIterator, "ForInIterator")
|
||||
DEF(RegExp, "RegExp")
|
||||
DEF(ArrayBuffer, "ArrayBuffer")
|
||||
DEF(SharedArrayBuffer, "SharedArrayBuffer")
|
||||
/* must keep same order as class IDs for typed arrays */
|
||||
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||
DEF(Int8Array, "Int8Array")
|
||||
DEF(Uint8Array, "Uint8Array")
|
||||
DEF(Int16Array, "Int16Array")
|
||||
DEF(Uint16Array, "Uint16Array")
|
||||
DEF(Int32Array, "Int32Array")
|
||||
DEF(Uint32Array, "Uint32Array")
|
||||
DEF(BigInt64Array, "BigInt64Array")
|
||||
DEF(BigUint64Array, "BigUint64Array")
|
||||
DEF(Float32Array, "Float32Array")
|
||||
DEF(Float64Array, "Float64Array")
|
||||
DEF(DataView, "DataView")
|
||||
DEF(BigInt, "BigInt")
|
||||
#ifdef CONFIG_BIGNUM
|
||||
DEF(BigFloat, "BigFloat")
|
||||
DEF(BigFloatEnv, "BigFloatEnv")
|
||||
DEF(BigDecimal, "BigDecimal")
|
||||
DEF(OperatorSet, "OperatorSet")
|
||||
DEF(Operators, "Operators")
|
||||
#endif
|
||||
DEF(Map, "Map")
|
||||
DEF(Set, "Set") /* Map + 1 */
|
||||
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
||||
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
||||
DEF(Map_Iterator, "Map Iterator")
|
||||
DEF(Set_Iterator, "Set Iterator")
|
||||
DEF(Array_Iterator, "Array Iterator")
|
||||
DEF(String_Iterator, "String Iterator")
|
||||
DEF(RegExp_String_Iterator, "RegExp String Iterator")
|
||||
DEF(Generator, "Generator")
|
||||
DEF(Proxy, "Proxy")
|
||||
DEF(Promise, "Promise")
|
||||
DEF(PromiseResolveFunction, "PromiseResolveFunction")
|
||||
DEF(PromiseRejectFunction, "PromiseRejectFunction")
|
||||
DEF(AsyncFunction, "AsyncFunction")
|
||||
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
|
||||
DEF(AsyncFunctionReject, "AsyncFunctionReject")
|
||||
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
|
||||
DEF(AsyncGenerator, "AsyncGenerator")
|
||||
DEF(EvalError, "EvalError")
|
||||
DEF(RangeError, "RangeError")
|
||||
DEF(ReferenceError, "ReferenceError")
|
||||
DEF(SyntaxError, "SyntaxError")
|
||||
DEF(TypeError, "TypeError")
|
||||
DEF(URIError, "URIError")
|
||||
DEF(InternalError, "InternalError")
|
||||
/* private symbols */
|
||||
DEF(Private_brand, "<brand>")
|
||||
/* symbols */
|
||||
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
|
||||
DEF(Symbol_iterator, "Symbol.iterator")
|
||||
DEF(Symbol_match, "Symbol.match")
|
||||
DEF(Symbol_matchAll, "Symbol.matchAll")
|
||||
DEF(Symbol_replace, "Symbol.replace")
|
||||
DEF(Symbol_search, "Symbol.search")
|
||||
DEF(Symbol_split, "Symbol.split")
|
||||
DEF(Symbol_toStringTag, "Symbol.toStringTag")
|
||||
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
|
||||
DEF(Symbol_hasInstance, "Symbol.hasInstance")
|
||||
DEF(Symbol_species, "Symbol.species")
|
||||
DEF(Symbol_unscopables, "Symbol.unscopables")
|
||||
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
|
||||
#ifdef CONFIG_BIGNUM
|
||||
DEF(Symbol_operatorSet, "Symbol.operatorSet")
|
||||
#endif
|
||||
|
||||
#endif /* DEF */
|
||||
8
src/quickjs/quickjs-config.h
Normal file
8
src/quickjs/quickjs-config.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __QUICKJS_CONFIG_H
|
||||
#define __QUICKJS_CONFIG_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#endif // __QUICKJS_CONFIG_H
|
||||
645
src/quickjs/quickjs-internal.c
Normal file
645
src/quickjs/quickjs-internal.c
Normal file
@@ -0,0 +1,645 @@
|
||||
#include "utils.h"
|
||||
#include "char-utils.h"
|
||||
#include "vector.h"
|
||||
#include "quickjs-internal.h"
|
||||
|
||||
JSValue
|
||||
js_std_file(JSContext* ctx, FILE* f) {
|
||||
JSClassID class_id = js_class_find(ctx, "FILE");
|
||||
JSValue obj, proto = JS_GetClassProto(ctx, class_id);
|
||||
JSSTDFile* file;
|
||||
|
||||
file = js_malloc(ctx, sizeof(JSSTDFile));
|
||||
*file = (JSSTDFile){0, TRUE, FALSE};
|
||||
|
||||
file->f = f;
|
||||
|
||||
obj = JS_NewObjectProtoClass(ctx, proto, class_id);
|
||||
|
||||
JS_SetOpaque(obj, file);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct list_head*
|
||||
js_modules_list(JSContext* ctx) {
|
||||
return &ctx->loaded_modules;
|
||||
}
|
||||
|
||||
JSModuleDef**
|
||||
js_modules_vector(JSContext* ctx) {
|
||||
struct list_head* el;
|
||||
Vector vec = VECTOR(ctx);
|
||||
JSModuleDef* m;
|
||||
|
||||
list_for_each(el, js_modules_list(ctx)) {
|
||||
m = list_entry(el, JSModuleDef, link);
|
||||
|
||||
vector_push(&vec, m);
|
||||
}
|
||||
|
||||
m = NULL;
|
||||
vector_push(&vec, m);
|
||||
|
||||
return vector_begin(&vec);
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_modules_entries(JSContext* ctx, JSValueConst this_val, int magic) {
|
||||
struct list_head* el;
|
||||
JSValue ret = JS_NewArray(ctx);
|
||||
uint32_t i = 0;
|
||||
list_for_each(el, &ctx->loaded_modules) {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
// const char* name = module_namecstr(ctx, m);
|
||||
JSValue entry = JS_NewArray(ctx);
|
||||
JS_SetPropertyUint32(ctx, entry, 0, JS_AtomToValue(ctx, m->module_name));
|
||||
JS_SetPropertyUint32(ctx, entry, 1, magic ? module_entry(ctx, m) : module_value(ctx, m));
|
||||
|
||||
if(1 /*str[0] != '<'*/)
|
||||
JS_SetPropertyUint32(ctx, ret, i++, entry);
|
||||
else
|
||||
JS_FreeValue(ctx, entry);
|
||||
|
||||
// JS_FreeCString(ctx, name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_modules_object(JSContext* ctx, JSValueConst this_val, int magic) {
|
||||
struct list_head* it;
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
|
||||
list_for_each(it, &ctx->loaded_modules) {
|
||||
JSModuleDef* m = list_entry(it, JSModuleDef, link);
|
||||
const char* name = module_namecstr(ctx, m);
|
||||
JSValue entry = magic ? module_entry(ctx, m) : module_value(ctx, m);
|
||||
|
||||
if(1 /*str[0] != '<'*/)
|
||||
JS_SetPropertyStr(ctx, obj, basename(name), entry);
|
||||
else
|
||||
JS_FreeValue(ctx, entry);
|
||||
|
||||
JS_FreeCString(ctx, name);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
js_module_find_fwd(JSContext* ctx, const char* name, JSModuleDef* start) {
|
||||
struct list_head* el;
|
||||
|
||||
for(el = start ? &start->link : ctx->loaded_modules.next; el != &ctx->loaded_modules; el = el->next)
|
||||
/*list_for_each(el, &ctx->loaded_modules)*/ {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
const char* str = module_namecstr(ctx, m);
|
||||
BOOL match = !strcmp(str, name);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if(match)
|
||||
return m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
js_module_index(JSContext* ctx, JSModuleDef* m) {
|
||||
struct list_head* el;
|
||||
int i = 0;
|
||||
|
||||
list_for_each(el, &ctx->loaded_modules) {
|
||||
|
||||
if(m == list_entry(el, JSModuleDef, link))
|
||||
return i;
|
||||
++i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
js_module_find_rev(JSContext* ctx, const char* name, JSModuleDef* start) {
|
||||
struct list_head* el;
|
||||
|
||||
for(el = start ? &start->link : ctx->loaded_modules.prev; el != &ctx->loaded_modules; el = el->prev) /*list_for_each_prev(el, &ctx->loaded_modules)*/ {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
const char* str = module_namecstr(ctx, m);
|
||||
BOOL match = !strcmp(str, name);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if(match)
|
||||
return m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
js_module_indexof(JSContext* ctx, JSModuleDef* def) {
|
||||
int i = 0;
|
||||
struct list_head* el;
|
||||
|
||||
list_for_each(el, &ctx->loaded_modules) {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
|
||||
if(m == def)
|
||||
return i;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
js_module_at(JSContext* ctx, int index) {
|
||||
int i = 0;
|
||||
struct list_head* el;
|
||||
|
||||
if(index >= 0) {
|
||||
list_for_each(el, &ctx->loaded_modules) {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
|
||||
if(index == i)
|
||||
return m;
|
||||
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
index = -(index + 1);
|
||||
|
||||
list_for_each_prev(el, &ctx->loaded_modules) {
|
||||
JSModuleDef* m = list_entry(el, JSModuleDef, link);
|
||||
|
||||
if(index == i)
|
||||
return m;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
module_make_object(JSContext* ctx, JSModuleDef* m, JSValueConst obj) {
|
||||
JSValue tmp;
|
||||
char buf[FMT_XLONG + 2];
|
||||
strcpy(buf, "0x");
|
||||
|
||||
if(!js_has_propertystr(ctx, obj, "name"))
|
||||
JS_SetPropertyStr(ctx, obj, "name", module_name(ctx, m));
|
||||
|
||||
JS_DefinePropertyValueStr(ctx, obj, "resolved", JS_NewBool(ctx, m->resolved), 0);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "funcCreated", JS_NewBool(ctx, m->func_created), 0);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "instantiated", JS_NewBool(ctx, m->instantiated), 0);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "evaluated", JS_NewBool(ctx, m->evaluated), 0);
|
||||
|
||||
if(!JS_IsUndefined((tmp = module_ns(ctx, m))))
|
||||
JS_DefinePropertyValueStr(ctx, obj, "ns", tmp, 0);
|
||||
|
||||
if(!JS_IsUndefined((tmp = module_exports(ctx, m))))
|
||||
JS_DefinePropertyValueStr(ctx, obj, "exports", tmp, 0);
|
||||
|
||||
if(!JS_IsUndefined((tmp = module_imports(ctx, m))))
|
||||
JS_DefinePropertyValueStr(ctx, obj, "imports", tmp, 0);
|
||||
|
||||
if(!JS_IsUndefined((tmp = module_reqmodules(ctx, m))))
|
||||
JS_SetPropertyStr(ctx, obj, "reqModules", tmp);
|
||||
|
||||
if(m->init_func) {
|
||||
JS_SetPropertyStr(ctx, obj, "native", JS_NewBool(ctx, m->init_func != NULL));
|
||||
}
|
||||
|
||||
if(!JS_IsUndefined((tmp = module_func(ctx, m)))) {
|
||||
if(m->init_func)
|
||||
JS_DefinePropertyValueStr(ctx, obj, "initFunc", tmp, 0);
|
||||
else
|
||||
JS_SetPropertyStr(ctx, obj, "func", tmp);
|
||||
}
|
||||
|
||||
if(!js_is_null_or_undefined((tmp = JS_DupValue(ctx, m->meta_obj))))
|
||||
JS_SetPropertyStr(ctx, obj, "metaObj", tmp);
|
||||
|
||||
if(!js_is_null_or_undefined((tmp = JS_DupValue(ctx, m->eval_exception))))
|
||||
JS_SetPropertyStr(ctx, obj, "evalException", tmp);
|
||||
|
||||
{
|
||||
JSAtom atom = js_symbol_static_atom(ctx, "toStringTag");
|
||||
JS_DefinePropertyValue(ctx, obj, atom, JS_NewString(ctx, "Module"), 0);
|
||||
JS_FreeAtom(ctx, atom);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
buf[2 + fmt_xlonglong0(&buf[2], (long long)(uintptr_t)m, __SIZEOF_POINTER__ * 2)] = 0;
|
||||
|
||||
JS_DefinePropertyValueStr(ctx, obj, "address", JS_NewString(ctx, buf), 0);
|
||||
}
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_object(JSContext* ctx, JSModuleDef* m) {
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
module_make_object(ctx, m, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
int
|
||||
module_exports_get(JSContext* ctx, JSModuleDef* m, BOOL rename_default, JSValueConst exports) {
|
||||
JSAtom def = JS_NewAtom(ctx, "default");
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->export_entries_count; i++) {
|
||||
JSExportEntry* entry = &m->export_entries[i];
|
||||
JSVarRef* ref = entry->u.local.var_ref;
|
||||
JSValue val = JS_UNDEFINED;
|
||||
JSAtom name = entry->export_name;
|
||||
|
||||
if(ref) {
|
||||
val = JS_DupValue(ctx, ref->pvalue ? *ref->pvalue : ref->value);
|
||||
|
||||
if(rename_default && name == def)
|
||||
name = m->module_name;
|
||||
}
|
||||
|
||||
JS_SetProperty(ctx, exports, name, val);
|
||||
}
|
||||
|
||||
JS_FreeAtom(ctx, def);
|
||||
return i;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_imports(JSContext* ctx, JSModuleDef* m) {
|
||||
JSValue obj = m->import_entries_count > 0 ? JS_NewArray(ctx) : JS_UNDEFINED;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->import_entries_count; i++) {
|
||||
JSImportEntry* entry = &m->import_entries[i];
|
||||
JSAtom name = entry->import_name;
|
||||
/*JSReqModuleEntry* req_module = &m->req_module_entries[entry->req_module_idx];
|
||||
JSAtom module_name = req_module->module_name;*/
|
||||
|
||||
JSValue import_value = JS_NewArray(ctx);
|
||||
|
||||
JS_SetPropertyUint32(ctx, import_value, 0, JS_AtomToValue(ctx, name));
|
||||
JS_SetPropertyUint32(ctx, import_value, 1, JS_NewUint32(ctx, entry->req_module_idx));
|
||||
JS_SetPropertyUint32(ctx, obj, i, import_value);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_reqmodules(JSContext* ctx, JSModuleDef* m) {
|
||||
JSValue obj = m->req_module_entries_count > 0 ? JS_NewArray(ctx) : JS_UNDEFINED;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->req_module_entries_count; i++) {
|
||||
JSReqModuleEntry* req_module = &m->req_module_entries[i];
|
||||
JSAtom module_name = req_module->module_name;
|
||||
JSModuleDef* module = req_module->module;
|
||||
|
||||
JSValue req_module_value = JS_NewArray(ctx);
|
||||
|
||||
JS_SetPropertyUint32(ctx, req_module_value, 0, JS_AtomToValue(ctx, module_name));
|
||||
JS_SetPropertyUint32(ctx, req_module_value, 1, JS_NewInt32(ctx, js_module_index(ctx, module)));
|
||||
JS_SetPropertyUint32(ctx, obj, i, req_module_value);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_default_export(JSContext* ctx, JSModuleDef* m) {
|
||||
JSAtom def = JS_NewAtom(ctx, "default");
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->export_entries_count; i++) {
|
||||
JSExportEntry* entry = &m->export_entries[i];
|
||||
JSVarRef* ref = entry->u.local.var_ref;
|
||||
JSAtom name = entry->export_name;
|
||||
|
||||
if(ref) {
|
||||
|
||||
if(name == def) {
|
||||
ret = JS_DupValue(ctx, ref->pvalue ? *ref->pvalue : ref->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_FreeAtom(ctx, def);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_ns(JSContext* ctx, JSModuleDef* m) {
|
||||
return JS_DupValue(ctx, m->module_ns);
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_exception(JSContext* ctx, JSModuleDef* m) {
|
||||
return m->eval_has_exception ? JS_DupValue(ctx, m->eval_exception) : JS_NULL;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_meta_obj(JSContext* ctx, JSModuleDef* m) {
|
||||
return JS_DupValue(ctx, m->meta_obj);
|
||||
}
|
||||
|
||||
static JSValue
|
||||
call_module_func(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* data) {
|
||||
union {
|
||||
JSModuleInitFunc* init_func;
|
||||
int32_t i[2];
|
||||
} u;
|
||||
|
||||
u.i[0] = JS_VALUE_GET_INT(data[0]);
|
||||
u.i[1] = JS_VALUE_GET_INT(data[1]);
|
||||
|
||||
if(argc >= 1) {
|
||||
JSModuleDef* m;
|
||||
|
||||
if((m = js_module_def(ctx, argv[0])))
|
||||
return JS_NewInt32(ctx, u.init_func(ctx, m));
|
||||
}
|
||||
|
||||
return JS_ThrowTypeError(ctx, "argument 1 module expected");
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_func(JSContext* ctx, JSModuleDef* m) {
|
||||
JSValue func = JS_UNDEFINED;
|
||||
|
||||
if(JS_IsFunction(ctx, m->func_obj)) {
|
||||
func = JS_DupValue(ctx, m->func_obj);
|
||||
} else if(m->init_func) {
|
||||
union {
|
||||
JSModuleInitFunc* init_func;
|
||||
int32_t i[2];
|
||||
} u = {m->init_func};
|
||||
|
||||
JSValueConst data[2] = {
|
||||
JS_MKVAL(JS_TAG_INT, u.i[0]),
|
||||
JS_MKVAL(JS_TAG_INT, u.i[1]),
|
||||
};
|
||||
|
||||
func = JS_NewCFunctionData(ctx, call_module_func, 1, 0, 2, data);
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_name(JSContext* ctx, JSModuleDef* m) {
|
||||
|
||||
if(m->module_name < (size_t)JS_GetRuntime(ctx)->atom_count)
|
||||
return JS_AtomToValue(ctx, m->module_name);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
const char*
|
||||
module_namecstr(JSContext* ctx, JSModuleDef* m) {
|
||||
return JS_AtomToCString(ctx, m->module_name);
|
||||
}
|
||||
|
||||
JSValue
|
||||
module_exports_find(JSContext* ctx, JSModuleDef* m, JSAtom atom) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->export_entries_count; i++) {
|
||||
JSExportEntry* entry = &m->export_entries[i];
|
||||
|
||||
if(entry->export_name == atom) {
|
||||
JSVarRef* ref = entry->u.local.var_ref;
|
||||
JSValue export = ref ? JS_DupValue(ctx, ref->pvalue ? *ref->pvalue : ref->value) : JS_UNDEFINED;
|
||||
return export;
|
||||
}
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
module_next(JSContext* ctx, JSModuleDef* m) {
|
||||
return m->link.next != js_modules_list(ctx) ? list_entry(m->link.next, JSModuleDef, link) : 0;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
module_prev(JSContext* ctx, JSModuleDef* m) {
|
||||
return m->link.prev != js_modules_list(ctx) ? list_entry(m->link.prev, JSModuleDef, link) : 0;
|
||||
}
|
||||
|
||||
JSModuleDef*
|
||||
module_last(JSContext* ctx) {
|
||||
struct list_head* list = js_modules_list(ctx);
|
||||
|
||||
return list_empty(list) ? 0 : list_entry(list->prev, JSModuleDef, link);
|
||||
}
|
||||
|
||||
void
|
||||
module_rename(JSContext* ctx, JSModuleDef* m, JSAtom name) {
|
||||
JS_FreeAtom(ctx, m->module_name);
|
||||
m->module_name = name;
|
||||
}
|
||||
|
||||
static void
|
||||
js_arraybuffer_freestring(JSRuntime* rt, void* opaque, void* ptr) {
|
||||
JSString* jstr = opaque;
|
||||
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, jstr));
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_arraybuffer_fromstring(JSContext* ctx, JSValueConst str) {
|
||||
JSString* jstr;
|
||||
|
||||
if(!JS_IsString(str))
|
||||
return JS_ThrowTypeError(ctx, "Not a string");
|
||||
|
||||
JS_DupValue(ctx, str);
|
||||
jstr = JS_VALUE_GET_PTR(str);
|
||||
|
||||
return JS_NewArrayBuffer(ctx, jstr->u.str8, jstr->len, js_arraybuffer_freestring, jstr, FALSE);
|
||||
}
|
||||
|
||||
void*
|
||||
js_sab_alloc(void* opaque, size_t size) {
|
||||
JSSABHeader* sab;
|
||||
|
||||
if(!(sab = malloc(sizeof(JSSABHeader) + size)))
|
||||
return 0;
|
||||
|
||||
sab->ref_count = 1;
|
||||
return sab->buf;
|
||||
}
|
||||
|
||||
void
|
||||
js_sab_free(void* opaque, void* ptr) {
|
||||
JSSABHeader* sab;
|
||||
int ref_count;
|
||||
sab = (JSSABHeader*)((uint8_t*)ptr - sizeof(JSSABHeader));
|
||||
ref_count = atomic_add_int(&sab->ref_count, -1);
|
||||
assert(ref_count >= 0);
|
||||
|
||||
if(ref_count == 0)
|
||||
free(sab);
|
||||
}
|
||||
|
||||
void
|
||||
js_sab_dup(void* opaque, void* ptr) {
|
||||
JSSABHeader* sab;
|
||||
sab = (JSSABHeader*)((uint8_t*)ptr - sizeof(JSSABHeader));
|
||||
atomic_add_int(&sab->ref_count, 1);
|
||||
}
|
||||
|
||||
JSValueConst
|
||||
js_cstring_value(const char* ptr) {
|
||||
return JS_MKPTR(JS_TAG_STRING, (JSString*)(void*)(ptr - offsetof(JSString, u)));
|
||||
}
|
||||
|
||||
char*
|
||||
js_cstring_dup(JSContext* ctx, const char* str) {
|
||||
/* purposely removing constness */
|
||||
JSString* p = (JSString*)(void*)(str - offsetof(JSString, u));
|
||||
JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
|
||||
return (char*)str;
|
||||
}
|
||||
|
||||
size_t
|
||||
js_cstring_len(JSValueConst v) {
|
||||
JSString* p;
|
||||
|
||||
if(JS_IsString(v)) {
|
||||
p = JS_VALUE_GET_PTR(v);
|
||||
return p->len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
js_cstring_ptr(JSValueConst v) {
|
||||
JSString* p;
|
||||
|
||||
if(JS_IsString(v)) {
|
||||
p = JS_VALUE_GET_PTR(v);
|
||||
return (char*)p->u.str8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*
|
||||
js_class_name(JSContext* ctx, JSClassID id) {
|
||||
JSAtom atom = JS_GetRuntime(ctx)->class_array[id].class_name;
|
||||
return JS_AtomToCString(ctx, atom);
|
||||
}
|
||||
|
||||
JSAtom
|
||||
js_class_atom(JSContext* ctx, JSClassID id) {
|
||||
JSAtom atom = 0;
|
||||
|
||||
if(id > 0 && id < (JSClassID)JS_GetRuntime(ctx)->class_count)
|
||||
atom = JS_GetRuntime(ctx)->class_array[id].class_name;
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSClassID
|
||||
js_class_find(JSContext* ctx, const char* name) {
|
||||
JSAtom atom = JS_NewAtom(ctx, name);
|
||||
JSRuntime* rt = JS_GetRuntime(ctx);
|
||||
int i, n = rt->class_count;
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
|
||||
if(rt->class_array[i].class_name == atom)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSClassID
|
||||
js_class_id(JSContext* ctx, int id) {
|
||||
return JS_GetRuntime(ctx)->class_array[id].class_id;
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_opcode_array(JSContext* ctx, const JSOpCode* opcode) {
|
||||
JSValue ret = JS_NewArray(ctx);
|
||||
JS_SetPropertyUint32(ctx, ret, 0, JS_NewUint32(ctx, opcode->size));
|
||||
JS_SetPropertyUint32(ctx, ret, 1, JS_NewUint32(ctx, opcode->n_pop));
|
||||
JS_SetPropertyUint32(ctx, ret, 2, JS_NewUint32(ctx, opcode->n_push));
|
||||
JS_SetPropertyUint32(ctx, ret, 3, JS_NewUint32(ctx, opcode->fmt));
|
||||
JS_SetPropertyUint32(ctx, ret, 4, JS_NewString(ctx, opcode->name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_opcode_object(JSContext* ctx, const struct JSOpCode* opcode) {
|
||||
JSValue ret = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, ret, "size", JS_NewUint32(ctx, opcode->size));
|
||||
JS_SetPropertyStr(ctx, ret, "n_pop", JS_NewUint32(ctx, opcode->n_pop));
|
||||
JS_SetPropertyStr(ctx, ret, "n_push", JS_NewUint32(ctx, opcode->n_push));
|
||||
JS_SetPropertyStr(ctx, ret, "fmt", JS_NewUint32(ctx, opcode->fmt));
|
||||
JS_SetPropertyStr(ctx, ret, "name", JS_NewString(ctx, opcode->name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_get_bytecode(JSContext* ctx, JSValueConst value) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
|
||||
if(JS_IsFunction(ctx, value)) {
|
||||
JSObject* obj = JS_VALUE_GET_OBJ(value);
|
||||
JSFunctionBytecode* fnbc;
|
||||
|
||||
if((fnbc = obj->u.func.function_bytecode)) {
|
||||
ret = JS_NewArrayBufferCopy(ctx, fnbc->byte_code_buf, fnbc->byte_code_len);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
js_opcode_list(JSContext* ctx, BOOL as_object) {
|
||||
JSValue ret = JS_NewArray(ctx);
|
||||
size_t i, j, len = countof(js_opcodes);
|
||||
|
||||
for(i = 0, j = 0; i < len; i++) {
|
||||
|
||||
if(i >= OP_TEMP_START && i < OP_TEMP_END)
|
||||
continue;
|
||||
|
||||
JS_SetPropertyUint32(ctx, ret, j++, (as_object ? js_opcode_object : js_opcode_array)(ctx, &js_opcodes[i]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JS_DEBUGGER_BUILD_BACKTRACE
|
||||
JSValue js_debugger_build_backtrace(JSContext* ctx, const uint8_t* cur_pc);
|
||||
|
||||
JSValue
|
||||
js_stack_get(JSContext* ctx) {
|
||||
return js_debugger_build_backtrace(ctx, ctx->rt->current_stack_frame->cur_pc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SHORT_OPCODES 1
|
||||
|
||||
const JSOpCode js_opcodes[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
|
||||
#define FMT(f)
|
||||
#define DEF(id, size, n_pop, n_push, f) {size, n_pop, n_push, OP_FMT_##f, #id},
|
||||
#include <quickjs-opcode.h>
|
||||
#undef DEF
|
||||
#undef FMT
|
||||
};
|
||||
1213
src/quickjs/quickjs-internal.h
Normal file
1213
src/quickjs/quickjs-internal.h
Normal file
File diff suppressed because it is too large
Load Diff
4051
src/quickjs/quickjs-libc.c
Normal file
4051
src/quickjs/quickjs-libc.c
Normal file
File diff suppressed because it is too large
Load Diff
62
src/quickjs/quickjs-libc.h
Normal file
62
src/quickjs/quickjs-libc.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* QuickJS C library
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef QUICKJS_LIBC_H
|
||||
#define QUICKJS_LIBC_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "quickjs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
|
||||
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
|
||||
void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
|
||||
void js_std_loop(JSContext *ctx);
|
||||
JSValue js_std_await(JSContext *ctx, JSValue obj);
|
||||
void js_std_init_handlers(JSRuntime *rt);
|
||||
void js_std_free_handlers(JSRuntime *rt);
|
||||
void js_std_dump_error(JSContext *ctx);
|
||||
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
|
||||
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
|
||||
JS_BOOL use_realpath, JS_BOOL is_main);
|
||||
JSModuleDef *js_module_loader(JSContext *ctx,
|
||||
const char *module_name, void *opaque);
|
||||
|
||||
int js_std_eval_binary_bare(JSContext *ctx, const uint8_t *buf, size_t buf_len);
|
||||
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||
int flags);
|
||||
void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
|
||||
JSValueConst reason,
|
||||
JS_BOOL is_handled, void *opaque);
|
||||
void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* QUICKJS_LIBC_H */
|
||||
372
src/quickjs/quickjs-opcode.h
Normal file
372
src/quickjs/quickjs-opcode.h
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* QuickJS opcode definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef FMT
|
||||
FMT(none)
|
||||
FMT(none_int)
|
||||
FMT(none_loc)
|
||||
FMT(none_arg)
|
||||
FMT(none_var_ref)
|
||||
FMT(u8)
|
||||
FMT(i8)
|
||||
FMT(loc8)
|
||||
FMT(const8)
|
||||
FMT(label8)
|
||||
FMT(u16)
|
||||
FMT(i16)
|
||||
FMT(label16)
|
||||
FMT(npop)
|
||||
FMT(npopx)
|
||||
FMT(npop_u16)
|
||||
FMT(loc)
|
||||
FMT(arg)
|
||||
FMT(var_ref)
|
||||
FMT(u32)
|
||||
FMT(i32)
|
||||
FMT(const)
|
||||
FMT(label)
|
||||
FMT(atom)
|
||||
FMT(atom_u8)
|
||||
FMT(atom_u16)
|
||||
FMT(atom_label_u8)
|
||||
FMT(atom_label_u16)
|
||||
FMT(label_u16)
|
||||
#undef FMT
|
||||
#endif /* FMT */
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
#ifndef def
|
||||
#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f)
|
||||
#endif
|
||||
|
||||
DEF(invalid, 1, 0, 0, none) /* never emitted */
|
||||
|
||||
/* push values */
|
||||
DEF( push_i32, 5, 0, 1, i32)
|
||||
DEF( push_const, 5, 0, 1, const)
|
||||
DEF( fclosure, 5, 0, 1, const) /* must follow push_const */
|
||||
DEF(push_atom_value, 5, 0, 1, atom)
|
||||
DEF( private_symbol, 5, 0, 1, atom)
|
||||
DEF( undefined, 1, 0, 1, none)
|
||||
DEF( null, 1, 0, 1, none)
|
||||
DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */
|
||||
DEF( push_false, 1, 0, 1, none)
|
||||
DEF( push_true, 1, 0, 1, none)
|
||||
DEF( object, 1, 0, 1, none)
|
||||
DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */
|
||||
DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */
|
||||
|
||||
DEF( drop, 1, 1, 0, none) /* a -> */
|
||||
DEF( nip, 1, 2, 1, none) /* a b -> b */
|
||||
DEF( nip1, 1, 3, 2, none) /* a b c -> b c */
|
||||
DEF( dup, 1, 1, 2, none) /* a -> a a */
|
||||
DEF( dup1, 1, 2, 3, none) /* a b -> a a b */
|
||||
DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */
|
||||
DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */
|
||||
DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */
|
||||
DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */
|
||||
DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */
|
||||
DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */
|
||||
DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */
|
||||
DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */
|
||||
DEF( swap, 1, 2, 2, none) /* a b -> b a */
|
||||
DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */
|
||||
DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */
|
||||
DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */
|
||||
DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */
|
||||
DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */
|
||||
|
||||
DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */
|
||||
DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF( apply, 3, 3, 1, u16)
|
||||
DEF( return, 1, 1, 0, none)
|
||||
DEF( return_undef, 1, 0, 0, none)
|
||||
DEF(check_ctor_return, 1, 1, 2, none)
|
||||
DEF( check_ctor, 1, 0, 0, none)
|
||||
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
|
||||
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
|
||||
DEF( return_async, 1, 1, 0, none)
|
||||
DEF( throw, 1, 1, 0, none)
|
||||
DEF( throw_error, 6, 0, 0, atom_u8)
|
||||
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
|
||||
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||
bytecode string */
|
||||
DEF( get_super, 1, 1, 1, none)
|
||||
DEF( import, 1, 1, 1, none) /* dynamic module import */
|
||||
|
||||
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
|
||||
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
|
||||
DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */
|
||||
DEF( put_var, 5, 1, 0, atom) /* must come after get_var */
|
||||
DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */
|
||||
DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */
|
||||
|
||||
DEF( get_ref_value, 1, 2, 3, none)
|
||||
DEF( put_ref_value, 1, 3, 0, none)
|
||||
|
||||
DEF( define_var, 6, 0, 0, atom_u8)
|
||||
DEF(check_define_var, 6, 0, 0, atom_u8)
|
||||
DEF( define_func, 6, 1, 0, atom_u8)
|
||||
DEF( get_field, 5, 1, 1, atom)
|
||||
DEF( get_field2, 5, 1, 2, atom)
|
||||
DEF( put_field, 5, 2, 0, atom)
|
||||
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
|
||||
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
|
||||
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
|
||||
DEF( get_array_el, 1, 2, 1, none)
|
||||
DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */
|
||||
DEF( put_array_el, 1, 3, 0, none)
|
||||
DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */
|
||||
DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */
|
||||
DEF( define_field, 5, 2, 1, atom)
|
||||
DEF( set_name, 5, 1, 1, atom)
|
||||
DEF(set_name_computed, 1, 2, 2, none)
|
||||
DEF( set_proto, 1, 2, 1, none)
|
||||
DEF(set_home_object, 1, 2, 2, none)
|
||||
DEF(define_array_el, 1, 3, 2, none)
|
||||
DEF( append, 1, 3, 2, none) /* append enumerated object, update length */
|
||||
DEF(copy_data_properties, 2, 3, 3, u8)
|
||||
DEF( define_method, 6, 2, 1, atom_u8)
|
||||
DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */
|
||||
DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */
|
||||
DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */
|
||||
|
||||
DEF( get_loc, 3, 0, 1, loc)
|
||||
DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */
|
||||
DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
||||
DEF( get_arg, 3, 0, 1, arg)
|
||||
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||
DEF( get_loc_check, 3, 0, 1, loc)
|
||||
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||
DEF(get_loc_checkthis, 3, 0, 1, loc)
|
||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||
DEF( close_loc, 3, 0, 0, loc)
|
||||
DEF( if_false, 5, 1, 0, label)
|
||||
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
|
||||
DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||
DEF( catch, 5, 0, 1, label)
|
||||
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
||||
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
||||
DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
|
||||
|
||||
DEF( to_object, 1, 1, 1, none)
|
||||
//DEF( to_string, 1, 1, 1, none)
|
||||
DEF( to_propkey, 1, 1, 1, none)
|
||||
DEF( to_propkey2, 1, 2, 2, none)
|
||||
|
||||
DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
|
||||
|
||||
DEF( make_loc_ref, 7, 0, 2, atom_u16)
|
||||
DEF( make_arg_ref, 7, 0, 2, atom_u16)
|
||||
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
||||
DEF( make_var_ref, 5, 0, 2, atom)
|
||||
|
||||
DEF( for_in_start, 1, 1, 1, none)
|
||||
DEF( for_of_start, 1, 1, 3, none)
|
||||
DEF(for_await_of_start, 1, 1, 3, none)
|
||||
DEF( for_in_next, 1, 1, 3, none)
|
||||
DEF( for_of_next, 2, 3, 5, u8)
|
||||
DEF(iterator_check_object, 1, 1, 1, none)
|
||||
DEF(iterator_get_value_done, 1, 1, 2, none)
|
||||
DEF( iterator_close, 1, 3, 0, none)
|
||||
DEF( iterator_next, 1, 4, 4, none)
|
||||
DEF( iterator_call, 2, 4, 5, u8)
|
||||
DEF( initial_yield, 1, 0, 0, none)
|
||||
DEF( yield, 1, 1, 2, none)
|
||||
DEF( yield_star, 1, 1, 2, none)
|
||||
DEF(async_yield_star, 1, 1, 2, none)
|
||||
DEF( await, 1, 1, 1, none)
|
||||
|
||||
/* arithmetic/logic operations */
|
||||
DEF( neg, 1, 1, 1, none)
|
||||
DEF( plus, 1, 1, 1, none)
|
||||
DEF( dec, 1, 1, 1, none)
|
||||
DEF( inc, 1, 1, 1, none)
|
||||
DEF( post_dec, 1, 1, 2, none)
|
||||
DEF( post_inc, 1, 1, 2, none)
|
||||
DEF( dec_loc, 2, 0, 0, loc8)
|
||||
DEF( inc_loc, 2, 0, 0, loc8)
|
||||
DEF( add_loc, 2, 1, 0, loc8)
|
||||
DEF( not, 1, 1, 1, none)
|
||||
DEF( lnot, 1, 1, 1, none)
|
||||
DEF( typeof, 1, 1, 1, none)
|
||||
DEF( delete, 1, 2, 1, none)
|
||||
DEF( delete_var, 5, 0, 1, atom)
|
||||
|
||||
DEF( mul, 1, 2, 1, none)
|
||||
DEF( div, 1, 2, 1, none)
|
||||
DEF( mod, 1, 2, 1, none)
|
||||
DEF( add, 1, 2, 1, none)
|
||||
DEF( sub, 1, 2, 1, none)
|
||||
DEF( pow, 1, 2, 1, none)
|
||||
DEF( shl, 1, 2, 1, none)
|
||||
DEF( sar, 1, 2, 1, none)
|
||||
DEF( shr, 1, 2, 1, none)
|
||||
DEF( lt, 1, 2, 1, none)
|
||||
DEF( lte, 1, 2, 1, none)
|
||||
DEF( gt, 1, 2, 1, none)
|
||||
DEF( gte, 1, 2, 1, none)
|
||||
DEF( instanceof, 1, 2, 1, none)
|
||||
DEF( in, 1, 2, 1, none)
|
||||
DEF( eq, 1, 2, 1, none)
|
||||
DEF( neq, 1, 2, 1, none)
|
||||
DEF( strict_eq, 1, 2, 1, none)
|
||||
DEF( strict_neq, 1, 2, 1, none)
|
||||
DEF( and, 1, 2, 1, none)
|
||||
DEF( xor, 1, 2, 1, none)
|
||||
DEF( or, 1, 2, 1, none)
|
||||
DEF(is_undefined_or_null, 1, 1, 1, none)
|
||||
DEF( private_in, 1, 2, 1, none)
|
||||
#ifdef CONFIG_BIGNUM
|
||||
DEF( mul_pow10, 1, 2, 1, none)
|
||||
DEF( math_mod, 1, 2, 1, none)
|
||||
#endif
|
||||
/* must be the last non short and non temporary opcode */
|
||||
DEF( nop, 1, 0, 0, none)
|
||||
|
||||
/* temporary opcodes: never emitted in the final bytecode */
|
||||
|
||||
def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||
|
||||
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
/* the following opcodes must be in the same order as the 'with_x' and
|
||||
get_var_undef, get_var and put_var opcodes */
|
||||
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
|
||||
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
|
||||
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
|
||||
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
|
||||
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||
|
||||
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
#if SHORT_OPCODES
|
||||
DEF( push_minus1, 1, 0, 1, none_int)
|
||||
DEF( push_0, 1, 0, 1, none_int)
|
||||
DEF( push_1, 1, 0, 1, none_int)
|
||||
DEF( push_2, 1, 0, 1, none_int)
|
||||
DEF( push_3, 1, 0, 1, none_int)
|
||||
DEF( push_4, 1, 0, 1, none_int)
|
||||
DEF( push_5, 1, 0, 1, none_int)
|
||||
DEF( push_6, 1, 0, 1, none_int)
|
||||
DEF( push_7, 1, 0, 1, none_int)
|
||||
DEF( push_i8, 2, 0, 1, i8)
|
||||
DEF( push_i16, 3, 0, 1, i16)
|
||||
DEF( push_const8, 2, 0, 1, const8)
|
||||
DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */
|
||||
DEF(push_empty_string, 1, 0, 1, none)
|
||||
|
||||
DEF( get_loc8, 2, 0, 1, loc8)
|
||||
DEF( put_loc8, 2, 1, 0, loc8)
|
||||
DEF( set_loc8, 2, 1, 1, loc8)
|
||||
|
||||
DEF( get_loc0, 1, 0, 1, none_loc)
|
||||
DEF( get_loc1, 1, 0, 1, none_loc)
|
||||
DEF( get_loc2, 1, 0, 1, none_loc)
|
||||
DEF( get_loc3, 1, 0, 1, none_loc)
|
||||
DEF( put_loc0, 1, 1, 0, none_loc)
|
||||
DEF( put_loc1, 1, 1, 0, none_loc)
|
||||
DEF( put_loc2, 1, 1, 0, none_loc)
|
||||
DEF( put_loc3, 1, 1, 0, none_loc)
|
||||
DEF( set_loc0, 1, 1, 1, none_loc)
|
||||
DEF( set_loc1, 1, 1, 1, none_loc)
|
||||
DEF( set_loc2, 1, 1, 1, none_loc)
|
||||
DEF( set_loc3, 1, 1, 1, none_loc)
|
||||
DEF( get_arg0, 1, 0, 1, none_arg)
|
||||
DEF( get_arg1, 1, 0, 1, none_arg)
|
||||
DEF( get_arg2, 1, 0, 1, none_arg)
|
||||
DEF( get_arg3, 1, 0, 1, none_arg)
|
||||
DEF( put_arg0, 1, 1, 0, none_arg)
|
||||
DEF( put_arg1, 1, 1, 0, none_arg)
|
||||
DEF( put_arg2, 1, 1, 0, none_arg)
|
||||
DEF( put_arg3, 1, 1, 0, none_arg)
|
||||
DEF( set_arg0, 1, 1, 1, none_arg)
|
||||
DEF( set_arg1, 1, 1, 1, none_arg)
|
||||
DEF( set_arg2, 1, 1, 1, none_arg)
|
||||
DEF( set_arg3, 1, 1, 1, none_arg)
|
||||
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
|
||||
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
|
||||
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||
|
||||
DEF( get_length, 1, 1, 1, none)
|
||||
|
||||
DEF( if_false8, 2, 1, 0, label8)
|
||||
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||
DEF( goto16, 3, 0, 0, label16)
|
||||
|
||||
DEF( call0, 1, 1, 1, npopx)
|
||||
DEF( call1, 1, 1, 1, npopx)
|
||||
DEF( call2, 1, 1, 1, npopx)
|
||||
DEF( call3, 1, 1, 1, npopx)
|
||||
|
||||
DEF( is_undefined, 1, 1, 1, none)
|
||||
DEF( is_null, 1, 1, 1, none)
|
||||
DEF(typeof_is_undefined, 1, 1, 1, none)
|
||||
DEF( typeof_is_function, 1, 1, 1, none)
|
||||
#endif
|
||||
|
||||
#undef DEF
|
||||
#undef def
|
||||
#endif /* DEF */
|
||||
689
src/quickjs/quickjs-textcode.c
Normal file
689
src/quickjs/quickjs-textcode.c
Normal file
@@ -0,0 +1,689 @@
|
||||
#include "defines.h"
|
||||
#include "quickjs-textcode.h"
|
||||
#include "utils.h"
|
||||
#include "buffer-utils.h"
|
||||
#include "debug.h"
|
||||
#include <libutf.h>
|
||||
#include <libutf.h>
|
||||
#include "tutf8e.h"
|
||||
|
||||
/**
|
||||
* \addtogroup quickjs-textdecoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
VISIBLE JSClassID js_decoder_class_id = 0, js_encoder_class_id = 0;
|
||||
VISIBLE JSValue textdecoder_proto = {{0}, JS_TAG_UNDEFINED}, textdecoder_ctor = {{0}, JS_TAG_UNDEFINED}, textencoder_proto = {{0}, JS_TAG_UNDEFINED},
|
||||
textencoder_ctor = {{0}, JS_TAG_UNDEFINED};
|
||||
|
||||
const TUTF8encoder* tutf8e_coders[] = {
|
||||
/* 0, 0, 0, 0, 0, 0, 0, 0, */
|
||||
&tutf8e_encoder_iso_8859_1, &tutf8e_encoder_iso_8859_2, &tutf8e_encoder_iso_8859_3, &tutf8e_encoder_iso_8859_4, &tutf8e_encoder_iso_8859_5,
|
||||
&tutf8e_encoder_iso_8859_6, &tutf8e_encoder_iso_8859_7, &tutf8e_encoder_iso_8859_8, &tutf8e_encoder_iso_8859_9, &tutf8e_encoder_iso_8859_10,
|
||||
&tutf8e_encoder_iso_8859_11, &tutf8e_encoder_iso_8859_13, &tutf8e_encoder_iso_8859_14, &tutf8e_encoder_iso_8859_15, &tutf8e_encoder_iso_8859_16,
|
||||
&tutf8e_encoder_windows_1250, &tutf8e_encoder_windows_1251, &tutf8e_encoder_windows_1252, &tutf8e_encoder_windows_1253, &tutf8e_encoder_windows_1254,
|
||||
&tutf8e_encoder_windows_1255, &tutf8e_encoder_windows_1256, &tutf8e_encoder_windows_1257, &tutf8e_encoder_windows_1258,
|
||||
};
|
||||
|
||||
const char* const textcode_encodings[] = {
|
||||
"unknown", "UTF-8", "UTF-16", "UTF-32", "unknown", "UTF-8", "UTF-16BE", "UTF-32BE",
|
||||
"ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8",
|
||||
"ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "WINDOWS-1250",
|
||||
"WINDOWS-1251", "WINDOWS-1252", "WINDOWS-1253", "WINDOWS-1254", "WINDOWS-1255", "WINDOWS-1256", "WINDOWS-1257", "WINDOWS-1258",
|
||||
};
|
||||
|
||||
enum {
|
||||
DECODER_DECODE,
|
||||
DECODER_END,
|
||||
};
|
||||
enum {
|
||||
DECODER_ENCODING,
|
||||
DECODER_ENDIANNESS,
|
||||
DECODER_BUFFERED,
|
||||
};
|
||||
|
||||
static size_t
|
||||
textdecoder_try(const void* in, size_t len) {
|
||||
const uint8_t *x, *y, *end;
|
||||
size_t r = 0;
|
||||
int ch;
|
||||
|
||||
x = in;
|
||||
end = x + len;
|
||||
|
||||
while(x < end) {
|
||||
y = x;
|
||||
|
||||
if((ch = unicode_from_utf8(x, end - x, &x)) == -1)
|
||||
break;
|
||||
|
||||
r += x - y;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
textdecoder_length(TextDecoder* td) {
|
||||
size_t len = 0, r;
|
||||
|
||||
r = textdecoder_try(ringbuffer_begin(&td->buffer), ringbuffer_continuous(&td->buffer));
|
||||
len += r;
|
||||
|
||||
if(len == ringbuffer_continuous(&td->buffer))
|
||||
if(td->buffer.head < td->buffer.tail) {
|
||||
r = textdecoder_try(td->buffer.data, ringbuffer_head(&td->buffer));
|
||||
len += r;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
JSValue
|
||||
textdecoder_decode(TextDecoder* dec, JSContext* ctx) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
DynBuf dbuf;
|
||||
size_t i = 0, blen;
|
||||
uint_least32_t cp;
|
||||
char tmp[UTF8_CHAR_LEN_MAX];
|
||||
int len = 0;
|
||||
js_dbuf_init(ctx, &dbuf);
|
||||
blen = ringbuffer_length(&dec->buffer);
|
||||
|
||||
if(blen)
|
||||
switch(dec->encoding) {
|
||||
case UTF8: {
|
||||
size_t blen, rlen = ringbuffer_length(&dec->buffer);
|
||||
|
||||
if((blen = textdecoder_length(dec)) < rlen) {
|
||||
ringbuffer_normalize(&dec->buffer);
|
||||
blen = textdecoder_length(dec);
|
||||
}
|
||||
|
||||
ret = JS_NewStringLen(ctx, (const char*)ringbuffer_begin(&dec->buffer), blen);
|
||||
ringbuffer_skip(&dec->buffer, blen);
|
||||
break;
|
||||
}
|
||||
case UTF16: {
|
||||
uint_least16_t* ptr = ringbuffer_begin(&dec->buffer);
|
||||
size_t n = blen & ~(0x1);
|
||||
|
||||
for(i = 0; i < n; ptr = ringbuffer_next(&dec->buffer, ptr), i += 2) {
|
||||
uint_least16_t u16[2] = {uint16_get_endian(ptr, dec->endian), 0};
|
||||
size_t ns = 2;
|
||||
|
||||
if(utf16_multiword(u16)) {
|
||||
if(i + 2 >= n)
|
||||
break;
|
||||
u16[1] = uint16_get_endian(ptr + 1, dec->endian == BIG);
|
||||
ns += 2;
|
||||
}
|
||||
|
||||
if(!libutf_c16_to_c32(u16, &cp)) {
|
||||
ret = JS_ThrowInternalError(ctx,
|
||||
"%s: TextDecoder: not a valid utf-16 code at (%llu: 0x%04x, 0x%04x): %lu",
|
||||
__func__,
|
||||
(long long unsigned int)i,
|
||||
(unsigned int)ptr[0],
|
||||
(unsigned int)ptr[1],
|
||||
(unsigned long)cp);
|
||||
break;
|
||||
}
|
||||
len = unicode_to_utf8((void*)tmp, cp);
|
||||
|
||||
if(dbuf_put(&dbuf, (const void*)tmp, len))
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case UTF32: {
|
||||
const uint_least32_t* ptr = ringbuffer_begin(&dec->buffer);
|
||||
size_t n = blen & ~(0x3);
|
||||
|
||||
for(i = 0; i < n; ptr = ringbuffer_next(&dec->buffer, ptr), i += 4) {
|
||||
cp = uint32_get_endian(ptr, dec->endian);
|
||||
if(!libutf_c32_to_c8(cp, &len, tmp)) {
|
||||
ret = JS_ThrowInternalError(ctx,
|
||||
"%s: TextDecoder: not a valid utf-32 code at (%llu: 0x%04x, 0x%04x): %lu",
|
||||
__func__,
|
||||
(long long unsigned int)i,
|
||||
(unsigned int)ptr[0],
|
||||
(unsigned int)ptr[1],
|
||||
(unsigned long)cp);
|
||||
break;
|
||||
}
|
||||
if(dbuf_put(&dbuf, (const void*)tmp, len))
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
TUTF8encoder encoder;
|
||||
|
||||
if((encoder = *tutf8e_coders[dec->encoding - 8])) {
|
||||
|
||||
const char* ptr = ringbuffer_begin(&dec->buffer);
|
||||
size_t n = 0;
|
||||
|
||||
if(TUTF8E_OK == tutf8e_encoder_buffer_length(encoder, ptr, 0, blen, &n)) {
|
||||
|
||||
uint8_t* dst = dbuf_reserve(&dbuf, n);
|
||||
|
||||
if(TUTF8E_OK == tutf8e_encoder_buffer_encode(encoder, ptr, blen, 0, (char*)dst, &n)) {
|
||||
dbuf.size += n;
|
||||
i = blen;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ret = JS_ThrowInternalError(ctx, "%s: TextDecoder: unknown encoding: %s", __func__, textcode_encodings[dec->encoding]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ringbuffer_skip(&dec->buffer, i);
|
||||
|
||||
if(JS_IsUndefined(ret) && dbuf.size > 0)
|
||||
ret = JS_NewStringLen(ctx, (const char*)dbuf.buf, dbuf.size);
|
||||
|
||||
dbuf_free(&dbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_decoder_get(JSContext* ctx, JSValueConst this_val, int magic) {
|
||||
TextDecoder* dec;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
if(!(dec = js_decoder_data(ctx, this_val)))
|
||||
return ret;
|
||||
switch(magic) {
|
||||
case DECODER_ENCODING: {
|
||||
ret = JS_NewString(ctx, textcode_encodings[dec->type_code]);
|
||||
break;
|
||||
}
|
||||
|
||||
case DECODER_ENDIANNESS: {
|
||||
ret = JS_NewBool(ctx, dec->endian == BIG);
|
||||
break;
|
||||
}
|
||||
|
||||
case DECODER_BUFFERED: {
|
||||
ret = JS_NewUint32(ctx, ringbuffer_length(&dec->buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_decoder_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst argv[]) {
|
||||
JSValue obj = JS_UNDEFINED;
|
||||
JSValue proto;
|
||||
TextDecoder* dec;
|
||||
|
||||
if(!(dec = js_mallocz(ctx, sizeof(TextDecoder))))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
/* using new_target to get the prototype is necessary when the class is extended. */
|
||||
proto = JS_GetPropertyStr(ctx, new_target, "prototype");
|
||||
if(JS_IsException(proto))
|
||||
goto fail;
|
||||
if(!JS_IsObject(proto))
|
||||
proto = textdecoder_proto;
|
||||
|
||||
/* using new_target to get the prototype is necessary when the class is extended. */
|
||||
obj = JS_NewObjectProtoClass(ctx, proto, js_decoder_class_id);
|
||||
JS_FreeValue(ctx, proto);
|
||||
if(JS_IsException(obj))
|
||||
goto fail;
|
||||
|
||||
ringbuffer_init(&dec->buffer, ctx);
|
||||
|
||||
if(argc >= 1) {
|
||||
const char* s = JS_ToCString(ctx, argv[0]);
|
||||
|
||||
if(s[case_finds(s, "utf32")] || s[case_finds(s, "utf-32")])
|
||||
dec->encoding = UTF32;
|
||||
else if(s[case_finds(s, "utf16")] || s[case_finds(s, "utf-16")])
|
||||
dec->encoding = UTF16;
|
||||
else if(s[case_finds(s, "utf8")] || s[case_finds(s, "utf-8")])
|
||||
dec->encoding = UTF8;
|
||||
else {
|
||||
return JS_ThrowInternalError(ctx, "%s: TextDecoder: '%s' is invalid s", __func__, s);
|
||||
}
|
||||
|
||||
if(s[case_finds(s, "be")] || s[case_finds(s, "be")])
|
||||
dec->endian = BIG;
|
||||
|
||||
JS_FreeCString(ctx, s);
|
||||
} else {
|
||||
dec->encoding = UTF8;
|
||||
}
|
||||
JS_SetOpaque(obj, dec);
|
||||
|
||||
return obj;
|
||||
|
||||
fail:
|
||||
js_free(ctx, dec);
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_decoder_decode(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst argv[], int magic) {
|
||||
TextDecoder* dec;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
|
||||
if(!(dec = js_decoder_data(ctx, this_val)))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
switch(magic) {
|
||||
case DECODER_END:
|
||||
case DECODER_DECODE: {
|
||||
InputBuffer in = js_input_chars(ctx, argv[0]);
|
||||
|
||||
// printf("js_decoder_decode (1) %s length=%zu in.size=%zu\n", magic == DECODER_DECODE ? "decode" :
|
||||
// "end", ringbuffer_length(&dec->buffer), in.size);
|
||||
if(ringbuffer_write(&dec->buffer, in.data, in.size) < 0)
|
||||
return JS_ThrowInternalError(ctx, "%s: TextDecoder: ringbuffer %s failed", __func__, magic == DECODER_DECODE ? "decode" : "end");
|
||||
|
||||
if(ringbuffer_length(&dec->buffer) == 0)
|
||||
ret = JS_NULL;
|
||||
else
|
||||
ret = textdecoder_decode(dec, ctx);
|
||||
|
||||
if(magic == DECODER_END)
|
||||
ringbuffer_reset(&dec->buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_decoder_inspect(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst argv[]) {
|
||||
TextDecoder* dec;
|
||||
|
||||
if(!(dec = js_decoder_data(ctx, this_val)))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
JSValue obj = JS_NewObjectClass(ctx, js_decoder_class_id);
|
||||
|
||||
JS_DefinePropertyValueStr(ctx, obj, "encoding", JS_NewString(ctx, textcode_encodings[dec->type_code]), JS_PROP_ENUMERABLE);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "buffered", JS_NewUint32(ctx, ringbuffer_length(&dec->buffer)), JS_PROP_ENUMERABLE);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
js_decoder_finalizer(JSRuntime* rt, JSValue val) {
|
||||
TextDecoder* dec = JS_GetOpaque(val, js_decoder_class_id);
|
||||
if(dec) {
|
||||
ringbuffer_free(&dec->buffer);
|
||||
js_free_rt(rt, dec);
|
||||
}
|
||||
// JS_FreeValueRT(rt, val);
|
||||
}
|
||||
|
||||
static JSClassDef js_decoder_class = {
|
||||
.class_name = "TextDecoder",
|
||||
.finalizer = js_decoder_finalizer,
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_decoder_funcs[] = {
|
||||
JS_CFUNC_MAGIC_DEF("decode", 1, js_decoder_decode, DECODER_DECODE),
|
||||
JS_CFUNC_MAGIC_DEF("end", 1, js_decoder_decode, DECODER_END),
|
||||
JS_CGETSET_ENUMERABLE_DEF("encoding", js_decoder_get, 0, DECODER_ENCODING),
|
||||
JS_CGETSET_MAGIC_DEF("endian", js_decoder_get, 0, DECODER_ENDIANNESS),
|
||||
JS_CGETSET_MAGIC_DEF("buffered", js_decoder_get, 0, DECODER_BUFFERED),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "TextDecoder", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
enum {
|
||||
ENCODER_ENCODE,
|
||||
ENCODER_END,
|
||||
};
|
||||
enum {
|
||||
ENCODER_ENCODING,
|
||||
ENCODER_ENDIANNESS,
|
||||
ENCODER_BUFFERED,
|
||||
};
|
||||
|
||||
/*static size_t
|
||||
textencoder_try(const void* in, size_t len) {
|
||||
const uint8_t *x, *y, *end;
|
||||
size_t r = 0;
|
||||
int ch;
|
||||
for(x = in, end=x+len; x < end; ) {
|
||||
y = x;
|
||||
if((ch = unicode_from_utf8(x, end - x, &x)) == -1)
|
||||
break;
|
||||
r += x - y;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
textencoder_length(TextEncoder* td) {
|
||||
size_t r = 0;
|
||||
|
||||
r += textencoder_try(ringbuffer_begin(&td->buffer), ringbuffer_continuous(&td->buffer));
|
||||
|
||||
if(td->buffer.head < td->buffer.tail)
|
||||
r += textencoder_try(td->buffer.data, ringbuffer_head(&td->buffer));
|
||||
|
||||
return r;
|
||||
}*/
|
||||
|
||||
JSValue
|
||||
textencoder_read(TextEncoder* te, JSContext* ctx) {
|
||||
JSValue ret, buf;
|
||||
int bits;
|
||||
size_t len = ringbuffer_length(&te->buffer);
|
||||
|
||||
if(len > ringbuffer_continuous(&te->buffer))
|
||||
ringbuffer_normalize(&te->buffer);
|
||||
|
||||
switch(te->encoding) {
|
||||
case UTF8: bits = 8; break;
|
||||
case UTF16: bits = 16; break;
|
||||
case UTF32: bits = 32; break;
|
||||
default: return JS_ThrowInternalError(ctx, "%s: TextEncoder: invalid encoding: %d", __func__, te->encoding);
|
||||
}
|
||||
|
||||
buf = JS_NewArrayBufferCopy(ctx, ringbuffer_begin(&te->buffer), len);
|
||||
ret = js_typedarray_new(ctx, bits, FALSE, FALSE, buf);
|
||||
JS_FreeValue(ctx, buf);
|
||||
|
||||
te->buffer.tail += len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue
|
||||
textencoder_encode(TextEncoder* enc, InputBuffer in, JSContext* ctx) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
size_t i;
|
||||
uint32_t cp;
|
||||
uint8_t u8[UTF8_CHAR_LEN_MAX];
|
||||
const uint8_t *ptr, *end, *next;
|
||||
|
||||
switch(enc->encoding) {
|
||||
case UTF8: {
|
||||
if(ringbuffer_write(&enc->buffer, in.data, in.size) < 0)
|
||||
return JS_ThrowInternalError(ctx, "%s: TextEncoder: ringbuffer write failed", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
case UTF16: {
|
||||
ptr = block_begin(&in.block);
|
||||
end = block_end(&in.block);
|
||||
|
||||
for(i = 0; ptr < end; ptr = next, i++) {
|
||||
cp = unicode_from_utf8(ptr, end - ptr, &next);
|
||||
|
||||
{
|
||||
uint_least16_t u16[2];
|
||||
int len;
|
||||
|
||||
if(!libutf_c32_to_c16(cp, &len, u16))
|
||||
return JS_ThrowInternalError(ctx,
|
||||
"%s: TextEncoder: not a valid code point at (%llu) [%llu]: %lu",
|
||||
__func__,
|
||||
(long long unsigned int)i,
|
||||
(long long unsigned int)(end - ptr),
|
||||
(unsigned long)cp);
|
||||
|
||||
for(int j = 0; j < len; j++)
|
||||
uint16_put_endian(u8 + j * 2, u16[j], enc->endian);
|
||||
|
||||
if(ringbuffer_append(&enc->buffer, u8, len * sizeof(uint16_t), ctx) < 0)
|
||||
return JS_ThrowInternalError(ctx, "TextEncoder: ringbuffer write failed");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UTF32: {
|
||||
ptr = block_begin(&in.block);
|
||||
end = block_end(&in.block);
|
||||
|
||||
for(i = 0; ptr < end; ptr = next, i++) {
|
||||
cp = unicode_from_utf8(ptr, end - ptr, &next);
|
||||
if(cp == 0xffffffff)
|
||||
return JS_ThrowInternalError(
|
||||
ctx, "%s: TextEncoder: not a valid code point at (%llu): %lu", __func__, (long long unsigned int)(ptr - in.block.base), (long unsigned int)cp);
|
||||
/*cp = 0;
|
||||
if(!libutf_c8_to_c32(ptr, &cp))
|
||||
return JS_ThrowInternalError(ctx, "No a valid code point at (%zu) [%zu]: %" PRIu32, i, end - ptr,
|
||||
cp); next = ptr + libutf_c8_type(ptr); if(next == ptr) break;*/
|
||||
|
||||
uint32_put_endian(u8, cp, enc->endian);
|
||||
|
||||
if(ringbuffer_append(&enc->buffer, u8, sizeof(cp), ctx) < 0)
|
||||
return JS_ThrowInternalError(ctx, "%s: TextEncoder: ringbuffer write failed", __func__);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ret = JS_ThrowInternalError(ctx, "%s: TextEncoder: unknown encoding", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_encoder_get(JSContext* ctx, JSValueConst this_val, int magic) {
|
||||
TextEncoder* enc;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
if(!(enc = js_encoder_data(ctx, this_val)))
|
||||
return ret;
|
||||
switch(magic) {
|
||||
case ENCODER_ENCODING: {
|
||||
ret = JS_NewString(ctx, textcode_encodings[enc->type_code]);
|
||||
break;
|
||||
}
|
||||
|
||||
case ENCODER_ENDIANNESS: {
|
||||
ret = JS_NewBool(ctx, enc->endian == BIG);
|
||||
break;
|
||||
}
|
||||
|
||||
case ENCODER_BUFFERED: {
|
||||
ret = JS_NewUint32(ctx, ringbuffer_length(&enc->buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_encoder_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst argv[]) {
|
||||
JSValue obj = JS_UNDEFINED;
|
||||
JSValue proto;
|
||||
TextEncoder* enc;
|
||||
|
||||
if(!(enc = js_mallocz(ctx, sizeof(TextEncoder))))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
/* using new_target to get the prototype is necessary when the class is extended. */
|
||||
proto = JS_GetPropertyStr(ctx, new_target, "prototype");
|
||||
if(JS_IsException(proto))
|
||||
goto fail;
|
||||
if(!JS_IsObject(proto))
|
||||
proto = textencoder_proto;
|
||||
|
||||
/* using new_target to get the prototype is necessary when the class is extended. */
|
||||
obj = JS_NewObjectProtoClass(ctx, proto, js_encoder_class_id);
|
||||
JS_FreeValue(ctx, proto);
|
||||
if(JS_IsException(obj))
|
||||
goto fail;
|
||||
|
||||
ringbuffer_init(&enc->buffer, ctx);
|
||||
|
||||
if(argc >= 1) {
|
||||
const char* s = JS_ToCString(ctx, argv[0]);
|
||||
|
||||
if(s[case_finds(s, "utf32")] || s[case_finds(s, "utf-32")])
|
||||
enc->encoding = UTF32;
|
||||
else if(s[case_finds(s, "utf16")] || s[case_finds(s, "utf-16")])
|
||||
enc->encoding = UTF16;
|
||||
else if(s[case_finds(s, "utf8")] || s[case_finds(s, "utf-8")])
|
||||
enc->encoding = UTF8;
|
||||
else {
|
||||
return JS_ThrowInternalError(ctx, "TextEncoder '%s' is invalid s", s);
|
||||
}
|
||||
|
||||
if(enc->encoding > UTF8)
|
||||
if(s[case_finds(s, "be")] || s[case_finds(s, "be")])
|
||||
enc->endian = BIG;
|
||||
|
||||
JS_FreeCString(ctx, s);
|
||||
} else {
|
||||
enc->encoding = UTF8;
|
||||
}
|
||||
JS_SetOpaque(obj, enc);
|
||||
|
||||
return obj;
|
||||
|
||||
fail:
|
||||
js_free(ctx, enc);
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_encoder_encode(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst argv[], int magic) {
|
||||
TextEncoder* enc;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
|
||||
if(!(enc = js_encoder_data(ctx, this_val)))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
switch(magic) {
|
||||
case ENCODER_END:
|
||||
case ENCODER_ENCODE: {
|
||||
InputBuffer in = js_input_chars(ctx, argv[0]);
|
||||
|
||||
ret = textencoder_encode(enc, in, ctx);
|
||||
|
||||
if(JS_IsException(ret))
|
||||
break;
|
||||
|
||||
if(ringbuffer_length(&enc->buffer) == 0)
|
||||
ret = JS_NULL;
|
||||
else
|
||||
ret = textencoder_read(enc, ctx);
|
||||
|
||||
if(magic == ENCODER_END)
|
||||
ringbuffer_reset(&enc->buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_encoder_inspect(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst argv[]) {
|
||||
TextEncoder* enc;
|
||||
|
||||
if(!(enc = js_encoder_data(ctx, this_val)))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
JSValue obj = JS_NewObjectClass(ctx, js_encoder_class_id);
|
||||
|
||||
JS_DefinePropertyValueStr(ctx, obj, "encoding", JS_NewString(ctx, textcode_encodings[enc->type_code]), JS_PROP_ENUMERABLE);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "buffered", JS_NewUint32(ctx, ringbuffer_length(&enc->buffer)), JS_PROP_ENUMERABLE);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
js_encoder_finalizer(JSRuntime* rt, JSValue val) {
|
||||
TextEncoder* enc = JS_GetOpaque(val, js_encoder_class_id);
|
||||
if(enc) {
|
||||
ringbuffer_free(&enc->buffer);
|
||||
js_free_rt(rt, enc);
|
||||
}
|
||||
// JS_FreeValueRT(rt, val);
|
||||
}
|
||||
|
||||
static JSClassDef js_encoder_class = {
|
||||
.class_name = "TextEncoder",
|
||||
.finalizer = js_encoder_finalizer,
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_encoder_funcs[] = {
|
||||
JS_CFUNC_MAGIC_DEF("encode", 1, js_encoder_encode, ENCODER_ENCODE),
|
||||
JS_CFUNC_MAGIC_DEF("end", 1, js_encoder_encode, ENCODER_END),
|
||||
JS_CGETSET_ENUMERABLE_DEF("encoding", js_encoder_get, 0, ENCODER_ENCODING),
|
||||
JS_CGETSET_MAGIC_DEF("endian", js_encoder_get, 0, ENCODER_ENDIANNESS),
|
||||
JS_CGETSET_MAGIC_DEF("buffered", js_encoder_get, 0, ENCODER_BUFFERED),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "TextEncoder", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
extern
|
||||
void JS_NewGlobalCConstructor2(JSContext *ctx,
|
||||
JSValue func_obj,
|
||||
const char *name,
|
||||
JSValueConst proto);
|
||||
int
|
||||
js_code_init_textdecoder(JSContext* ctx, JSModuleDef* m)
|
||||
{
|
||||
// RH TODO: check if this (possibly being called twice or for some other reason) produces a mem leak
|
||||
JS_NewClassID(&js_encoder_class_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_encoder_class_id, &js_encoder_class);
|
||||
|
||||
textencoder_ctor = JS_NewCFunction2(ctx, js_encoder_constructor, "TextEncoder", 1, JS_CFUNC_constructor, 0);
|
||||
textencoder_proto = JS_NewObject(ctx);
|
||||
|
||||
JS_SetPropertyFunctionList(ctx, textencoder_proto, js_encoder_funcs, countof(js_encoder_funcs));
|
||||
JS_SetClassProto(ctx, js_encoder_class_id, textencoder_proto);
|
||||
JS_SetConstructor(ctx, textencoder_ctor, textencoder_proto);
|
||||
|
||||
JS_NewGlobalCConstructor2(ctx, textencoder_ctor, "TextEncoder", textencoder_proto);
|
||||
|
||||
|
||||
JS_NewClassID(&js_decoder_class_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_decoder_class_id, &js_decoder_class);
|
||||
|
||||
textdecoder_ctor = JS_NewCFunction2(ctx, js_decoder_constructor, "TextDecoder", 1, JS_CFUNC_constructor, 0);
|
||||
textdecoder_proto = JS_NewObject(ctx);
|
||||
|
||||
JS_SetPropertyFunctionList(ctx, textdecoder_proto, js_decoder_funcs, countof(js_decoder_funcs));
|
||||
JS_SetClassProto(ctx, js_decoder_class_id, textdecoder_proto);
|
||||
|
||||
JS_SetConstructor(ctx, textdecoder_ctor, textdecoder_proto);
|
||||
|
||||
JS_NewGlobalCConstructor2(ctx, textdecoder_ctor, "TextDecoder", textdecoder_proto);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef JS_TEXTCODE_MODULE
|
||||
#define JS_INIT_MODULE js_init_module
|
||||
#else
|
||||
#define JS_INIT_MODULE js_init_module_textdecoder
|
||||
#endif
|
||||
|
||||
VISIBLE JSModuleDef*
|
||||
JS_INIT_MODULE(JSContext* ctx, const char* module_name) {
|
||||
JSModuleDef* m;
|
||||
|
||||
/*if((m = JS_NewCModule(ctx, module_name, js_code_init)))
|
||||
{
|
||||
JS_AddModuleExport(ctx, m, "TextDecoder");
|
||||
JS_AddModuleExport(ctx, m, "TextEncoder");
|
||||
//if(!strcmp(module_name, "textdecoder"))
|
||||
// JS_AddModuleExport(ctx, m, "default");
|
||||
}*/
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
86
src/quickjs/quickjs-textcode.h
Normal file
86
src/quickjs/quickjs-textcode.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef QUICKJS_TEXTCODE_H
|
||||
#define QUICKJS_TEXTCODE_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
/**
|
||||
* \defgroup quickjs-textdecoder quickjs-textdecoder: String Decoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum utf_encoding { UNKNOWN = 0, UTF8, UTF16, UTF32 } UTFCharset;
|
||||
typedef enum text_encoding {
|
||||
UTF16LE = 2,
|
||||
UTF32LE = 3,
|
||||
UTF16BE = 6,
|
||||
UTF32BE = 7,
|
||||
ISO_8859_1,
|
||||
ISO_8859_2,
|
||||
ISO_8859_3,
|
||||
ISO_8859_4,
|
||||
ISO_8859_5,
|
||||
ISO_8859_6,
|
||||
ISO_8859_7,
|
||||
ISO_8859_8,
|
||||
ISO_8859_9,
|
||||
ISO_8859_10,
|
||||
ISO_8859_11,
|
||||
ISO_8859_13,
|
||||
ISO_8859_14,
|
||||
ISO_8859_15,
|
||||
ISO_8859_16,
|
||||
WINDOWS_1250,
|
||||
WINDOWS_1251,
|
||||
WINDOWS_1252,
|
||||
WINDOWS_1253,
|
||||
WINDOWS_1254,
|
||||
WINDOWS_1255,
|
||||
WINDOWS_1256,
|
||||
WINDOWS_1257,
|
||||
WINDOWS_1258,
|
||||
} TextEncoding;
|
||||
|
||||
#define TextcodeType \
|
||||
PACK union { \
|
||||
struct { \
|
||||
UTFCharset encoding : 2; \
|
||||
Endian endian : 1; \
|
||||
}; \
|
||||
TextEncoding type_code; \
|
||||
}; \
|
||||
ENDPACK
|
||||
|
||||
struct text_coder {
|
||||
RingBuffer buffer;
|
||||
TextcodeType
|
||||
};
|
||||
|
||||
typedef struct text_coder TextEncoder;
|
||||
typedef struct text_coder TextDecoder;
|
||||
|
||||
extern VISIBLE JSClassID js_decoder_class_id, js_encoder_class_id;
|
||||
extern VISIBLE JSValue textdecoder_proto, textdecoder_ctor, textencoder_proto, textencoder_ctor;
|
||||
extern const char* const textcode_encodings[];
|
||||
|
||||
size_t textdecoder_length(TextDecoder*);
|
||||
JSValue textdecoder_read(TextDecoder*, JSContext* ctx);
|
||||
int js_code_init_textdecoder(JSContext*, JSModuleDef* m);
|
||||
size_t textencoder_length(TextEncoder*);
|
||||
JSValue textencoder_read(TextEncoder*, JSContext* ctx);
|
||||
int js_encoder_init(JSContext*, JSModuleDef* m);
|
||||
|
||||
static inline TextDecoder*
|
||||
js_decoder_data(JSContext* ctx, JSValueConst value) {
|
||||
return JS_GetOpaque(value, js_decoder_class_id);
|
||||
}
|
||||
|
||||
static inline TextEncoder*
|
||||
js_encoder_data(JSContext* ctx, JSValueConst value) {
|
||||
return JS_GetOpaque(value, js_encoder_class_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(QUICKJS_TEXTCODE_H) */
|
||||
55942
src/quickjs/quickjs.c
Normal file
55942
src/quickjs/quickjs.c
Normal file
File diff suppressed because it is too large
Load Diff
1070
src/quickjs/quickjs.h
Normal file
1070
src/quickjs/quickjs.h
Normal file
File diff suppressed because it is too large
Load Diff
136
src/quickjs/ringbuffer.c
Normal file
136
src/quickjs/ringbuffer.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "ringbuffer.h"
|
||||
|
||||
/**
|
||||
* \addtogroup ringbuffer
|
||||
* @{
|
||||
*/
|
||||
void
|
||||
ringbuffer_reset(RingBuffer* r) {
|
||||
r->head = r->tail = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ringbuffer_queue(RingBuffer* r, uint8_t data) {
|
||||
/* overwrite the oldest byte if the r is full */
|
||||
if(ringbuffer_full(r)) {
|
||||
r->tail = ((r->tail + 1) % r->size);
|
||||
}
|
||||
|
||||
r->data[r->head] = data;
|
||||
r->head = ((r->head + 1) % r->size);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ringbuffer_dequeue(RingBuffer* r, uint8_t* data) {
|
||||
if(ringbuffer_empty(r))
|
||||
return FALSE;
|
||||
|
||||
*data = r->data[r->tail];
|
||||
r->tail = ((r->tail + 1) % r->size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ringbuffer_write(RingBuffer* r, const void* x, size_t len) {
|
||||
const uint8_t* p = x;
|
||||
size_t i;
|
||||
|
||||
if(ringbuffer_avail(r) < len)
|
||||
return -1;
|
||||
// ringbuffer_realloc(r, ringbuffer_length(r) + len);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
assert(!ringbuffer_full(r));
|
||||
ringbuffer_queue(r, p[i]);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ringbuffer_append(RingBuffer* r, const void* x, size_t len, JSContext* ctx) {
|
||||
|
||||
if(!ringbuffer_reserve(r, ringbuffer_length(r) + len))
|
||||
return -1;
|
||||
|
||||
return ringbuffer_write(r, x, len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ringbuffer_read(RingBuffer* r, void* x, size_t len) {
|
||||
uint8_t* p = x;
|
||||
size_t i;
|
||||
|
||||
if(ringbuffer_empty(r))
|
||||
return -1;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
ringbuffer_dequeue(r, &p[i]);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
ringbuffer_peek(RingBuffer* r, size_t index) {
|
||||
if(index >= ringbuffer_length(r))
|
||||
return 0;
|
||||
|
||||
return &r->data[(r->tail + index) % r->size];
|
||||
}
|
||||
|
||||
void
|
||||
ringbuffer_normalize(RingBuffer* r) {
|
||||
if(r->head < r->tail) {
|
||||
size_t n = r->size - r->tail;
|
||||
void* x = alloca(r->head);
|
||||
memcpy(x, r->data, r->head);
|
||||
memmove(r->data, &r->data[r->tail], n);
|
||||
memcpy(&r->data[n], x, r->head);
|
||||
r->tail = 0;
|
||||
r->head += n;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(r->data, &r->data[r->tail], ringbuffer_length(r));
|
||||
r->head -= r->tail;
|
||||
r->tail = 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ringbuffer_resize(RingBuffer* r, size_t newsize) {
|
||||
ringbuffer_normalize(r);
|
||||
if(newsize > r->size)
|
||||
return vector_grow(&r->vec, 1, newsize);
|
||||
else if(newsize < r->size)
|
||||
return vector_shrink(&r->vec, 1, newsize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ringbuffer_allocate(RingBuffer* r, size_t size) {
|
||||
ssize_t n = ringbuffer_length(r);
|
||||
|
||||
if((r->size - n) < size)
|
||||
return ringbuffer_resize(r, ringbuffer_length(r) + size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
ringbuffer_reserve(RingBuffer* rb, size_t min_bytes) {
|
||||
ssize_t grow;
|
||||
if((grow = min_bytes - ringbuffer_avail(rb)) > 0)
|
||||
if(!ringbuffer_resize(rb, vector_size(&rb->vec, 1) + grow))
|
||||
return 0;
|
||||
|
||||
if(ringbuffer_headroom(rb) < min_bytes)
|
||||
ringbuffer_normalize(rb);
|
||||
|
||||
assert(ringbuffer_headroom(rb) >= min_bytes);
|
||||
|
||||
return ringbuffer_end(rb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
88
src/quickjs/ringbuffer.h
Normal file
88
src/quickjs/ringbuffer.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef RINGBUFFER_H
|
||||
#define RINGBUFFER_H
|
||||
|
||||
#include "vector.h"
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* \defgroup ringbuffer ringbuffer: Ring Buffer implementation
|
||||
* @{
|
||||
*/
|
||||
typedef union ringbuffer {
|
||||
struct {
|
||||
uint8_t* data;
|
||||
size_t size, capacity;
|
||||
BOOL error;
|
||||
DynBufReallocFunc* realloc_func;
|
||||
void* opaque;
|
||||
volatile uint32_t tail, head;
|
||||
};
|
||||
DynBuf dbuf;
|
||||
Vector vec;
|
||||
|
||||
} RingBuffer;
|
||||
|
||||
#define RINGBUFFER_INIT() \
|
||||
{ \
|
||||
{ 0, 0, 0, 0, &ringbuffer_default_realloc, 0 } \
|
||||
}
|
||||
|
||||
#define ringbuffer_init(rb, ctx) \
|
||||
do { \
|
||||
vector_init(&(rb)->vec, ctx); \
|
||||
vector_allocate(&(rb)->vec, 1, 1023); \
|
||||
} while(0)
|
||||
#define ringbuffer_init_rt(rb, rt) \
|
||||
do { \
|
||||
vector_init_rt(&(rb)->vec, rt); \
|
||||
vector_allocate(&(rb)->vec, 1, 1023); \
|
||||
} while(0)
|
||||
#define RINGBUFFER(ctx) \
|
||||
(RingBuffer) { \
|
||||
{ 0, 0, 0, 0, (DynBufReallocFunc*)&js_realloc, ctx, 0, 0 } \
|
||||
}
|
||||
#define RINGBUFFER_RT(rt) \
|
||||
(RingBuffer) { \
|
||||
{ 0, 0, 0, 0, (DynBufReallocFunc*)&js_realloc_rt, rt } \
|
||||
}
|
||||
#define ringbuffer_free(rb) vector_free(&(rb)->vec)
|
||||
#define ringbuffer_begin(rb) (void*)&ringbuffer_tail(rb)
|
||||
#define ringbuffer_end(rb) (void*)&ringbuffer_head(rb)
|
||||
#define ringbuffer_head(rb) (rb)->data[(rb)->head]
|
||||
#define ringbuffer_tail(rb) (rb)->data[(rb)->tail]
|
||||
|
||||
#define ringbuffer_empty(rb) ((rb)->tail == (rb)->head)
|
||||
#define ringbuffer_full(rb) ((rb)->size == (rb)->head - (rb)->tail)
|
||||
#define ringbuffer_wrapped(rb) ((rb)->head < (rb)->tail)
|
||||
#define ringbuffer_headroom(rb) ((rb)->size - (rb)->head)
|
||||
#define ringbuffer_avail(rb) ((rb)->size - ringbuffer_length(rb))
|
||||
#define ringbuffer_length(rb) (ringbuffer_wrapped(rb) ? ((rb)->size - (rb)->tail) + (rb)->head : (rb)->head - (rb)->tail)
|
||||
#define ringbuffer_continuous(rb) (ringbuffer_wrapped(rb) ? (rb)->size - (rb)->tail : (rb)->head - (rb)->tail)
|
||||
#define ringbuffer_is_continuous(rb) ((rb)->head >= (rb)->tail)
|
||||
//#define ringbuffer_skip(rb, n) ((rb)->tail += (n), (rb)->tail %= (rb)->size)
|
||||
#define ringbuffer_wrap(rb, idx) ((idx) % (rb)->size)
|
||||
#define ringbuffer_next(rb, ptr) (void*)(ringbuffer_wrap(rb, ((uint8_t*)(ptr + 1)) - (rb)->data) + (rb)->data)
|
||||
|
||||
void ringbuffer_reset(RingBuffer*);
|
||||
void ringbuffer_queue(RingBuffer*, uint8_t data);
|
||||
BOOL ringbuffer_dequeue(RingBuffer*, uint8_t* data);
|
||||
ssize_t ringbuffer_write(RingBuffer*, const void* x, size_t len);
|
||||
ssize_t ringbuffer_read(RingBuffer*, void* x, size_t len);
|
||||
uint8_t* ringbuffer_peek(RingBuffer*, size_t index);
|
||||
void ringbuffer_normalize(RingBuffer*);
|
||||
BOOL ringbuffer_resize(RingBuffer*, size_t);
|
||||
BOOL ringbuffer_allocate(RingBuffer*, size_t);
|
||||
uint8_t* ringbuffer_reserve(RingBuffer* rb, size_t min_bytes);
|
||||
ssize_t ringbuffer_append(RingBuffer* r, const void* x, size_t len, JSContext* ctx);
|
||||
|
||||
static inline uint8_t*
|
||||
ringbuffer_skip(RingBuffer* rb, size_t n) {
|
||||
assert(ringbuffer_length(rb) >= n);
|
||||
rb->tail = (rb->tail + n) % rb->size;
|
||||
return ringbuffer_begin(rb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(RINGBUFFER_H) */
|
||||
69
src/quickjs/test_fib.c
Normal file
69
src/quickjs/test_fib.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* File generated automatically by the QuickJS compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_test_fib_size = 160;
|
||||
|
||||
const uint8_t qjsc_test_fib[160] = {
|
||||
0x43, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
|
||||
0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
|
||||
0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, 0x10,
|
||||
0x2e, 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x73, 0x6f,
|
||||
0x06, 0x66, 0x69, 0x62, 0x0e, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x6f, 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67,
|
||||
0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57,
|
||||
0x6f, 0x72, 0x6c, 0x64, 0x10, 0x66, 0x69, 0x62,
|
||||
0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d, 0xc6, 0x03,
|
||||
0x01, 0xc8, 0x03, 0x00, 0x00, 0x01, 0x00, 0xca,
|
||||
0x03, 0x00, 0x00, 0x0c, 0x20, 0x06, 0x01, 0xa2,
|
||||
0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x32,
|
||||
0x00, 0xca, 0x03, 0x00, 0x0c, 0x08, 0xec, 0x02,
|
||||
0x29, 0x38, 0xe6, 0x00, 0x00, 0x00, 0x42, 0xe7,
|
||||
0x00, 0x00, 0x00, 0x04, 0xe8, 0x00, 0x00, 0x00,
|
||||
0x24, 0x01, 0x00, 0x0e, 0x38, 0xe6, 0x00, 0x00,
|
||||
0x00, 0x42, 0xe7, 0x00, 0x00, 0x00, 0x04, 0xe9,
|
||||
0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0xbf, 0x0a,
|
||||
0xf1, 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2e, 0xc6,
|
||||
0x03, 0x01, 0x05, 0x01, 0x00, 0x04, 0x0a, 0x62,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContextRaw(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
JS_AddIntrinsicBaseObjects(ctx);
|
||||
JS_AddIntrinsicDate(ctx);
|
||||
JS_AddIntrinsicEval(ctx);
|
||||
JS_AddIntrinsicStringNormalize(ctx);
|
||||
JS_AddIntrinsicRegExp(ctx);
|
||||
JS_AddIntrinsicJSON(ctx);
|
||||
JS_AddIntrinsicProxy(ctx);
|
||||
JS_AddIntrinsicMapSet(ctx);
|
||||
JS_AddIntrinsicTypedArrays(ctx);
|
||||
JS_AddIntrinsicPromise(ctx);
|
||||
JS_AddIntrinsicBigInt(ctx);
|
||||
{
|
||||
extern JSModuleDef *js_init_module_fib(JSContext *ctx, const char *name);
|
||||
js_init_module_fib(ctx, "examples/fib.so");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_test_fib, qjsc_test_fib_size, 0);
|
||||
js_std_loop(ctx);
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 0;
|
||||
}
|
||||
676
src/quickjs/tutf8e.c
Normal file
676
src/quickjs/tutf8e.c
Normal file
@@ -0,0 +1,676 @@
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int tutf8e_string_length(const uint16_t *table, const char *input, const char *invalid, size_t *input_length, size_t *output_length)
|
||||
{
|
||||
const size_t invalid_length = invalid ? strlen(invalid) : 0;
|
||||
|
||||
const unsigned char *i;
|
||||
for (i = (const unsigned char *) input; *i; ++i, (*input_length)++) {
|
||||
const uint16_t c = table[*i];
|
||||
if (c<0x80) {
|
||||
*output_length += 1;
|
||||
continue;
|
||||
}
|
||||
if (c<0x800) {
|
||||
*output_length += 2;
|
||||
continue;
|
||||
}
|
||||
if (c<0xffff) {
|
||||
*output_length += 3;
|
||||
continue;
|
||||
}
|
||||
if (invalid) {
|
||||
*output_length += invalid_length;
|
||||
}
|
||||
else {
|
||||
return TUTF8E_INVALID;
|
||||
}
|
||||
}
|
||||
return TUTF8E_OK;
|
||||
}
|
||||
|
||||
int tutf8e_string_encode(const uint16_t *table, const char *input, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
int ret;
|
||||
size_t input_length = 0;
|
||||
size_t encoded_length = 0;
|
||||
if (!(ret = tutf8e_string_length(table, input, invalid, &input_length, &encoded_length)))
|
||||
{
|
||||
if (encoded_length+1 > *output_length) return TUTF8E_TOOLONG;
|
||||
if (!(ret = tutf8e_buffer_encode(table, input, input_length, invalid, output, output_length)))
|
||||
{
|
||||
output[encoded_length] = 0;
|
||||
return TUTF8E_OK;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tutf8e_buffer_length
|
||||
(
|
||||
const uint16_t *table,
|
||||
const char *input,
|
||||
size_t input_length,
|
||||
const char *invalid,
|
||||
size_t *length
|
||||
)
|
||||
{
|
||||
const size_t invalid_length = invalid ? strlen(invalid) : 0;
|
||||
|
||||
const unsigned char *i;
|
||||
for (i = (const unsigned char *) input; input_length; ++i, --input_length) {
|
||||
const uint16_t c = table[*i];
|
||||
if (c<0x80) {
|
||||
++*length;
|
||||
continue;
|
||||
}
|
||||
if (c<0x800) {
|
||||
*length += 2;
|
||||
continue;
|
||||
}
|
||||
if (c<0xffff) {
|
||||
*length += 3;
|
||||
continue;
|
||||
}
|
||||
if (invalid) {
|
||||
*length += invalid_length;
|
||||
}
|
||||
else {
|
||||
return TUTF8E_INVALID;
|
||||
}
|
||||
}
|
||||
return TUTF8E_OK;
|
||||
}
|
||||
|
||||
int tutf8e_buffer_encode
|
||||
(
|
||||
const uint16_t *table,
|
||||
const char *input,
|
||||
size_t input_length,
|
||||
const char *invalid,
|
||||
char *output,
|
||||
size_t *output_length
|
||||
)
|
||||
{
|
||||
size_t invalid_length = invalid ? strlen(invalid) : 0;
|
||||
|
||||
size_t left = *output_length;
|
||||
unsigned char *o = (unsigned char *) output;
|
||||
const unsigned char *i;
|
||||
for (i = (const unsigned char *) input; input_length; ++i, --input_length) {
|
||||
const uint16_t c = table[*i];
|
||||
if (c<0x80) {
|
||||
if (left<1) return TUTF8E_TOOLONG;
|
||||
*(o++) = c;
|
||||
left -= 1;
|
||||
continue;
|
||||
}
|
||||
if (c<0x800) {
|
||||
if (left<2) return TUTF8E_TOOLONG;
|
||||
*(o++) = 0xc0 | (c>>6);
|
||||
*(o++) = 0x80 | (c&0x3f);
|
||||
left -= 2;
|
||||
continue;
|
||||
}
|
||||
if (c<0xffff) {
|
||||
if (left<3) return TUTF8E_TOOLONG;
|
||||
*(o++) = 0xe0 | (c>>12);
|
||||
*(o++) = 0x80 | ((c>>6)&0x3f);
|
||||
*(o++) = 0x80 | (c&0x3f);
|
||||
left -= 3;
|
||||
continue;
|
||||
}
|
||||
if (invalid)
|
||||
{
|
||||
if (left<invalid_length) return TUTF8E_TOOLONG;
|
||||
if (invalid_length) {
|
||||
memcpy(o, invalid, invalid_length);
|
||||
o += invalid_length;
|
||||
left -= invalid_length;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return TUTF8E_INVALID;
|
||||
}
|
||||
}
|
||||
*output_length -= left;
|
||||
return TUTF8E_OK;
|
||||
}
|
||||
|
||||
const uint16_t tutf8e_iso_8859_1_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_10_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7, 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a,
|
||||
0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b,
|
||||
0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_11_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
|
||||
0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
|
||||
0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
|
||||
0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0xffff, 0xffff, 0xffff, 0xffff, 0x0e3f,
|
||||
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
|
||||
0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_13_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
|
||||
0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
|
||||
0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
|
||||
0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
|
||||
0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_14_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178,
|
||||
0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_15_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_16_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b,
|
||||
0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a, 0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_2_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
|
||||
0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_3_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0xffff, 0x0124, 0x00a7, 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0xffff, 0x017b,
|
||||
0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0xffff, 0x017c,
|
||||
0x00c0, 0x00c1, 0x00c2, 0xffff, 0x00c4, 0x010a, 0x0108, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0xffff, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0xffff, 0x00e4, 0x010b, 0x0109, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0xffff, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_4_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,
|
||||
0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,
|
||||
0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,
|
||||
0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,
|
||||
0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,
|
||||
0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_5_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
|
||||
0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_6_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0xffff, 0xffff, 0xffff, 0x00a4, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x060c, 0x00ad, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x061b, 0xffff, 0xffff, 0xffff, 0x061f,
|
||||
0xffff, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
|
||||
0x0650, 0x0651, 0x0652, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_7_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x2018, 0x2019, 0x00a3, 0x20ac, 0x20af, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x037a, 0x00ab, 0x00ac, 0x00ad, 0xffff, 0x2015,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
0x03a0, 0x03a1, 0xffff, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
|
||||
0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
|
||||
0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_8_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0xffff, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x2017,
|
||||
0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
|
||||
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0xffff, 0xffff, 0x200e, 0x200f, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_iso_8859_9_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1250_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0xffff, 0x201e, 0x2026, 0x2020, 0x2021, 0xffff, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0xffff, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
|
||||
0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
|
||||
0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1251_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
|
||||
0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0xffff, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
|
||||
0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
|
||||
0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1252_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xffff, 0x017d, 0xffff,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xffff, 0x017e, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1253_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0xffff, 0x2030, 0xffff, 0x2039, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0xffff, 0x2122, 0xffff, 0x203a, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0xffff, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
0x03a0, 0x03a1, 0xffff, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
|
||||
0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
|
||||
0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1254_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xffff, 0xffff, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1255_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0xffff, 0x2039, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0xffff, 0x203a, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0xffff, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
|
||||
0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
|
||||
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0xffff, 0xffff, 0x200e, 0x200f, 0xffff,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1256_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
|
||||
0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
|
||||
0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
|
||||
0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
|
||||
0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
|
||||
0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1257_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0xffff, 0x201e, 0x2026, 0x2020, 0x2021, 0xffff, 0x2030, 0xffff, 0x2039, 0xffff, 0x00a8, 0x02c7, 0x00b8,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0xffff, 0x2122, 0xffff, 0x203a, 0xffff, 0x00af, 0x02db, 0xffff,
|
||||
0x00a0, 0xffff, 0x00a2, 0x00a3, 0x00a4, 0xffff, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
|
||||
0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
|
||||
0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
|
||||
0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
|
||||
0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9,
|
||||
};
|
||||
|
||||
const uint16_t tutf8e_windows_1258_utf8[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0xffff, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0xffff, 0x2039, 0x0152, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0xffff, 0x203a, 0x0153, 0xffff, 0xffff, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff,
|
||||
};
|
||||
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_1 = (TUTF8encoder) tutf8e_iso_8859_1_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_10 = (TUTF8encoder) tutf8e_iso_8859_10_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_11 = (TUTF8encoder) tutf8e_iso_8859_11_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_13 = (TUTF8encoder) tutf8e_iso_8859_13_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_14 = (TUTF8encoder) tutf8e_iso_8859_14_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_15 = (TUTF8encoder) tutf8e_iso_8859_15_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_16 = (TUTF8encoder) tutf8e_iso_8859_16_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_2 = (TUTF8encoder) tutf8e_iso_8859_2_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_3 = (TUTF8encoder) tutf8e_iso_8859_3_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_4 = (TUTF8encoder) tutf8e_iso_8859_4_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_5 = (TUTF8encoder) tutf8e_iso_8859_5_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_6 = (TUTF8encoder) tutf8e_iso_8859_6_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_7 = (TUTF8encoder) tutf8e_iso_8859_7_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_8 = (TUTF8encoder) tutf8e_iso_8859_8_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_iso_8859_9 = (TUTF8encoder) tutf8e_iso_8859_9_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1250 = (TUTF8encoder) tutf8e_windows_1250_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1251 = (TUTF8encoder) tutf8e_windows_1251_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1252 = (TUTF8encoder) tutf8e_windows_1252_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1253 = (TUTF8encoder) tutf8e_windows_1253_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1254 = (TUTF8encoder) tutf8e_windows_1254_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1255 = (TUTF8encoder) tutf8e_windows_1255_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1256 = (TUTF8encoder) tutf8e_windows_1256_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1257 = (TUTF8encoder) tutf8e_windows_1257_utf8;
|
||||
const TUTF8encoder tutf8e_encoder_windows_1258 = (TUTF8encoder) tutf8e_windows_1258_utf8;
|
||||
|
||||
TUTF8encoder tutf8e_encoder(const char *encoding)
|
||||
{
|
||||
if (!strcmp(encoding, "iso-8859-1")) return tutf8e_encoder_iso_8859_1;
|
||||
if (!strcmp(encoding, "iso-8859-10")) return tutf8e_encoder_iso_8859_10;
|
||||
if (!strcmp(encoding, "iso-8859-11")) return tutf8e_encoder_iso_8859_11;
|
||||
if (!strcmp(encoding, "iso-8859-13")) return tutf8e_encoder_iso_8859_13;
|
||||
if (!strcmp(encoding, "iso-8859-14")) return tutf8e_encoder_iso_8859_14;
|
||||
if (!strcmp(encoding, "iso-8859-15")) return tutf8e_encoder_iso_8859_15;
|
||||
if (!strcmp(encoding, "iso-8859-16")) return tutf8e_encoder_iso_8859_16;
|
||||
if (!strcmp(encoding, "iso-8859-2")) return tutf8e_encoder_iso_8859_2;
|
||||
if (!strcmp(encoding, "iso-8859-3")) return tutf8e_encoder_iso_8859_3;
|
||||
if (!strcmp(encoding, "iso-8859-4")) return tutf8e_encoder_iso_8859_4;
|
||||
if (!strcmp(encoding, "iso-8859-5")) return tutf8e_encoder_iso_8859_5;
|
||||
if (!strcmp(encoding, "iso-8859-6")) return tutf8e_encoder_iso_8859_6;
|
||||
if (!strcmp(encoding, "iso-8859-7")) return tutf8e_encoder_iso_8859_7;
|
||||
if (!strcmp(encoding, "iso-8859-8")) return tutf8e_encoder_iso_8859_8;
|
||||
if (!strcmp(encoding, "iso-8859-9")) return tutf8e_encoder_iso_8859_9;
|
||||
if (!strcmp(encoding, "windows-1250")) return tutf8e_encoder_windows_1250;
|
||||
if (!strcmp(encoding, "windows-1251")) return tutf8e_encoder_windows_1251;
|
||||
if (!strcmp(encoding, "windows-1252")) return tutf8e_encoder_windows_1252;
|
||||
if (!strcmp(encoding, "windows-1253")) return tutf8e_encoder_windows_1253;
|
||||
if (!strcmp(encoding, "windows-1254")) return tutf8e_encoder_windows_1254;
|
||||
if (!strcmp(encoding, "windows-1255")) return tutf8e_encoder_windows_1255;
|
||||
if (!strcmp(encoding, "windows-1256")) return tutf8e_encoder_windows_1256;
|
||||
if (!strcmp(encoding, "windows-1257")) return tutf8e_encoder_windows_1257;
|
||||
if (!strcmp(encoding, "windows-1258")) return tutf8e_encoder_windows_1258;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
138
src/quickjs/tutf8e.h
Normal file
138
src/quickjs/tutf8e.h
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
#ifndef TUTF8E_H
|
||||
#define TUTF8E_H
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdint.h> /* uint16_t */
|
||||
|
||||
/*************** Internal API ***************/
|
||||
|
||||
/* NUL-terminated C-string API */
|
||||
|
||||
extern int tutf8e_string_length(const uint16_t *table, const char *input, const char *invalid, size_t *input_length, size_t *output_length);
|
||||
extern int tutf8e_string_encode(const uint16_t *table, const char *input, const char *invalid, char *output, size_t *output_length);
|
||||
|
||||
/* Known-length buffer API */
|
||||
|
||||
extern int tutf8e_buffer_length(const uint16_t *table, const char *input, size_t input_length, const char *invalid, size_t *output_length);
|
||||
extern int tutf8e_buffer_encode(const uint16_t *table, const char *input, size_t input_length, const char *invalid, char *output, size_t *output_length);
|
||||
|
||||
/*************** Public API ***************/
|
||||
|
||||
/* Opaque handle type */
|
||||
|
||||
typedef void *TUTF8encoder;
|
||||
|
||||
/* Query encoder by name */
|
||||
|
||||
extern TUTF8encoder tutf8e_encoder(const char *encoding);
|
||||
|
||||
#define TUTF8E_OK 0 /* Success */
|
||||
#define TUTF8E_INVALID 1 /* Invalid input character */
|
||||
#define TUTF8E_TOOLONG 2 /* Insufficient output buffer */
|
||||
|
||||
/*
|
||||
* tutf8e_encoder_string_length
|
||||
*
|
||||
* Determine the length of input and UTF8 encoded output of NUL-terminated string
|
||||
* Performance: single pass O(n)
|
||||
*
|
||||
* output NUL terminator not counted
|
||||
*
|
||||
* - TUTF8E_INVALID if input character is not convertable
|
||||
* - TUTF8E_OK for success
|
||||
*/
|
||||
|
||||
static inline int tutf8e_encoder_string_length(const TUTF8encoder encoder, const char *input, const char *invalid, size_t *input_length, size_t *output_length)
|
||||
{
|
||||
return tutf8e_string_length((const uint16_t *) encoder, input, invalid, input_length, output_length);
|
||||
}
|
||||
|
||||
/*
|
||||
* tutf8e_encoder_string_encode
|
||||
*
|
||||
* UTF8 encode NUL-terminated string
|
||||
* Performance: two pass O(n)
|
||||
*
|
||||
* output string is NUL terminated
|
||||
* output_length is output buffer size for input
|
||||
* output_length is encoded length for output, including NUL
|
||||
*
|
||||
* - TUTF8E_TOOLONG if output buffer insuficient
|
||||
* - TUTF8E_INVALID if input character is not convertable
|
||||
* - TUTF8E_OK for success
|
||||
*/
|
||||
|
||||
static inline int tutf8e_encoder_string_encode(const TUTF8encoder encoder, const char *input, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_string_encode((const uint16_t *) encoder, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
/* Known-length buffer API */
|
||||
|
||||
/*
|
||||
* tutf8e_encoder_buffer_length
|
||||
*
|
||||
* Determine the length of input and UTF8 encoded output of string
|
||||
* Performance: single pass O(n)
|
||||
*
|
||||
* output NUL terminator not counted
|
||||
*
|
||||
* - TUTF8E_INVALID if input character is not convertable
|
||||
* - TUTF8E_OK for success
|
||||
*/
|
||||
|
||||
static inline int tutf8e_encoder_buffer_length(const TUTF8encoder encoder, const char *input, const char *invalid, size_t input_length, size_t *length)
|
||||
{
|
||||
return tutf8e_buffer_length((const uint16_t *) encoder, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* tutf8e_encoder_buffer_encode
|
||||
*
|
||||
* UTF8 encode string
|
||||
* Performance: two pass O(n)
|
||||
*
|
||||
* output string is not NUL terminated
|
||||
*
|
||||
* output_length is output buffer size for input
|
||||
* output_length is encoded length for output
|
||||
*
|
||||
* - TUTF8E_TOOLONG if output buffer insuficient
|
||||
* - TUTF8E_INVALID if input character is not convertable
|
||||
* - TUTF8E_OK for success
|
||||
*/
|
||||
|
||||
static inline int tutf8e_encoder_buffer_encode(const TUTF8encoder encoder, const char *input, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_buffer_encode((const uint16_t *) encoder, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
/* Supported encoders */
|
||||
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_1;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_10;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_11;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_13;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_14;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_15;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_16;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_2;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_3;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_4;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_5;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_6;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_7;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_8;
|
||||
extern const TUTF8encoder tutf8e_encoder_iso_8859_9;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1250;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1251;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1252;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1253;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1254;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1255;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1256;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1257;
|
||||
extern const TUTF8encoder tutf8e_encoder_windows_1258;
|
||||
|
||||
#endif
|
||||
3234
src/quickjs/utils.c
Normal file
3234
src/quickjs/utils.c
Normal file
File diff suppressed because one or more lines are too long
1154
src/quickjs/utils.h
Normal file
1154
src/quickjs/utils.h
Normal file
File diff suppressed because it is too large
Load Diff
299
src/quickjs/vector.c
Normal file
299
src/quickjs/vector.c
Normal file
@@ -0,0 +1,299 @@
|
||||
#include "vector.h"
|
||||
#include "buffer-utils.h"
|
||||
#include "utils.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* \addtogroup vector
|
||||
* @{
|
||||
*/
|
||||
|
||||
realloc2_helper(vector_realloc);
|
||||
js_realloc_helper(vector_js_realloc);
|
||||
js_realloc_rt_helper(vector_js_realloc_rt);
|
||||
|
||||
#define HAVE_UINT128
|
||||
|
||||
#if(defined(__GNUC__) && (__GNUC__ >= 5)) || defined(HAVE__BUILTIN_MUL_OVERFLOW)
|
||||
|
||||
/*#elif defined(HAVE_UINT128)
|
||||
#warning No umult64 implementation*/
|
||||
#else
|
||||
int
|
||||
umult64(uint64_t a, uint64_t b, uint64_t* c) {
|
||||
uint32_t ahi = a >> 32;
|
||||
uint32_t alo = (a & 0xffffffff);
|
||||
uint32_t bhi = b >> 32;
|
||||
uint32_t blo = (b & 0xffffffff);
|
||||
|
||||
if(ahi && bhi)
|
||||
return 0;
|
||||
|
||||
a = (uint64_t)(ahi)*blo + (uint64_t)(alo)*bhi;
|
||||
|
||||
if(a <= 0xffffffff) {
|
||||
uint64_t x = (uint64_t)(alo)*blo;
|
||||
if(x + (a << 32) < x)
|
||||
return 0;
|
||||
*c = x + (a << 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
vector_free(Vector* vec) {
|
||||
if(vec->data)
|
||||
vec->realloc_func(vec->opaque, vec->data, 0);
|
||||
|
||||
vec->data = 0;
|
||||
vec->capacity = vec->size = 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
vector_indexof(const Vector* vec, size_t elsz, void* ptr) {
|
||||
if(ptr < vector_begin(vec) || ptr > vector_back(vec, elsz))
|
||||
return -1;
|
||||
|
||||
return ((size_t)vector_begin(vec) - (size_t)ptr) / elsz;
|
||||
}
|
||||
|
||||
int32_t
|
||||
vector_find(const Vector* vec, size_t elsz, void* ptr) {
|
||||
void* x;
|
||||
int32_t i = 0;
|
||||
|
||||
if(vector_empty(vec))
|
||||
return -1;
|
||||
|
||||
vector_foreach(vec, elsz, x) {
|
||||
if(!memcmp(x, ptr, elsz))
|
||||
return i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
vector_finds(const Vector* vec, const char* str) {
|
||||
char** x;
|
||||
int32_t i = 0;
|
||||
|
||||
if(vector_empty(vec))
|
||||
return -1;
|
||||
|
||||
vector_foreach_t(vec, x) {
|
||||
if(!strcmp(*x, str))
|
||||
return i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
vector_counts(const Vector* vec, const char* str) {
|
||||
char** x;
|
||||
int count = 0;
|
||||
|
||||
if(vector_empty(vec))
|
||||
return 0;
|
||||
|
||||
vector_foreach_t(vec, x) if(!strcmp(*x, str))++ count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void*
|
||||
vector_put(Vector* vec, const void* bytes, size_t len) {
|
||||
size_t pos;
|
||||
|
||||
if(!len)
|
||||
return 0;
|
||||
|
||||
pos = vec->size;
|
||||
|
||||
if(!vector_allocate(vec, 1, vec->size + len - 1))
|
||||
return 0;
|
||||
|
||||
memcpy(vec->data + pos, bytes, len);
|
||||
|
||||
return vec->data + pos;
|
||||
}
|
||||
|
||||
void __attribute__((format(printf, 2, 3))) vector_printf(Vector* vec, const char* fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[128];
|
||||
size_t len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(len < sizeof(buf)) {
|
||||
vector_put(vec, buf, len);
|
||||
} else {
|
||||
size_t pos = vec->size;
|
||||
|
||||
if(!vector_allocate(vec, 1, vec->size + len))
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf((char*)(vec->data + pos), len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
vec->size += len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vector_diff(void* a, size_t m, void* b, size_t n, size_t elsz, Vector* out) {
|
||||
char* ptr = a;
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < m; i++) {
|
||||
if(array_contains(b, n, elsz, ptr))
|
||||
vector_put(out, ptr, elsz);
|
||||
|
||||
ptr += elsz;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vector_symmetricdiff(void* a, size_t m, void* b, size_t n, size_t elsz, Vector* out_a, Vector* out_b) {
|
||||
vector_diff(a, m, b, n, elsz, out_a);
|
||||
vector_diff(b, n, a, m, elsz, out_b);
|
||||
}
|
||||
|
||||
void
|
||||
vector_intersection(void* a, size_t m, void* b, size_t n, size_t elsz, Vector* out) {
|
||||
size_t i, j = 0, k = 0;
|
||||
|
||||
for(i = 0; i < m + n; i++) {
|
||||
void* aptr = (char*)a + j * elsz;
|
||||
void* bptr = (char*)b + k * elsz;
|
||||
int r = memcmp(aptr, bptr, elsz);
|
||||
|
||||
if(r < 0 && j < m) {
|
||||
j++;
|
||||
} else if(r > 0 && k < n) {
|
||||
k++;
|
||||
} else if(r == 0 && j < m && k < n) {
|
||||
vector_put(out, aptr, elsz);
|
||||
j++;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vector_copy(Vector* dst, const Vector* src) {
|
||||
dst->realloc_func = src->realloc_func;
|
||||
dst->opaque = src->opaque;
|
||||
dst->data = 0;
|
||||
dst->capacity = 0;
|
||||
|
||||
if(!dbuf_realloc(&dst->dbuf, src->size)) {
|
||||
memcpy(dst->data, src->data, src->size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vector_fwrite(const Vector* vec, size_t start, FILE* out) {
|
||||
size_t i, len = vector_size(vec, sizeof(char*));
|
||||
|
||||
for(i = start; i < len; i++) {
|
||||
const char* str = *(char**)vector_at(vec, sizeof(char*), i);
|
||||
|
||||
fputs(i > start ? "',\n '" : "[\n '", out);
|
||||
fputs(str, out);
|
||||
|
||||
if(i + 1 == len)
|
||||
fputs("'\n]", out);
|
||||
}
|
||||
|
||||
fflush(out);
|
||||
}
|
||||
|
||||
BOOL
|
||||
vector_grow(Vector* vec, size_t elsz, int32_t len) {
|
||||
uint64_t need;
|
||||
|
||||
if(len < 0)
|
||||
return FALSE;
|
||||
|
||||
if(!umult64(elsz, len, &need))
|
||||
return FALSE;
|
||||
|
||||
if(need <= vec->size)
|
||||
return FALSE;
|
||||
|
||||
vec->data = vec->realloc_func(vec->opaque, vec->data, need);
|
||||
vec->size = need;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char*
|
||||
vector_pushstring(Vector* vec, const char* str) {
|
||||
char* s;
|
||||
|
||||
if((s = vec->realloc_func(vec->opaque, 0, strlen(str) + 1))) {
|
||||
strcpy(s, str);
|
||||
vector_push(vec, s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char*
|
||||
vector_pushstringlen(Vector* vec, const char* str, size_t len) {
|
||||
char* s;
|
||||
|
||||
if((s = vec->realloc_func(vec->opaque, 0, len + 1))) {
|
||||
strncpy(s, str, len);
|
||||
s[len] = '\0';
|
||||
vector_push(vec, s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
vector_clearstrings(Vector* vec) {
|
||||
char** ptr;
|
||||
|
||||
vector_foreach_t(vec, ptr) free(*ptr);
|
||||
vector_clear(vec);
|
||||
}
|
||||
|
||||
void
|
||||
vector_dumpstrings(const Vector* vec, DynBuf* buf) {
|
||||
size_t i, len = vector_size(vec, sizeof(char*));
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
const char* str = *(char**)vector_at(vec, sizeof(char*), i);
|
||||
|
||||
dbuf_putstr(buf, i > 0 ? "',\n '" : "[\n '");
|
||||
dbuf_putstr(buf, str);
|
||||
|
||||
if(i + 1 == len)
|
||||
dbuf_putstr(buf, "'\n]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
242
src/quickjs/vector.h
Normal file
242
src/quickjs/vector.h
Normal file
@@ -0,0 +1,242 @@
|
||||
#ifndef VECTOR_H
|
||||
#define VECTOR_H
|
||||
|
||||
#include <quickjs.h>
|
||||
#include <cutils.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* \defgroup vector vector: Vector implementation
|
||||
* @{
|
||||
*/
|
||||
#define roundto(n, mod) (((n) = (((n) + (mod)-1))), n = (n) - ((uint64_t)(n) % (uint64_t)(mod)))
|
||||
|
||||
typedef union Vector {
|
||||
DynBuf dbuf;
|
||||
struct {
|
||||
char* data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
BOOL error;
|
||||
DynBufReallocFunc* realloc_func;
|
||||
void* opaque;
|
||||
};
|
||||
} Vector;
|
||||
|
||||
#define VECTOR_INIT() \
|
||||
{ \
|
||||
{ 0, 0, 0, 0, &vector_realloc, 0 } \
|
||||
}
|
||||
|
||||
#define vector_init(vec, ctx) dbuf_init2(&((vec)->dbuf), (ctx), (DynBufReallocFunc*)&vector_js_realloc)
|
||||
#define vector_init_rt(vec, rt) dbuf_init2(&((vec)->dbuf), (rt), (DynBufReallocFunc*)&vector_js_realloc_rt)
|
||||
#define VECTOR(ctx) \
|
||||
(Vector) { \
|
||||
{ 0, 0, 0, 0, (DynBufReallocFunc*)&vector_js_realloc, ctx } \
|
||||
}
|
||||
#define VECTOR_RT(rt) \
|
||||
(Vector) { \
|
||||
{ 0, 0, 0, 0, (DynBufReallocFunc*)&vector_js_realloc_rt, rt } \
|
||||
}
|
||||
|
||||
#define vector_begin(vec) ((void*)((vec)->data))
|
||||
#define vector_end(vec) ((void*)((vec)->data + (vec)->size))
|
||||
|
||||
#define vector_begin_t(vec, t) ((t*)vector_begin(vec))
|
||||
#define vector_end_t(vec, t) ((t*)vector_end(vec))
|
||||
|
||||
#define vector_foreach_t(a, p) for((p) = vector_begin(a); (p) != vector_end(a); ++(p))
|
||||
#define vector_foreach(a, msz, p) for((p) = vector_begin(a); (char*)(p) != (char*)vector_end(a); (p) = (void*)(((char*)p) + msz))
|
||||
|
||||
#if(defined(__GNUC__) && (__GNUC__ >= 5)) || defined(HAVE__BUILTIN_MUL_OVERFLOW)
|
||||
static inline int
|
||||
umult64(uint64_t a, uint64_t b, uint64_t* c) {
|
||||
return !__builtin_mul_overflow(a, b, c);
|
||||
}
|
||||
#elif defined(HAVE_UINT128)
|
||||
static inline int
|
||||
umult64(uint64_t a, uint64_t b, uint64_t* c) {
|
||||
__uint128_t x = ((__uint128_t)a) * b;
|
||||
if((*c = (uint64_t)x) != x)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
extern int umult64(uint64_t a, uint64_t b, uint64_t* c);
|
||||
#endif
|
||||
|
||||
void* vector_realloc(void*, void* ptr, size_t size);
|
||||
void* vector_js_realloc(JSContext* ctx, void* ptr, size_t size);
|
||||
void* vector_js_realloc_rt(JSRuntime* rt, void* ptr, size_t size);
|
||||
int32_t vector_indexof(const Vector* vec, size_t elsz, void* ptr);
|
||||
int32_t vector_find(const Vector* vec, size_t elsz, void* ptr);
|
||||
int32_t vector_finds(const Vector* vec, const char* str);
|
||||
int vector_counts(const Vector* vec, const char* str);
|
||||
void* vector_put(Vector* vec, const void* bytes, size_t len);
|
||||
void vector_free(Vector* vec);
|
||||
void vector_printf(Vector* vec, const char*, ...);
|
||||
void vector_intersection(void*, size_t, void*, size_t, size_t, Vector*);
|
||||
void vector_diff(void*, size_t, void*, size_t, size_t, Vector*);
|
||||
void vector_symmetricdiff(void*, size_t, void*, size_t, size_t, Vector*, Vector*);
|
||||
int vector_copy(Vector* dst, const Vector* src);
|
||||
void vector_fwrite(const Vector*, size_t, FILE* out);
|
||||
BOOL vector_grow(Vector* vec, size_t elsz, int32_t len);
|
||||
char* vector_pushstring(Vector*, const char*);
|
||||
char* vector_pushstringlen(Vector*, const char*, size_t);
|
||||
void vector_clearstrings(Vector*);
|
||||
void vector_dumpstrings(const Vector*, DynBuf* buf);
|
||||
|
||||
#define vector_push(vec, elem) vector_put((vec), &(elem), sizeof((elem)))
|
||||
|
||||
static inline void*
|
||||
vector_allocate(Vector* vec, size_t elsz, int32_t pos) {
|
||||
uint64_t need;
|
||||
size_t capacity;
|
||||
if(pos < 0)
|
||||
return 0;
|
||||
if(!umult64(elsz, pos + 1, &need))
|
||||
return 0;
|
||||
if(need > vec->size) {
|
||||
capacity = vec->capacity;
|
||||
if(need > capacity) {
|
||||
if(elsz < 8)
|
||||
roundto(need, 1000);
|
||||
else
|
||||
roundto(need, 8000);
|
||||
assert(need >= 1000);
|
||||
if(dbuf_realloc(&vec->dbuf, need))
|
||||
return 0;
|
||||
if(vec->capacity > capacity)
|
||||
memset(vec->data + capacity, 0, vec->capacity - capacity);
|
||||
}
|
||||
vec->size = ((uint32_t)pos + 1) * elsz;
|
||||
}
|
||||
return vec->data + (uint32_t)pos * elsz;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
vector_shrink(Vector* vec, size_t elsz, int32_t len) {
|
||||
uint64_t need;
|
||||
if(len < 0)
|
||||
return FALSE;
|
||||
if(!umult64(elsz, len, &need))
|
||||
return FALSE;
|
||||
if(need > vec->size)
|
||||
return FALSE;
|
||||
vec->size = need;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
vector_at(const Vector* vec, size_t elsz, int32_t pos) {
|
||||
uint64_t offs;
|
||||
if(pos < 0)
|
||||
return 0;
|
||||
if(!umult64(elsz, pos, &offs))
|
||||
return 0;
|
||||
if(offs >= vec->size)
|
||||
return 0;
|
||||
return vec->data + offs;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
vector_size(const Vector* vec, size_t elsz) {
|
||||
return vec->size / elsz;
|
||||
}
|
||||
|
||||
static inline int
|
||||
vector_empty(const Vector* vec) {
|
||||
return vec->size == 0;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
vector_front(const Vector* vec, size_t elsz) {
|
||||
assert(vec->size >= elsz);
|
||||
return vec->data;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
vector_back(const Vector* vec, size_t elsz) {
|
||||
uint32_t n = vector_size(vec, elsz);
|
||||
assert(n);
|
||||
return vector_at(vec, elsz, n - 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_clear(Vector* vec) {
|
||||
vec->size = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_freestrings(Vector* vec) {
|
||||
vector_clearstrings(vec);
|
||||
vector_free(vec);
|
||||
}
|
||||
|
||||
static inline void*
|
||||
vector_emplace(Vector* vec, size_t elsz) {
|
||||
uint32_t n = vector_size(vec, elsz);
|
||||
return vector_allocate(vec, elsz, n);
|
||||
}
|
||||
|
||||
static inline void*
|
||||
vector_pop(Vector* vec, size_t elsz) {
|
||||
uint32_t n = vector_size(vec, elsz);
|
||||
assert(n);
|
||||
vector_shrink(vec, elsz, n - 1);
|
||||
return vector_end(vec);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_puts(Vector* vec, const char* str) {
|
||||
vector_put(vec, str, strlen(str));
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_putc(Vector* vec, char c) {
|
||||
vector_put(vec, &c, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_put0(Vector* vec) {
|
||||
vector_put(vec, "\0", 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_putlong(Vector* vec, long l, int radix) {
|
||||
char buf[64];
|
||||
size_t len = snprintf(buf, sizeof(buf), radix == 16 ? "%lx" : radix == 8 ? "%lo" : "%lu", l);
|
||||
vector_put(vec, buf, len);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_putptr(Vector* vec, void* p) {
|
||||
vector_put(vec, &p, sizeof(p));
|
||||
}
|
||||
|
||||
void quicksort_r(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* ptr);
|
||||
|
||||
static inline void
|
||||
vector_sort(Vector* vec, size_t elsz, int (*compar)(const void*, const void*, void*), void* arg) {
|
||||
quicksort_r(vector_begin(vec), vector_size(vec, elsz), elsz, compar, arg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vector_catlong(Vector* vec, long l, int radix) {
|
||||
char buf[64];
|
||||
size_t len = snprintf(buf, sizeof(buf), radix == 16 ? "%lx" : radix == 8 ? "%lo" : "%lu", l);
|
||||
vector_put(vec, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(VECTOR_H) */
|
||||
27
src/quickjs/windows_1250.h
Normal file
27
src/quickjs/windows_1250.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_WINDOWS_1250_H
|
||||
#define TUTF8E_WINDOWS_1250_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_windows_1250_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_windows_1250, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1250_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_windows_1250, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1250_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_windows_1250, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1250_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_windows_1250, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
src/quickjs/windows_1251.h
Normal file
27
src/quickjs/windows_1251.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef TUTF8E_WINDOWS_1251_H
|
||||
#define TUTF8E_WINDOWS_1251_H
|
||||
|
||||
#include <tutf8e.h>
|
||||
|
||||
static inline int tutf8e_windows_1251_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_length(tutf8e_encoder_windows_1251, input, input_length, invalid, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1251_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_string_encode(tutf8e_encoder_windows_1251, input, invalid, output, output_length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1251_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_length(tutf8e_encoder_windows_1251, input, input_length, invalid, length);
|
||||
}
|
||||
|
||||
static inline int tutf8e_windows_1251_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
|
||||
{
|
||||
return tutf8e_encoder_buffer_encode(tutf8e_encoder_windows_1251, input, input_length, invalid, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user