mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-22 10:06:39 +00:00
Compare commits
249 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ad6701757 | ||
|
|
176d7a1a0c | ||
|
|
ebfbb8a900 | ||
|
|
a94e8b9536 | ||
|
|
13910b23a4 | ||
|
|
6385c56832 | ||
|
|
3c879c7288 | ||
|
|
101ad3cb7e | ||
|
|
8cfee6c8a3 | ||
|
|
8673599d2b | ||
|
|
ec65e622aa | ||
|
|
65837f49e1 | ||
|
|
e5b21f026e | ||
|
|
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,8 +220,6 @@
|
||||
#define sfProvider ((7U << 16U) + 30U)
|
||||
#define sfMPTokenMetadata ((7U << 16U) + 31U)
|
||||
#define sfCredentialType ((7U << 16U) + 32U)
|
||||
#define sfJsonTxBody ((7U << 16U) + 33U)
|
||||
#define sfHookName ((7U << 16U) + 97U)
|
||||
#define sfRemarkValue ((7U << 16U) + 98U)
|
||||
#define sfRemarkName ((7U << 16U) + 99U)
|
||||
#define sfAccount ((8U << 16U) + 1U)
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROTOCOL_JSONTX_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_JSONTX_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace jsonTx {
|
||||
|
||||
/** Returns true iff the STObject declares a sfJsonTxBody field.
|
||||
|
||||
Used as a routing predicate: a transaction with this field present
|
||||
is claimed to use the "json-tx" signing scheme and must be validated
|
||||
through jsonTx::checkSignature / checkStructuralEquivalence. An
|
||||
empty body field still counts as "claimed json-tx" so the empty
|
||||
case is reported as a clean failure instead of silently falling
|
||||
back to the classical sig path.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
hasBody(STObject const& obj) noexcept;
|
||||
|
||||
/** Borrow a Slice over the ASCII body bytes.
|
||||
|
||||
Returns an empty slice if sfJsonTxBody is not present. The slice is
|
||||
valid for as long as the STObject the field belongs to.
|
||||
*/
|
||||
[[nodiscard]] Slice
|
||||
body(STObject const& obj);
|
||||
|
||||
/** SHA-512-Half of the body bytes.
|
||||
|
||||
This is the deterministic "ASCII signing digest" used by json-tx:
|
||||
the bytes the client sees as their message are hashed with SHA-512
|
||||
and truncated to 256 bits, the same digest convention rippled uses
|
||||
elsewhere. Returns a zero-valued hash if sfJsonTxBody is absent.
|
||||
*/
|
||||
[[nodiscard]] uint256
|
||||
bodyHash(STObject const& obj);
|
||||
|
||||
/** Signature check only: verify sfTxnSignature against the raw bytes of
|
||||
sfJsonTxBody using sfSigningPubKey.
|
||||
|
||||
The classical signing payload is NOT used. This is the json-tx
|
||||
analogue of STTx::checkSingleSign and is intended to be called from
|
||||
the same code path (e.g. STTx::checkSign).
|
||||
|
||||
Precondition: `stx` carries a non-empty sfJsonTxBody.
|
||||
*/
|
||||
[[nodiscard]] Expected<void, std::string>
|
||||
checkSignature(STTx const& stx);
|
||||
|
||||
/** Structural-equivalence check: parse sfJsonTxBody as JSON and confirm
|
||||
it serialises to the same canonical binary as the other structural
|
||||
fields of `stx` (excluding sfTxnSignature and sfJsonTxBody).
|
||||
|
||||
This is a local-check style rule -- it should run alongside
|
||||
passesLocalChecks, not inside the signature verification path.
|
||||
|
||||
Precondition: `stx` carries a non-empty sfJsonTxBody.
|
||||
*/
|
||||
[[nodiscard]] Expected<void, std::string>
|
||||
checkStructuralEquivalence(STTx const& stx);
|
||||
|
||||
} // namespace jsonTx
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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,13 +31,9 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FIX (HookMap, Supported::yes, VoteBehavior::DefaultYes)
|
||||
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(JsonTx, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DynamicNFT, Supported::no, VoteBehavior::DefaultNo)
|
||||
@@ -62,18 +55,18 @@ XRPL_FIX (FillOrKill, Supported::yes, VoteBehavior::DefaultYe
|
||||
XRPL_FEATURE(DID, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(AMM, 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)
|
||||
@@ -157,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
|
||||
|
||||
@@ -93,7 +93,7 @@ LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, ({
|
||||
*/
|
||||
LEDGER_ENTRY(ltHOOK_DEFINITION, 'D', HookDefinition, hook_definition, ({
|
||||
{sfHookHash, soeREQUIRED},
|
||||
{sfHookOn, soeOPTIONAL},
|
||||
{sfHookOn, soeREQUIRED},
|
||||
{sfHookOnIncoming, soeOPTIONAL},
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
@@ -396,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,11 +292,6 @@ TYPED_SFIELD(sfAssetClass, VL, 29)
|
||||
TYPED_SFIELD(sfProvider, VL, 30)
|
||||
TYPED_SFIELD(sfMPTokenMetadata, VL, 31)
|
||||
TYPED_SFIELD(sfCredentialType, VL, 32)
|
||||
// json-tx: the exact ASCII bytes the client signed; authoritative over
|
||||
// the classical signing payload when present. Not part of the classical
|
||||
// signing-payload computation (the bytes ARE the signing payload).
|
||||
TYPED_SFIELD(sfJsonTxBody, VL, 33, SField::sMD_Default, SField::notSigning)
|
||||
TYPED_SFIELD(sfHookName, VL, 97)
|
||||
TYPED_SFIELD(sfRemarkValue, VL, 98)
|
||||
TYPED_SFIELD(sfRemarkName, VL, 99)
|
||||
|
||||
@@ -346,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)
|
||||
@@ -393,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
|
||||
|
||||
@@ -550,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
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
[project]
|
||||
name = "json-tx"
|
||||
version = "0.0.1"
|
||||
description = "Prototype: canonical packing of (tx_json_str, signature) using ripple-binary-codec output as an LZ dictionary"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"xrpl-py>=4.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/json_tx"]
|
||||
|
||||
[tool.uv]
|
||||
dev-dependencies = [
|
||||
"pytest>=8.0",
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
from json_tx import patch # noqa: F401 -- side-effect: register JsonTxCompressed
|
||||
from json_tx.codec import (
|
||||
JSON_TX_FIELD,
|
||||
TAGS,
|
||||
canonical_json,
|
||||
compress_stream,
|
||||
decompress_stream,
|
||||
pack,
|
||||
pack_wire,
|
||||
unpack,
|
||||
unpack_wire,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"JSON_TX_FIELD",
|
||||
"TAGS",
|
||||
"canonical_json",
|
||||
"compress_stream",
|
||||
"decompress_stream",
|
||||
"pack",
|
||||
"pack_wire",
|
||||
"unpack",
|
||||
"unpack_wire",
|
||||
]
|
||||
@@ -1,79 +0,0 @@
|
||||
"""Demo: compare classical binary, raw JSON+sig, and JsonTxCompressed wire."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from xrpl.core.binarycodec import encode, encode_for_signing
|
||||
from xrpl.core.keypairs import (
|
||||
derive_classic_address,
|
||||
derive_keypair,
|
||||
generate_seed,
|
||||
sign,
|
||||
)
|
||||
|
||||
from json_tx import canonical_json, compress_stream, pack_wire, unpack_wire
|
||||
|
||||
|
||||
SAMPLE_TX = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "1000000",
|
||||
"Fee": "12",
|
||||
"Sequence": 1,
|
||||
"Flags": 2147483648,
|
||||
"SigningPubKey": "",
|
||||
}
|
||||
|
||||
|
||||
def _report(label: str, tx: dict, tx_json_str: str, priv: str) -> None:
|
||||
signature = bytes.fromhex(sign(tx_json_str.encode().hex(), priv))
|
||||
|
||||
# 1. Classical signed wire: full binary with TxnSignature (what xrpl does today).
|
||||
classical_signing = bytes.fromhex(encode_for_signing(tx))
|
||||
classical_signed_dict = dict(tx)
|
||||
classical_signed_dict["TxnSignature"] = signature.hex().upper()
|
||||
classical_wire = bytes.fromhex(encode(classical_signed_dict))
|
||||
|
||||
# 2. Naive JSON submission: tx_json_str + signature (what json-tx wants to replace).
|
||||
raw_json_plus_sig = len(tx_json_str) + len(signature)
|
||||
|
||||
# 3. json-tx wire: classical binary (ex TxnSignature) + JsonTxCompressed + TxnSignature.
|
||||
stream = compress_stream(tx_json_str, tx_json=tx)
|
||||
jsontx_wire = pack_wire(tx_json_str, signature)
|
||||
|
||||
print(f"\n== {label} ==")
|
||||
print(f" tx_json_str : {len(tx_json_str):5d} bytes")
|
||||
print(f" signature : {len(signature):5d} bytes")
|
||||
print(f" classical binary (signing payload): {len(classical_signing):5d} bytes")
|
||||
print(f" classical wire (binary + sig) : {len(classical_wire):5d} bytes <- today")
|
||||
print(f" raw JSON + sig (bytes sent) : {raw_json_plus_sig:5d} bytes <- naive json submit")
|
||||
print(f" JsonTxCompressed stream alone : {len(stream):5d} bytes [mode=0x{stream[0]:02x}]")
|
||||
print(f" json-tx wire (classical + stream) : {len(jsontx_wire):5d} bytes <- proposed")
|
||||
delta_vs_classical = len(jsontx_wire) - len(classical_wire)
|
||||
print(f" overhead vs classical wire : {delta_vs_classical:+5d} bytes")
|
||||
delta_vs_raw = len(jsontx_wire) - raw_json_plus_sig
|
||||
print(f" overhead vs raw JSON+sig : {delta_vs_raw:+5d} bytes")
|
||||
|
||||
recovered_tx, recovered_str, recovered_sig = unpack_wire(jsontx_wire)
|
||||
assert recovered_str == tx_json_str
|
||||
assert recovered_sig == signature
|
||||
assert recovered_tx == tx
|
||||
|
||||
|
||||
def main() -> None:
|
||||
seed = generate_seed()
|
||||
pub, priv = derive_keypair(seed)
|
||||
tx = dict(SAMPLE_TX)
|
||||
tx["Account"] = derive_classic_address(pub)
|
||||
tx["SigningPubKey"] = pub
|
||||
|
||||
_report("canonical tx_json_str (ordinal order, no whitespace)",
|
||||
tx, canonical_json(tx), priv)
|
||||
_report("non-canonical tx_json_str (insertion order + spaces)",
|
||||
tx, json.dumps(tx, separators=(", ", ": ")), priv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,384 +0,0 @@
|
||||
"""
|
||||
json-tx: field-aware packer for (tx_json_str, signature).
|
||||
|
||||
The ripple binary codec already decomposes a transaction into ordered
|
||||
(field_name, canonical_bytes) pairs. We reuse that as the dictionary.
|
||||
|
||||
Opcode stream:
|
||||
OP_FIELD i -> render field i exactly as it appears in tx_json_str
|
||||
OP_TAG t -> emit a glue snippet from TAGS (',', ':', '"', ...)
|
||||
OP_RAW n <bytes> -> n bytes of literal passthrough
|
||||
OP_END -> terminator
|
||||
|
||||
The stream is what gets stored in the `JsonTxCompressed` Blob field on
|
||||
the wire. The TxnSignature field still carries the ed25519/secp256k1
|
||||
signature, but that signature is now over the ASCII `tx_json_str`, not
|
||||
the classical signing payload.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from xrpl.core.binarycodec.definitions.field_instance import FieldInstance
|
||||
from xrpl.core.binarycodec.types.st_object import STObject
|
||||
|
||||
# `patch` registers the JsonTxCompressed field. Imported for its side effect.
|
||||
from json_tx import patch as _patch # noqa: F401
|
||||
|
||||
OP_FIELD = 0x01 # emit `"<name>":<canonical-value>` (tight pair)
|
||||
OP_TAG = 0x02 # emit a structural glue byte
|
||||
OP_RAW = 0x03 # length-prefixed literal bytes
|
||||
OP_NAME = 0x04 # emit `"<name>"` for field i
|
||||
OP_VALUE = 0x05 # emit canonical rendering of field i's value
|
||||
OP_END = 0x00
|
||||
|
||||
# Mode byte at the head of every stream.
|
||||
MODE_CANONICAL = 0x00 # body is an OP_* stream; tx_json_str reconstructs via dictionary
|
||||
MODE_VERBATIM = 0x01 # body is raw UTF-8 tx_json_str, length-prefixed
|
||||
|
||||
JSON_TX_FIELD = _patch.FIELD_NAME
|
||||
|
||||
# Structural glue. INVARIANT: no tag may end in `"` -- otherwise it would
|
||||
# eat the leading `"` of a field NAME/FIELD rendering and prevent re-align.
|
||||
# Order: longest first so the greedy matcher picks the most specific glue.
|
||||
TAGS: list[bytes] = [
|
||||
# comma-based field separators
|
||||
b",\n ",
|
||||
b",\n\t",
|
||||
b",\n ",
|
||||
b",\n ",
|
||||
b",\n",
|
||||
b", ",
|
||||
# colon-based name:value separators
|
||||
b": ",
|
||||
b": ",
|
||||
# leading indent after `{`
|
||||
b"\n ",
|
||||
b"\n\t",
|
||||
b"\n ",
|
||||
b"\n ",
|
||||
# single chars
|
||||
b"{",
|
||||
b"}",
|
||||
b"[",
|
||||
b"]",
|
||||
b",",
|
||||
b":",
|
||||
b'"',
|
||||
b" ",
|
||||
b"\n",
|
||||
b"\t",
|
||||
]
|
||||
|
||||
|
||||
# ---------- varint (unsigned LEB128) ----------
|
||||
|
||||
def _vw(n: int) -> bytes:
|
||||
if n < 0:
|
||||
raise ValueError("varint must be non-negative")
|
||||
out = bytearray()
|
||||
while True:
|
||||
b = n & 0x7F
|
||||
n >>= 7
|
||||
if n:
|
||||
out.append(b | 0x80)
|
||||
else:
|
||||
out.append(b)
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def _vr(buf: bytes, i: int) -> tuple[int, int]:
|
||||
n = 0
|
||||
shift = 0
|
||||
while True:
|
||||
b = buf[i]
|
||||
i += 1
|
||||
n |= (b & 0x7F) << shift
|
||||
if not (b & 0x80):
|
||||
return n, i
|
||||
shift += 7
|
||||
|
||||
|
||||
# ---------- canonical field extraction ----------
|
||||
|
||||
@dataclass
|
||||
class CanonField:
|
||||
name: str
|
||||
instance: FieldInstance
|
||||
canonical_bytes: bytes
|
||||
value: Any
|
||||
|
||||
|
||||
def _ordered_fields_from_dict(tx_json: dict, *, skip: set[str]) -> list[CanonField]:
|
||||
"""Serialize tx_json once through STObject, then re-parse to slice each field."""
|
||||
from xrpl.core.binarycodec.binary_wrappers.binary_parser import BinaryParser
|
||||
from xrpl.core.binarycodec.definitions import definitions
|
||||
|
||||
tx_for_enc = {k: v for k, v in tx_json.items() if k not in skip}
|
||||
st = STObject.from_value(tx_for_enc)
|
||||
blob = bytes(st)
|
||||
|
||||
parser = BinaryParser(blob.hex())
|
||||
total = len(parser)
|
||||
fields: list[CanonField] = []
|
||||
while not parser.is_end():
|
||||
start = total - len(parser)
|
||||
fi = parser.read_field()
|
||||
parser.read_field_value(fi)
|
||||
end = total - len(parser)
|
||||
fields.append(
|
||||
CanonField(
|
||||
name=fi.name,
|
||||
instance=definitions.get_field_instance(fi.name),
|
||||
canonical_bytes=blob[start:end],
|
||||
value=tx_json[fi.name],
|
||||
)
|
||||
)
|
||||
return fields
|
||||
|
||||
|
||||
def _render_name(name: str) -> bytes:
|
||||
"""Render `"Name"` including the enclosing double-quotes."""
|
||||
return json.dumps(name, separators=(",", ":")).encode()
|
||||
|
||||
|
||||
def _render_value(value: Any) -> bytes:
|
||||
"""Render the canonical JSON form of a value."""
|
||||
return json.dumps(value, separators=(",", ":")).encode()
|
||||
|
||||
|
||||
def _render_field_json(name: str, value: Any) -> bytes:
|
||||
"""Render one tight `"Name":<value>` pair -- no whitespace."""
|
||||
return _render_name(name) + b":" + _render_value(value)
|
||||
|
||||
|
||||
def canonical_json(tx_json: dict) -> str:
|
||||
"""Serialize tx_json with fields in canonical (ordinal) order.
|
||||
|
||||
The signed ASCII JSON must match this ordering so the opcode stream
|
||||
can walk fields in lock-step with the binary dictionary. Any field the
|
||||
codec does not recognize falls to the tail in insertion order.
|
||||
"""
|
||||
from xrpl.core.binarycodec.definitions import definitions
|
||||
|
||||
known, unknown = [], []
|
||||
for k, v in tx_json.items():
|
||||
try:
|
||||
fi = definitions.get_field_instance(k)
|
||||
known.append((fi.ordinal, k, v))
|
||||
except Exception:
|
||||
unknown.append((k, v))
|
||||
known.sort(key=lambda x: x[0])
|
||||
ordered = [(k, v) for _o, k, v in known] + unknown
|
||||
body = ",".join(
|
||||
f"{json.dumps(k, separators=(',', ':'))}:"
|
||||
f"{json.dumps(v, separators=(',', ':'))}"
|
||||
for k, v in ordered
|
||||
)
|
||||
return "{" + body + "}"
|
||||
|
||||
|
||||
# ---------- stream codec (opcode layer only) ----------
|
||||
|
||||
def compress_stream(tx_json_str: str, *, tx_json: dict | None = None) -> bytes:
|
||||
"""Encode tx_json_str using tx_json's fields as dictionary.
|
||||
|
||||
Opcodes (after the mode byte):
|
||||
OP_FIELD i -- `"Name":<canonical-value>` tight pair (no whitespace)
|
||||
OP_NAME i -- `"Name"` alone (enclosing quotes included)
|
||||
OP_VALUE i -- canonical rendering of field i's value
|
||||
OP_TAG t -- structural glue from TAGS
|
||||
OP_RAW n.. -- literal passthrough
|
||||
|
||||
The matcher at each cursor position tries, longest-match first:
|
||||
1. OP_FIELD against any unused field pair
|
||||
2. OP_NAME against any unused field name
|
||||
3. OP_VALUE against any unused field value
|
||||
4. OP_TAG
|
||||
5. OP_RAW (one byte, coalesced)
|
||||
|
||||
If the resulting OP stream is not shorter than a verbatim copy, we
|
||||
emit MODE_VERBATIM instead.
|
||||
"""
|
||||
if tx_json is None:
|
||||
tx_json = json.loads(tx_json_str)
|
||||
src = tx_json_str.encode()
|
||||
|
||||
fields = _ordered_fields_from_dict(
|
||||
tx_json, skip={"TxnSignature", JSON_TX_FIELD}
|
||||
)
|
||||
name_render = [_render_name(f.name) for f in fields]
|
||||
value_render = [_render_value(f.value) for f in fields]
|
||||
pair_render = [name_render[i] + b":" + value_render[i] for i in range(len(fields))]
|
||||
|
||||
unused_pair = set(range(len(fields)))
|
||||
unused_name = set(range(len(fields)))
|
||||
unused_value = set(range(len(fields)))
|
||||
|
||||
body = bytearray()
|
||||
raw_buf = bytearray()
|
||||
|
||||
def flush_raw() -> None:
|
||||
if raw_buf:
|
||||
body.append(OP_RAW)
|
||||
body.extend(_vw(len(raw_buf)))
|
||||
body.extend(raw_buf)
|
||||
raw_buf.clear()
|
||||
|
||||
def best_match(candidates: set[int], renders: list[bytes], at: int) -> tuple[int, int]:
|
||||
best_idx, best_len = -1, 0
|
||||
for idx in candidates:
|
||||
r = renders[idx]
|
||||
if len(r) > best_len and src.startswith(r, at):
|
||||
best_idx, best_len = idx, len(r)
|
||||
return best_idx, best_len
|
||||
|
||||
i = 0
|
||||
while i < len(src):
|
||||
# Try the tight FIELD match first -- cheapest per byte of output.
|
||||
idx, hit = best_match(unused_pair, pair_render, i)
|
||||
if idx >= 0:
|
||||
flush_raw()
|
||||
body.append(OP_FIELD)
|
||||
body.extend(_vw(idx))
|
||||
i += hit
|
||||
unused_pair.discard(idx)
|
||||
unused_name.discard(idx)
|
||||
unused_value.discard(idx)
|
||||
continue
|
||||
|
||||
# Then NAME (standalone), preferring longer names over shorter ones.
|
||||
idx, hit = best_match(unused_name, name_render, i)
|
||||
if idx >= 0:
|
||||
flush_raw()
|
||||
body.append(OP_NAME)
|
||||
body.extend(_vw(idx))
|
||||
i += hit
|
||||
unused_name.discard(idx)
|
||||
unused_pair.discard(idx) # no longer a "pair" candidate
|
||||
continue
|
||||
|
||||
# Then VALUE (standalone).
|
||||
idx, hit = best_match(unused_value, value_render, i)
|
||||
if idx >= 0:
|
||||
flush_raw()
|
||||
body.append(OP_VALUE)
|
||||
body.extend(_vw(idx))
|
||||
i += hit
|
||||
unused_value.discard(idx)
|
||||
unused_pair.discard(idx)
|
||||
continue
|
||||
|
||||
# Structural glue.
|
||||
tag_hit = -1
|
||||
for t_idx, tag in enumerate(TAGS):
|
||||
if src.startswith(tag, i):
|
||||
tag_hit = t_idx
|
||||
break
|
||||
if tag_hit >= 0:
|
||||
flush_raw()
|
||||
body.append(OP_TAG)
|
||||
body.extend(_vw(tag_hit))
|
||||
i += len(TAGS[tag_hit])
|
||||
continue
|
||||
|
||||
raw_buf.append(src[i])
|
||||
i += 1
|
||||
|
||||
flush_raw()
|
||||
body.append(OP_END)
|
||||
|
||||
op_form = bytes([MODE_CANONICAL]) + bytes(body)
|
||||
verbatim = bytes([MODE_VERBATIM]) + _vw(len(src)) + src
|
||||
return op_form if len(op_form) <= len(verbatim) else verbatim
|
||||
|
||||
|
||||
def decompress_stream(stream: bytes, tx_json_for_dict: dict) -> str:
|
||||
"""Rebuild tx_json_str from a json-tx stream + a parsed tx dict (dictionary source)."""
|
||||
mode = stream[0]
|
||||
i = 1
|
||||
if mode == MODE_VERBATIM:
|
||||
ln, i = _vr(stream, i)
|
||||
return stream[i : i + ln].decode()
|
||||
if mode != MODE_CANONICAL:
|
||||
raise ValueError(f"unknown json-tx stream mode 0x{mode:02x}")
|
||||
|
||||
fields = _ordered_fields_from_dict(
|
||||
tx_json_for_dict,
|
||||
skip={"TxnSignature", JSON_TX_FIELD},
|
||||
)
|
||||
name_render = [_render_name(f.name) for f in fields]
|
||||
value_render = [_render_value(f.value) for f in fields]
|
||||
pair_render = [name_render[i] + b":" + value_render[i] for i in range(len(fields))]
|
||||
|
||||
out = bytearray()
|
||||
while i < len(stream):
|
||||
op = stream[i]
|
||||
i += 1
|
||||
if op == OP_END:
|
||||
break
|
||||
if op == OP_FIELD:
|
||||
idx, i = _vr(stream, i)
|
||||
out += pair_render[idx]
|
||||
elif op == OP_NAME:
|
||||
idx, i = _vr(stream, i)
|
||||
out += name_render[idx]
|
||||
elif op == OP_VALUE:
|
||||
idx, i = _vr(stream, i)
|
||||
out += value_render[idx]
|
||||
elif op == OP_TAG:
|
||||
idx, i = _vr(stream, i)
|
||||
out += TAGS[idx]
|
||||
elif op == OP_RAW:
|
||||
ln, i = _vr(stream, i)
|
||||
out += stream[i : i + ln]
|
||||
i += ln
|
||||
else:
|
||||
raise ValueError(f"unknown opcode 0x{op:02x} at offset {i - 1}")
|
||||
return out.decode()
|
||||
|
||||
|
||||
# ---------- wire-tx pack/unpack (full binary with JsonTxCompressed) ----------
|
||||
|
||||
def pack_wire(tx_json_str: str, signature: bytes) -> bytes:
|
||||
"""Build the on-wire binary tx: canonical binary + JsonTxCompressed + TxnSignature.
|
||||
|
||||
`tx_json_str` is the exact ASCII bytes the client signed -- any field
|
||||
order / whitespace. `signature` is the raw signature over those bytes.
|
||||
"""
|
||||
from xrpl.core.binarycodec.main import encode
|
||||
|
||||
tx_json = json.loads(tx_json_str)
|
||||
stream = compress_stream(tx_json_str, tx_json=tx_json)
|
||||
wire_dict = dict(tx_json)
|
||||
wire_dict[JSON_TX_FIELD] = stream.hex().upper()
|
||||
wire_dict["TxnSignature"] = signature.hex().upper()
|
||||
return bytes.fromhex(encode(wire_dict))
|
||||
|
||||
|
||||
def unpack_wire(wire: bytes) -> tuple[dict, str, bytes]:
|
||||
"""Decode the wire tx back into (tx_json_dict, tx_json_str, signature)."""
|
||||
from xrpl.core.binarycodec.main import decode
|
||||
|
||||
decoded = decode(wire.hex().upper())
|
||||
stream_hex = decoded.pop(JSON_TX_FIELD)
|
||||
sig_hex = decoded.pop("TxnSignature")
|
||||
# The dictionary is the other fields of the tx, i.e. the decoded dict
|
||||
# minus the scaffolding keys (already removed above).
|
||||
tx_json_str = decompress_stream(bytes.fromhex(stream_hex), decoded)
|
||||
return json.loads(tx_json_str), tx_json_str, bytes.fromhex(sig_hex)
|
||||
|
||||
|
||||
# ---------- convenience ----------
|
||||
|
||||
def pack(tx_json: dict, signature: bytes) -> bytes:
|
||||
"""Alias for pack_wire for the common case."""
|
||||
return pack_wire(tx_json, signature)
|
||||
|
||||
|
||||
def unpack(wire: bytes) -> tuple[dict, bytes]:
|
||||
tx_json, _, sig = unpack_wire(wire)
|
||||
return tx_json, sig
|
||||
@@ -1,50 +0,0 @@
|
||||
"""Runtime monkey-patch: register a `JsonTxCompressed` Blob field.
|
||||
|
||||
Import this module (or call `register_json_tx_field()`) before using the
|
||||
binary codec so that a transaction dict containing `JsonTxCompressed`
|
||||
will serialize it as a Blob and parse it back out.
|
||||
|
||||
The field is intentionally `isSigningField=False` — the ASCII JSON is
|
||||
what TxnSignature signs, not the binary form, so this field must not
|
||||
participate in any classical signing payload.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from xrpl.core.binarycodec.definitions import definitions as _d
|
||||
from xrpl.core.binarycodec.definitions.field_header import FieldHeader
|
||||
from xrpl.core.binarycodec.definitions.field_info import FieldInfo
|
||||
|
||||
FIELD_NAME = "JsonTxCompressed"
|
||||
_TYPE_NAME = "Blob"
|
||||
|
||||
|
||||
def _pick_free_nth_for_type(type_name: str) -> int:
|
||||
"""Find an unused `nth` code within the given type so there's no header clash."""
|
||||
type_code = _d._TYPE_ORDINAL_MAP[type_name]
|
||||
taken = {
|
||||
h.field_code for h in _d._FIELD_HEADER_NAME_MAP if h.type_code == type_code
|
||||
}
|
||||
for n in range(1, 255):
|
||||
if n not in taken:
|
||||
return n
|
||||
raise RuntimeError(f"no free nth code for type {type_name}")
|
||||
|
||||
|
||||
def register_json_tx_field() -> None:
|
||||
if FIELD_NAME in _d._FIELD_INFO_MAP:
|
||||
return
|
||||
nth = _pick_free_nth_for_type(_TYPE_NAME)
|
||||
info = FieldInfo(
|
||||
nth=nth,
|
||||
is_variable_length_encoded=True,
|
||||
is_serialized=True,
|
||||
is_signing_field=False,
|
||||
type_name=_TYPE_NAME,
|
||||
)
|
||||
header = FieldHeader(_d._TYPE_ORDINAL_MAP[_TYPE_NAME], nth)
|
||||
_d._FIELD_INFO_MAP[FIELD_NAME] = info
|
||||
_d._FIELD_HEADER_NAME_MAP[header] = FIELD_NAME
|
||||
|
||||
|
||||
register_json_tx_field()
|
||||
@@ -1,63 +0,0 @@
|
||||
import json
|
||||
|
||||
from xrpl.core.keypairs import derive_classic_address, derive_keypair, generate_seed, sign
|
||||
|
||||
from json_tx import compress_stream, decompress_stream, pack_wire, unpack_wire
|
||||
|
||||
|
||||
def _signed(tx: dict) -> tuple[dict, str, bytes]:
|
||||
seed = generate_seed()
|
||||
pub, priv = derive_keypair(seed)
|
||||
tx = dict(tx)
|
||||
tx["Account"] = derive_classic_address(pub)
|
||||
tx["SigningPubKey"] = pub
|
||||
from json_tx import canonical_json
|
||||
tx_json_str = canonical_json(tx)
|
||||
sig = bytes.fromhex(sign(tx_json_str.encode().hex(), priv))
|
||||
return tx, tx_json_str, sig
|
||||
|
||||
|
||||
def test_wire_roundtrip():
|
||||
tx, tx_json_str, sig = _signed({
|
||||
"TransactionType": "Payment",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "1000000",
|
||||
"Fee": "12",
|
||||
"Sequence": 1,
|
||||
"Flags": 2147483648,
|
||||
})
|
||||
wire = pack_wire(tx_json_str, sig)
|
||||
recovered_tx, recovered_str, recovered_sig = unpack_wire(wire)
|
||||
assert recovered_str == tx_json_str
|
||||
assert recovered_sig == sig
|
||||
assert recovered_tx == tx
|
||||
|
||||
|
||||
def test_stream_roundtrip_direct():
|
||||
tx, tx_json_str, _ = _signed({
|
||||
"TransactionType": "Payment",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "2500000",
|
||||
"Fee": "15",
|
||||
"Sequence": 42,
|
||||
"Flags": 0,
|
||||
})
|
||||
stream = compress_stream(tx_json_str, tx_json=tx)
|
||||
rebuilt = decompress_stream(stream, tx)
|
||||
assert rebuilt == tx_json_str
|
||||
|
||||
|
||||
def test_raw_fallback_preserved():
|
||||
# Unusual whitespace -> RAW opcodes. Dictionary still reconstructs losslessly.
|
||||
tx = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "1",
|
||||
"Fee": "12",
|
||||
"Sequence": 1,
|
||||
"SigningPubKey": "",
|
||||
}
|
||||
odd = '{ "TransactionType" : "Payment" }'
|
||||
stream = compress_stream(odd, tx_json=tx)
|
||||
assert decompress_stream(stream, tx) == odd
|
||||
476
json-tx-py/uv.lock
generated
476
json-tx-py/uv.lock
generated
@@ -1,476 +0,0 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.10"
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.13.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "idna" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base58"
|
||||
version = "2.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7f/45/8ae61209bb9015f516102fa559a2914178da1d5868428bd86a1b4421141d/base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c", size = 6528, upload-time = "2021-10-30T22:12:17.858Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/45/ec96b29162a402fc4c1c5512d114d7b3787b9d1c2ec241d9568b4816ee23/base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2", size = 5621, upload-time = "2021-10-30T22:12:16.658Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2026.4.22"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deprecated"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "wrapt" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/49/85/12f0a49a7c4ffb70572b6c2ef13c90c88fd190debda93b23f026b25f9634/deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223", size = 2932523, upload-time = "2025-10-30T08:19:02.757Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecpy"
|
||||
version = "1.2.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/48/3f8c1a252e3a46fd04e6fabc5e11c933b9c39cf84edd4e7c906e29c23750/ECPy-1.2.5.tar.gz", hash = "sha256:9635cffb9b6ecf7fd7f72aea1665829ac74a1d272006d0057d45a621aae20228", size = 38458, upload-time = "2020-10-26T11:56:16.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/35/4a113189f7138035a21bd255d30dc7bffc77c942c93b7948d2eac2e22429/ECPy-1.2.5-py3-none-any.whl", hash = "sha256:559c92e42406d9d1a6b2b8fc26e6ad7bc985f33903b72f426a56cb1073a25ce3", size = 43075, upload-time = "2020-10-26T11:56:13.613Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.28.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.13"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "json-tx"
|
||||
version = "0.0.1"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "xrpl-py" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "xrpl-py", specifier = ">=4.0.0" }]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "pytest", specifier = ">=8.0" }]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycryptodome"
|
||||
version = "3.23.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886, upload-time = "2025-05-17T17:21:20.614Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151, upload-time = "2025-05-17T17:21:22.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461, upload-time = "2025-05-17T17:21:25.225Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440, upload-time = "2025-05-17T17:21:27.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005, upload-time = "2025-05-17T17:21:31.37Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "9.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-deprecated"
|
||||
version = "1.3.1.20260408"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1a/db/076de3e81b106d3cec17aec9640ab1b2d02f29bad441de280459c161ce65/types_deprecated-1.3.1.20260408.tar.gz", hash = "sha256:62d6a86d0cc754c14bb2de31162d069b1c6a07ce11ee65e5258f8f75308eb3a3", size = 8524, upload-time = "2026-04-08T04:26:39.894Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/53/d0/d3258379deb749d949c3c72313981c9d2cceec518b87dcf506f022f5d49f/types_deprecated-1.3.1.20260408-py3-none-any.whl", hash = "sha256:b64e1eab560d4fa9394a27a3099211344b0e0f2f3ac8026d825c86e70d65cdd5", size = 9079, upload-time = "2026-04-08T04:26:38.752Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
version = "16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021, upload-time = "2026-01-10T09:22:22.696Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320, upload-time = "2026-01-10T09:22:23.94Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815, upload-time = "2026-01-10T09:22:25.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054, upload-time = "2026-01-10T09:22:27.101Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565, upload-time = "2026-01-10T09:22:28.293Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848, upload-time = "2026-01-10T09:22:30.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249, upload-time = "2026-01-10T09:22:32.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685, upload-time = "2026-01-10T09:22:33.345Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340, upload-time = "2026-01-10T09:22:34.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022, upload-time = "2026-01-10T09:22:36.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319, upload-time = "2026-01-10T09:22:37.602Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631, upload-time = "2026-01-10T09:22:38.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870, upload-time = "2026-01-10T09:22:39.893Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361, upload-time = "2026-01-10T09:22:41.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615, upload-time = "2026-01-10T09:22:42.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246, upload-time = "2026-01-10T09:22:43.654Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684, upload-time = "2026-01-10T09:22:44.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968, upload-time = "2026-01-10T09:23:41.031Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735, upload-time = "2026-01-10T09:23:42.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "2.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/64/925f213fdcbb9baeb1530449ac71a4d57fc361c053d06bf78d0c5c7cd80c/wrapt-2.1.2.tar.gz", hash = "sha256:3996a67eecc2c68fd47b4e3c564405a5777367adfd9b8abb58387b63ee83b21e", size = 81678, upload-time = "2026-03-06T02:53:25.134Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c", size = 60669, upload-time = "2026-03-06T02:52:40.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/18/3f373935bc5509e7ac444c8026a56762e50c1183e7061797437ca96c12ce/wrapt-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a819e39017f95bf7aede768f75915635aa8f671f2993c036991b8d3bfe8dbb6f", size = 61603, upload-time = "2026-03-06T02:54:21.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/7a/32758ca2853b07a887a4574b74e28843919103194bb47001a304e24af62f/wrapt-2.1.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5681123e60aed0e64c7d44f72bbf8b4ce45f79d81467e2c4c728629f5baf06eb", size = 113632, upload-time = "2026-03-06T02:53:54.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/d5/eeaa38f670d462e97d978b3b0d9ce06d5b91e54bebac6fbed867809216e7/wrapt-2.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b8b28e97a44d21836259739ae76284e180b18abbb4dcfdff07a415cf1016c3e", size = 115644, upload-time = "2026-03-06T02:54:53.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/09/2a41506cb17affb0bdf9d5e2129c8c19e192b388c4c01d05e1b14db23c00/wrapt-2.1.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cef91c95a50596fcdc31397eb6955476f82ae8a3f5a8eabdc13611b60ee380ba", size = 112016, upload-time = "2026-03-06T02:54:43.274Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/15/0e6c3f5e87caadc43db279724ee36979246d5194fa32fed489c73643ba59/wrapt-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dad63212b168de8569b1c512f4eac4b57f2c6934b30df32d6ee9534a79f1493f", size = 114823, upload-time = "2026-03-06T02:54:29.392Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/b2/0ad17c8248f4e57bedf44938c26ec3ee194715f812d2dbbd9d7ff4be6c06/wrapt-2.1.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d307aa6888d5efab2c1cde09843d48c843990be13069003184b67d426d145394", size = 111244, upload-time = "2026-03-06T02:54:02.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/04/bcdba98c26f2c6522c7c09a726d5d9229120163493620205b2f76bd13c01/wrapt-2.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c87cf3f0c85e27b3ac7d9ad95da166bf8739ca215a8b171e8404a2d739897a45", size = 113307, upload-time = "2026-03-06T02:54:12.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/1b/5e2883c6bc14143924e465a6fc5a92d09eeabe35310842a481fb0581f832/wrapt-2.1.2-cp310-cp310-win32.whl", hash = "sha256:d1c5fea4f9fe3762e2b905fdd67df51e4be7a73b7674957af2d2ade71a5c075d", size = 57986, upload-time = "2026-03-06T02:54:26.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/5a/4efc997bccadd3af5749c250b49412793bc41e13a83a486b2b54a33e240c/wrapt-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:d8f7740e1af13dff2684e4d56fe604a7e04d6c94e737a60568d8d4238b9a0c71", size = 60336, upload-time = "2026-03-06T02:54:18Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/f5/a2bb833e20181b937e87c242645ed5d5aa9c373006b0467bfe1a35c727d0/wrapt-2.1.2-cp310-cp310-win_arm64.whl", hash = "sha256:1c6cc827c00dc839350155f316f1f8b4b0c370f52b6a19e782e2bda89600c7dc", size = 58757, upload-time = "2026-03-06T02:53:51.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/81/60c4471fce95afa5922ca09b88a25f03c93343f759aae0f31fb4412a85c7/wrapt-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96159a0ee2b0277d44201c3b5be479a9979cf154e8c82fa5df49586a8e7679bb", size = 60666, upload-time = "2026-03-06T02:52:58.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/be/80e80e39e7cb90b006a0eaf11c73ac3a62bbfb3068469aec15cc0bc795de/wrapt-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98ba61833a77b747901e9012072f038795de7fc77849f1faa965464f3f87ff2d", size = 61601, upload-time = "2026-03-06T02:53:00.487Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/be/d7c88cd9293c859fc74b232abdc65a229bb953997995d6912fc85af18323/wrapt-2.1.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:767c0dbbe76cae2a60dd2b235ac0c87c9cccf4898aef8062e57bead46b5f6894", size = 114057, upload-time = "2026-03-06T02:52:44.08Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/25/36c04602831a4d685d45a93b3abea61eca7fe35dab6c842d6f5d570ef94a/wrapt-2.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c691a6bc752c0cc4711cc0c00896fcd0f116abc253609ef64ef930032821842", size = 116099, upload-time = "2026-03-06T02:54:56.74Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/4e/98a6eb417ef551dc277bec1253d5246b25003cf36fdf3913b65cb7657a56/wrapt-2.1.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f3b7d73012ea75aee5844de58c88f44cf62d0d62711e39da5a82824a7c4626a8", size = 112457, upload-time = "2026-03-06T02:53:52.842Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/a6/a6f7186a5297cad8ec53fd7578533b28f795fdf5372368c74bd7e6e9841c/wrapt-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:577dff354e7acd9d411eaf4bfe76b724c89c89c8fc9b7e127ee28c5f7bcb25b6", size = 115351, upload-time = "2026-03-06T02:53:32.684Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/6f/06e66189e721dbebd5cf20e138acc4d1150288ce118462f2fcbff92d38db/wrapt-2.1.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3d7b6fd105f8b24e5bd23ccf41cb1d1099796524bcc6f7fbb8fe576c44befbc9", size = 111748, upload-time = "2026-03-06T02:53:08.455Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/43/4808b86f499a51370fbdbdfa6cb91e9b9169e762716456471b619fca7a70/wrapt-2.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:866abdbf4612e0b34764922ef8b1c5668867610a718d3053d59e24a5e5fcfc15", size = 113783, upload-time = "2026-03-06T02:53:02.02Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/2c/a3f28b8fa7ac2cefa01cfcaca3471f9b0460608d012b693998cd61ef43df/wrapt-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5a0a0a3a882393095573344075189eb2d566e0fd205a2b6414e9997b1b800a8b", size = 57977, upload-time = "2026-03-06T02:53:27.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/c3/2b1c7bd07a27b1db885a2fab469b707bdd35bddf30a113b4917a7e2139d2/wrapt-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:64a07a71d2730ba56f11d1a4b91f7817dc79bc134c11516b75d1921a7c6fcda1", size = 60336, upload-time = "2026-03-06T02:54:28.104Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/5c/76ece7b401b088daa6503d6264dd80f9a727df3e6042802de9a223084ea2/wrapt-2.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:b89f095fe98bc12107f82a9f7d570dc83a0870291aeb6b1d7a7d35575f55d98a", size = 58756, upload-time = "2026-03-06T02:53:16.319Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/b6/1db817582c49c7fcbb7df6809d0f515af29d7c2fbf57eb44c36e98fb1492/wrapt-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ff2aad9c4cda28a8f0653fc2d487596458c2a3f475e56ba02909e950a9efa6a9", size = 61255, upload-time = "2026-03-06T02:52:45.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/16/9b02a6b99c09227c93cd4b73acc3678114154ec38da53043c0ddc1fba0dc/wrapt-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6433ea84e1cfacf32021d2a4ee909554ade7fd392caa6f7c13f1f4bf7b8e8748", size = 61848, upload-time = "2026-03-06T02:53:48.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/aa/ead46a88f9ec3a432a4832dfedb84092fc35af2d0ba40cd04aea3889f247/wrapt-2.1.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c20b757c268d30d6215916a5fa8461048d023865d888e437fab451139cad6c8e", size = 121433, upload-time = "2026-03-06T02:54:40.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/9f/742c7c7cdf58b59085a1ee4b6c37b013f66ac33673a7ef4aaed5e992bc33/wrapt-2.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79847b83eb38e70d93dc392c7c5b587efe65b3e7afcc167aa8abd5d60e8761c8", size = 123013, upload-time = "2026-03-06T02:53:26.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/44/2c3dd45d53236b7ed7c646fcf212251dc19e48e599debd3926b52310fafb/wrapt-2.1.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f8fba1bae256186a83d1875b2b1f4e2d1242e8fac0f58ec0d7e41b26967b965c", size = 117326, upload-time = "2026-03-06T02:53:11.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/e2/b17d66abc26bd96f89dec0ecd0ef03da4a1286e6ff793839ec431b9fae57/wrapt-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e3d3b35eedcf5f7d022291ecd7533321c4775f7b9cd0050a31a68499ba45757c", size = 121444, upload-time = "2026-03-06T02:54:09.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/62/e2977843fdf9f03daf1586a0ff49060b1b2fc7ff85a7ea82b6217c1ae36e/wrapt-2.1.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6f2c5390460de57fa9582bc8a1b7a6c86e1a41dfad74c5225fc07044c15cc8d1", size = 116237, upload-time = "2026-03-06T02:54:03.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/dd/27fc67914e68d740bce512f11734aec08696e6b17641fef8867c00c949fc/wrapt-2.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7dfa9f2cf65d027b951d05c662cc99ee3bd01f6e4691ed39848a7a5fffc902b2", size = 120563, upload-time = "2026-03-06T02:53:20.412Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/9f/b750b3692ed2ef4705cb305bd68858e73010492b80e43d2a4faa5573cbe7/wrapt-2.1.2-cp312-cp312-win32.whl", hash = "sha256:eba8155747eb2cae4a0b913d9ebd12a1db4d860fc4c829d7578c7b989bd3f2f0", size = 58198, upload-time = "2026-03-06T02:53:37.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/b2/feecfe29f28483d888d76a48f03c4c4d8afea944dbee2b0cd3380f9df032/wrapt-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1c51c738d7d9faa0b3601708e7e2eda9bf779e1b601dce6c77411f2a1b324a63", size = 60441, upload-time = "2026-03-06T02:52:47.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/e1/e328f605d6e208547ea9fd120804fcdec68536ac748987a68c47c606eea8/wrapt-2.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:c8e46ae8e4032792eb2f677dbd0d557170a8e5524d22acc55199f43efedd39bf", size = 58836, upload-time = "2026-03-06T02:53:22.053Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/7a/d936840735c828b38d26a854e85d5338894cda544cb7a85a9d5b8b9c4df7/wrapt-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787fd6f4d67befa6fe2abdffcbd3de2d82dfc6fb8a6d850407c53332709d030b", size = 61259, upload-time = "2026-03-06T02:53:41.922Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/88/9a9b9a90ac8ca11c2fdb6a286cb3a1fc7dd774c00ed70929a6434f6bc634/wrapt-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4bdf26e03e6d0da3f0e9422fd36bcebf7bc0eeb55fdf9c727a09abc6b9fe472e", size = 61851, upload-time = "2026-03-06T02:52:48.672Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/a9/5b7d6a16fd6533fed2756900fc8fc923f678179aea62ada6d65c92718c00/wrapt-2.1.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bbac24d879aa22998e87f6b3f481a5216311e7d53c7db87f189a7a0266dafffb", size = 121446, upload-time = "2026-03-06T02:54:14.013Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/bb/34c443690c847835cfe9f892be78c533d4f32366ad2888972c094a897e39/wrapt-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16997dfb9d67addc2e3f41b62a104341e80cac52f91110dece393923c0ebd5ca", size = 123056, upload-time = "2026-03-06T02:54:10.829Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/b9/ff205f391cb708f67f41ea148545f2b53ff543a7ac293b30d178af4d2271/wrapt-2.1.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:162e4e2ba7542da9027821cb6e7c5e068d64f9a10b5f15512ea28e954893a267", size = 117359, upload-time = "2026-03-06T02:53:03.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/3d/1ea04d7747825119c3c9a5e0874a40b33594ada92e5649347c457d982805/wrapt-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f29c827a8d9936ac320746747a016c4bc66ef639f5cd0d32df24f5eacbf9c69f", size = 121479, upload-time = "2026-03-06T02:53:45.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/cc/ee3a011920c7a023b25e8df26f306b2484a531ab84ca5c96260a73de76c0/wrapt-2.1.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:a9dd9813825f7ecb018c17fd147a01845eb330254dff86d3b5816f20f4d6aaf8", size = 116271, upload-time = "2026-03-06T02:54:46.356Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/fd/e5ff7ded41b76d802cf1191288473e850d24ba2e39a6ec540f21ae3b57cb/wrapt-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f8dbdd3719e534860d6a78526aafc220e0241f981367018c2875178cf83a413", size = 120573, upload-time = "2026-03-06T02:52:50.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/c5/242cae3b5b080cd09bacef0591691ba1879739050cc7c801ff35c8886b66/wrapt-2.1.2-cp313-cp313-win32.whl", hash = "sha256:5c35b5d82b16a3bc6e0a04349b606a0582bc29f573786aebe98e0c159bc48db6", size = 58205, upload-time = "2026-03-06T02:53:47.494Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/69/c358c61e7a50f290958809b3c61ebe8b3838ea3e070d7aac9814f95a0528/wrapt-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f8bc1c264d8d1cf5b3560a87bbdd31131573eb25f9f9447bb6252b8d4c44a3a1", size = 60452, upload-time = "2026-03-06T02:53:30.038Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/66/c8a6fcfe321295fd8c0ab1bd685b5a01462a9b3aa2f597254462fc2bc975/wrapt-2.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:3beb22f674550d5634642c645aba4c72a2c66fb185ae1aebe1e955fae5a13baf", size = 58842, upload-time = "2026-03-06T02:52:52.114Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/55/9c7052c349106e0b3f17ae8db4b23a691a963c334de7f9dbd60f8f74a831/wrapt-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0fc04bc8664a8bc4c8e00b37b5355cffca2535209fba1abb09ae2b7c76ddf82b", size = 63075, upload-time = "2026-03-06T02:53:19.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/a8/ce7b4006f7218248dd71b7b2b732d0710845a0e49213b18faef64811ffef/wrapt-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a9b9d50c9af998875a1482a038eb05755dfd6fe303a313f6a940bb53a83c3f18", size = 63719, upload-time = "2026-03-06T02:54:33.452Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/e5/2ca472e80b9e2b7a17f106bb8f9df1db11e62101652ce210f66935c6af67/wrapt-2.1.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2d3ff4f0024dd224290c0eabf0240f1bfc1f26363431505fb1b0283d3b08f11d", size = 152643, upload-time = "2026-03-06T02:52:42.721Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/42/30f0f2cefca9d9cbf6835f544d825064570203c3e70aa873d8ae12e23791/wrapt-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3278c471f4468ad544a691b31bb856374fbdefb7fee1a152153e64019379f015", size = 158805, upload-time = "2026-03-06T02:54:25.441Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/67/d08672f801f604889dcf58f1a0b424fe3808860ede9e03affc1876b295af/wrapt-2.1.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8914c754d3134a3032601c6984db1c576e6abaf3fc68094bb8ab1379d75ff92", size = 145990, upload-time = "2026-03-06T02:53:57.456Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/a7/fd371b02e73babec1de6ade596e8cd9691051058cfdadbfd62a5898f3295/wrapt-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ff95d4264e55839be37bafe1536db2ab2de19da6b65f9244f01f332b5286cfbf", size = 155670, upload-time = "2026-03-06T02:54:55.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/2d/9fe0095dfdb621009f40117dcebf41d7396c2c22dca6eac779f4c007b86c/wrapt-2.1.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:76405518ca4e1b76fbb1b9f686cff93aebae03920cc55ceeec48ff9f719c5f67", size = 144357, upload-time = "2026-03-06T02:54:24.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/b6/ec7b4a254abbe4cde9fa15c5d2cca4518f6b07d0f1b77d4ee9655e30280e/wrapt-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c0be8b5a74c5824e9359b53e7e58bef71a729bacc82e16587db1c4ebc91f7c5a", size = 150269, upload-time = "2026-03-06T02:53:31.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/6b/2fabe8ebf148f4ee3c782aae86a795cc68ffe7d432ef550f234025ce0cfa/wrapt-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:f01277d9a5fc1862f26f7626da9cf443bebc0abd2f303f41c5e995b15887dabd", size = 59894, upload-time = "2026-03-06T02:54:15.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/fb/9ba66fc2dedc936de5f8073c0217b5d4484e966d87723415cc8262c5d9c2/wrapt-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:84ce8f1c2104d2f6daa912b1b5b039f331febfeee74f8042ad4e04992bd95c8f", size = 63197, upload-time = "2026-03-06T02:54:41.943Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/1c/012d7423c95d0e337117723eb8ecf73c622ce15a97847e84cf3f8f26cd7e/wrapt-2.1.2-cp313-cp313t-win_arm64.whl", hash = "sha256:a93cd767e37faeddbe07d8fc4212d5cba660af59bdb0f6372c93faaa13e6e679", size = 60363, upload-time = "2026-03-06T02:54:48.093Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/25/e7ea0b417db02bb796182a5316398a75792cd9a22528783d868755e1f669/wrapt-2.1.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1370e516598854e5b4366e09ce81e08bfe94d42b0fd569b88ec46cc56d9164a9", size = 61418, upload-time = "2026-03-06T02:53:55.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/0f/fa539e2f6a770249907757eaeb9a5ff4deb41c026f8466c1c6d799088a9b/wrapt-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6de1a3851c27e0bd6a04ca993ea6f80fc53e6c742ee1601f486c08e9f9b900a9", size = 61914, upload-time = "2026-03-06T02:52:53.37Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/37/02af1867f5b1441aaeda9c82deed061b7cd1372572ddcd717f6df90b5e93/wrapt-2.1.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:de9f1a2bbc5ac7f6012ec24525bdd444765a2ff64b5985ac6e0692144838542e", size = 120417, upload-time = "2026-03-06T02:54:30.74Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/b7/0138a6238c8ba7476c77cf786a807f871672b37f37a422970342308276e7/wrapt-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:970d57ed83fa040d8b20c52fe74a6ae7e3775ae8cff5efd6a81e06b19078484c", size = 122797, upload-time = "2026-03-06T02:54:51.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/ad/819ae558036d6a15b7ed290d5b14e209ca795dd4da9c58e50c067d5927b0/wrapt-2.1.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3969c56e4563c375861c8df14fa55146e81ac11c8db49ea6fb7f2ba58bc1ff9a", size = 117350, upload-time = "2026-03-06T02:54:37.651Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/2d/afc18dc57a4600a6e594f77a9ae09db54f55ba455440a54886694a84c71b/wrapt-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:57d7c0c980abdc5f1d98b11a2aa3bb159790add80258c717fa49a99921456d90", size = 121223, upload-time = "2026-03-06T02:54:35.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/5b/5ec189b22205697bc56eb3b62aed87a1e0423e9c8285d0781c7a83170d15/wrapt-2.1.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:776867878e83130c7a04237010463372e877c1c994d449ca6aaafeab6aab2586", size = 116287, upload-time = "2026-03-06T02:54:19.654Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/2d/f84939a7c9b5e6cdd8a8d0f6a26cabf36a0f7e468b967720e8b0cd2bdf69/wrapt-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fab036efe5464ec3291411fabb80a7a39e2dd80bae9bcbeeca5087fdfa891e19", size = 119593, upload-time = "2026-03-06T02:54:16.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/fe/ccd22a1263159c4ac811ab9374c061bcb4a702773f6e06e38de5f81a1bdc/wrapt-2.1.2-cp314-cp314-win32.whl", hash = "sha256:e6ed62c82ddf58d001096ae84ce7f833db97ae2263bff31c9b336ba8cfe3f508", size = 58631, upload-time = "2026-03-06T02:53:06.498Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/0a/6bd83be7bff2e7efaac7b4ac9748da9d75a34634bbbbc8ad077d527146df/wrapt-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:467e7c76315390331c67073073d00662015bb730c566820c9ca9b54e4d67fd04", size = 60875, upload-time = "2026-03-06T02:53:50.252Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/c0/0b3056397fe02ff80e5a5d72d627c11eb885d1ca78e71b1a5c1e8c7d45de/wrapt-2.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:da1f00a557c66225d53b095a97eace0fc5349e3bfda28fa34ffae238978ee575", size = 59164, upload-time = "2026-03-06T02:53:59.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/ed/5d89c798741993b2371396eb9d4634f009ff1ad8a6c78d366fe2883ea7a6/wrapt-2.1.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:62503ffbc2d3a69891cf29beeaccdb4d5e0a126e2b6a851688d4777e01428dbb", size = 63163, upload-time = "2026-03-06T02:52:54.873Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/8c/05d277d182bf36b0a13d6bd393ed1dec3468a25b59d01fba2dd70fe4d6ae/wrapt-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c7e6cd120ef837d5b6f860a6ea3745f8763805c418bb2f12eeb1fa6e25f22d22", size = 63723, upload-time = "2026-03-06T02:52:56.374Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/27/6c51ec1eff4413c57e72d6106bb8dec6f0c7cdba6503d78f0fa98767bcc9/wrapt-2.1.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3769a77df8e756d65fbc050333f423c01ae012b4f6731aaf70cf2bef61b34596", size = 152652, upload-time = "2026-03-06T02:53:23.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/4c/d7dd662d6963fc7335bfe29d512b02b71cdfa23eeca7ab3ac74a67505deb/wrapt-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a76d61a2e851996150ba0f80582dd92a870643fa481f3b3846f229de88caf044", size = 158807, upload-time = "2026-03-06T02:53:35.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/4d/1e5eea1a78d539d346765727422976676615814029522c76b87a95f6bcdd/wrapt-2.1.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6f97edc9842cf215312b75fe737ee7c8adda75a89979f8e11558dfff6343cc4b", size = 146061, upload-time = "2026-03-06T02:52:57.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/bc/62cabea7695cd12a288023251eeefdcb8465056ddaab6227cb78a2de005b/wrapt-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4006c351de6d5007aa33a551f600404ba44228a89e833d2fadc5caa5de8edfbf", size = 155667, upload-time = "2026-03-06T02:53:39.422Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/99/6f2888cd68588f24df3a76572c69c2de28287acb9e1972bf0c83ce97dbc1/wrapt-2.1.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a9372fc3639a878c8e7d87e1556fa209091b0a66e912c611e3f833e2c4202be2", size = 144392, upload-time = "2026-03-06T02:54:22.41Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/51/1dfc783a6c57971614c48e361a82ca3b6da9055879952587bc99fe1a7171/wrapt-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3144b027ff30cbd2fca07c0a87e67011adb717eb5f5bd8496325c17e454257a3", size = 150296, upload-time = "2026-03-06T02:54:07.848Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/38/cbb8b933a0201076c1f64fc42883b0023002bdc14a4964219154e6ff3350/wrapt-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:3b8d15e52e195813efe5db8cec156eebe339aaf84222f4f4f051a6c01f237ed7", size = 60539, upload-time = "2026-03-06T02:54:00.594Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/dd/e5176e4b241c9f528402cebb238a36785a628179d7d8b71091154b3e4c9e/wrapt-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:08ffa54146a7559f5b8df4b289b46d963a8e74ed16ba3687f99896101a3990c5", size = 63969, upload-time = "2026-03-06T02:54:39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/99/79f17046cf67e4a95b9987ea129632ba8bcec0bc81f3fb3d19bdb0bd60cd/wrapt-2.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:72aaa9d0d8e4ed0e2e98019cea47a21f823c9dd4b43c7b77bba6679ffcca6a00", size = 60554, upload-time = "2026-03-06T02:53:14.132Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/c7/8528ac2dfa2c1e6708f647df7ae144ead13f0a31146f43c7264b4942bf12/wrapt-2.1.2-py3-none-any.whl", hash = "sha256:b8fd6fa2b2c4e7621808f8c62e8317f4aae56e59721ad933bac5239d913cf0e8", size = 43993, upload-time = "2026-03-06T02:53:12.905Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-py"
|
||||
version = "4.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "base58" },
|
||||
{ name = "deprecated" },
|
||||
{ name = "ecpy" },
|
||||
{ name = "httpx" },
|
||||
{ name = "pycryptodome" },
|
||||
{ name = "types-deprecated" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "websockets" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/51/e7/8faf71e5b9b314d329a13cdc7966ad565a6e52a875adeaee0f778b1b8ef1/xrpl_py-4.5.0.tar.gz", hash = "sha256:3ee25fcb748bdf6afe18aad8f74ba71ffa23bf681409fda3a9eb029e4381fc74", size = 175681, upload-time = "2026-02-12T23:41:52.176Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/3c/65c853f906f5003c06c5e0cbc50e47bac2ecca17957a9d3a3d823efd8c38/xrpl_py-4.5.0-py3-none-any.whl", hash = "sha256:aa4720b5bf8070d8303346111f1095ec9afe13abdf49b2dc4b988d28ebc227ca", size = 314897, upload-time = "2026-02-12T23:41:50.609Z" },
|
||||
]
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpl/protocol/JsonTx.h>
|
||||
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/STBlob.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/protocol/STParsedJSON.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
namespace jsonTx {
|
||||
|
||||
namespace {
|
||||
|
||||
/** Canonical serialization of `obj` with the given fields removed.
|
||||
STObject's own serialization already sorts by field code, but we
|
||||
have to walk the fields ourselves to skip the json-tx wrapper
|
||||
entries rather than mutate the object. */
|
||||
Blob
|
||||
canonicalSerialization(
|
||||
STObject const& obj,
|
||||
std::initializer_list<SField const*> skip)
|
||||
{
|
||||
std::vector<STBase const*> fields;
|
||||
for (auto const& entry : obj)
|
||||
{
|
||||
if (entry.getSType() == STI_NOTPRESENT)
|
||||
continue;
|
||||
bool skipped = false;
|
||||
for (SField const* s : skip)
|
||||
if (entry.getFName() == *s)
|
||||
{
|
||||
skipped = true;
|
||||
break;
|
||||
}
|
||||
if (!skipped)
|
||||
fields.push_back(&entry);
|
||||
}
|
||||
std::sort(
|
||||
fields.begin(), fields.end(), [](STBase const* a, STBase const* b) {
|
||||
return a->getFName().fieldCode < b->getFName().fieldCode;
|
||||
});
|
||||
|
||||
Serializer s;
|
||||
for (STBase const* f : fields)
|
||||
{
|
||||
f->addFieldID(s);
|
||||
f->add(s);
|
||||
auto const sType = f->getSType();
|
||||
if (sType == STI_ARRAY || sType == STI_OBJECT)
|
||||
s.addFieldID(sType, 1);
|
||||
}
|
||||
return s.getData();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
hasBody(STObject const& obj) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return obj.isFieldPresent(sfJsonTxBody);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Slice
|
||||
body(STObject const& obj)
|
||||
{
|
||||
if (!obj.isFieldPresent(sfJsonTxBody))
|
||||
return Slice{};
|
||||
// peekAtField gives us a view into the STObject's owned storage;
|
||||
// STBlob::value() returns a Slice over that storage directly.
|
||||
auto const& field = obj.peekAtField(sfJsonTxBody);
|
||||
return static_cast<STBlob const&>(field).value();
|
||||
}
|
||||
|
||||
uint256
|
||||
bodyHash(STObject const& obj)
|
||||
{
|
||||
auto const s = body(obj);
|
||||
if (s.empty())
|
||||
return uint256{};
|
||||
return sha512Half(s);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
checkSignature(STTx const& stx)
|
||||
{
|
||||
if (!hasBody(stx))
|
||||
return Unexpected<std::string>("JsonTxBody field is missing.");
|
||||
|
||||
auto const bodySlice = body(stx);
|
||||
if (bodySlice.empty())
|
||||
return Unexpected<std::string>("JsonTxBody is empty.");
|
||||
|
||||
if (!stx.isFieldPresent(sfSigningPubKey))
|
||||
return Unexpected<std::string>("SigningPubKey is missing.");
|
||||
|
||||
Blob const spk = stx.getFieldVL(sfSigningPubKey);
|
||||
if (!publicKeyType(makeSlice(spk)))
|
||||
return Unexpected<std::string>("SigningPubKey is not a valid key.");
|
||||
|
||||
if (!stx.isFieldPresent(sfTxnSignature))
|
||||
return Unexpected<std::string>("TxnSignature is missing.");
|
||||
|
||||
Blob const sig = stx.getFieldVL(sfTxnSignature);
|
||||
if (sig.empty())
|
||||
return Unexpected<std::string>("TxnSignature is empty.");
|
||||
|
||||
if (!verify(PublicKey(makeSlice(spk)), bodySlice, makeSlice(sig)))
|
||||
return Unexpected<std::string>(
|
||||
"Signature over JsonTxBody failed verification.");
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
checkStructuralEquivalence(STTx const& stx)
|
||||
{
|
||||
if (!hasBody(stx))
|
||||
return Unexpected<std::string>("JsonTxBody field is missing.");
|
||||
|
||||
auto const bodySlice = body(stx);
|
||||
if (bodySlice.empty())
|
||||
return Unexpected<std::string>("JsonTxBody is empty.");
|
||||
|
||||
std::string const bodyStr(
|
||||
reinterpret_cast<char const*>(bodySlice.data()), bodySlice.size());
|
||||
|
||||
Json::Value parsed;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(bodyStr, parsed) || !parsed.isObject())
|
||||
return Unexpected<std::string>(
|
||||
"JsonTxBody is not a valid JSON object.");
|
||||
|
||||
STParsedJSONObject parsedObj("JsonTxBody", parsed);
|
||||
if (!parsedObj.object)
|
||||
return Unexpected<std::string>(
|
||||
"JsonTxBody does not parse into a valid STObject: " +
|
||||
(parsedObj.error.isMember(jss::error_message)
|
||||
? parsedObj.error[jss::error_message].asString()
|
||||
: std::string("unknown parse error")));
|
||||
|
||||
// The json-tx wrapper fields (TxnSignature, JsonTxBody) are excluded
|
||||
// from both sides: TxnSignature covers the body bytes (not the
|
||||
// binary), and JsonTxBody is the body itself.
|
||||
std::initializer_list<SField const*> const skip{
|
||||
&sfTxnSignature, &sfJsonTxBody};
|
||||
|
||||
if (canonicalSerialization(stx, skip) !=
|
||||
canonicalSerialization(*parsedObj.object, skip))
|
||||
return Unexpected<std::string>(
|
||||
"JsonTxBody content does not match the structural fields "
|
||||
"of the transaction.");
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace jsonTx
|
||||
} // namespace ripple
|
||||
@@ -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");
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <xrpl/json/to_string.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/JsonTx.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/STAccount.h>
|
||||
@@ -217,14 +216,6 @@ STTx::checkSign(
|
||||
{
|
||||
try
|
||||
{
|
||||
// json-tx: when sfJsonTxBody is present and the amendment is
|
||||
// active, the signature covers the raw ASCII bytes of the body
|
||||
// instead of the classical signing payload. Structural
|
||||
// equivalence between the body and the other STTx fields is
|
||||
// enforced separately in passesLocalChecks.
|
||||
if (rules.enabled(featureJsonTx) && jsonTx::hasBody(*this))
|
||||
return jsonTx::checkSignature(*this);
|
||||
|
||||
// Determine whether we're single- or multi-signing by looking
|
||||
// at the SigningPubKey. If it's empty we must be
|
||||
// multi-signing. Otherwise we're single-signing.
|
||||
@@ -672,21 +663,6 @@ passesLocalChecks(STObject const& st, std::string& reason)
|
||||
return false;
|
||||
}
|
||||
|
||||
// json-tx: if the tx carries sfJsonTxBody, its parsed content must
|
||||
// match the other structural fields. We can only run this when the
|
||||
// object is actually an STTx -- passesLocalChecks is also called on
|
||||
// nested STObjects that don't participate in the json-tx scheme.
|
||||
if (auto const* stx = dynamic_cast<STTx const*>(&st);
|
||||
stx && jsonTx::hasBody(*stx))
|
||||
{
|
||||
if (auto const result = jsonTx::checkStructuralEquivalence(*stx);
|
||||
!result)
|
||||
{
|
||||
reason = result.error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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."),
|
||||
|
||||
@@ -43,13 +43,11 @@ TxFormats::TxFormats()
|
||||
{sfSigningPubKey, soeREQUIRED},
|
||||
{sfTicketSequence, soeOPTIONAL},
|
||||
{sfTxnSignature, soeOPTIONAL},
|
||||
{sfJsonTxBody, soeOPTIONAL}, // json-tx: ASCII bytes that were signed
|
||||
{sfSigners, soeOPTIONAL}, // submit_multisigned
|
||||
{sfSigners, soeOPTIONAL}, // submit_multisigned
|
||||
{sfEmitDetails, soeOPTIONAL},
|
||||
{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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user