mirror of
https://github.com/Xahau/xahaud.git
synced 2026-03-01 10:12:22 +00:00
Compare commits
557 Commits
batch
...
jshooks-me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebfbb8a900 | ||
|
|
a94e8b9536 | ||
|
|
13910b23a4 | ||
|
|
6385c56832 | ||
|
|
3c879c7288 | ||
|
|
101ad3cb7e | ||
|
|
8cfee6c8a3 | ||
|
|
8673599d2b | ||
|
|
ec65e622aa | ||
|
|
65837f49e1 | ||
|
|
e5b21f026e | ||
|
|
8d08d8f1db | ||
|
|
fff46e3dd0 | ||
|
|
52369f3ebb | ||
|
|
57c4e3c9cc | ||
|
|
8e1ae86ce2 | ||
|
|
bed5473540 | ||
|
|
de1f57819f | ||
|
|
6dd6393bb8 | ||
|
|
73861a4bfe | ||
|
|
5a2bf0e0b1 | ||
|
|
5e9d961c5d | ||
|
|
73f14374b4 | ||
|
|
3380b7e2fd | ||
|
|
da6bd8cac1 | ||
|
|
05f0186572 | ||
|
|
d4db9276c6 | ||
|
|
a6824770fc | ||
|
|
5678b8fbb1 | ||
|
|
bfeef7fd91 | ||
|
|
b78c4abece | ||
|
|
a9d1f2aa69 | ||
|
|
3540148941 | ||
|
|
8ec0e9bb22 | ||
|
|
7bfa595c6c | ||
|
|
a57e819ac5 | ||
|
|
825e923081 | ||
|
|
30f8f7de00 | ||
|
|
0c236573fb | ||
|
|
293266519d | ||
|
|
96e3851c51 | ||
|
|
c9e886e5e3 | ||
|
|
7eb3c96e8b | ||
|
|
14edb034bb | ||
|
|
8b45539f9c | ||
|
|
a95832668c | ||
|
|
a9b36e1a40 | ||
|
|
dc5931fc36 | ||
|
|
59f91ab7ff | ||
|
|
e58f1e9333 | ||
|
|
7e5b799eff | ||
|
|
eda5fe9b00 | ||
|
|
d2f4539b38 | ||
|
|
c2f5c9b07a | ||
|
|
c028804db6 | ||
|
|
e4330e6d14 | ||
|
|
76139db44e | ||
|
|
eda065c41c | ||
|
|
2b5932e420 | ||
|
|
baaa746d4f | ||
|
|
923b91c883 | ||
|
|
3de1a4134b | ||
|
|
19ccbaf7b2 | ||
|
|
5d7f70f9df | ||
|
|
3eb092a914 | ||
|
|
86d7d61a3f | ||
|
|
923466e023 | ||
|
|
0bd5bcc692 | ||
|
|
979fb40073 | ||
|
|
b9e2341b69 | ||
|
|
e4d4d5a5a6 | ||
|
|
64b6bd2905 | ||
|
|
ad2f0eaafc | ||
|
|
08db1de928 | ||
|
|
1cdcfca337 | ||
|
|
959f7cd21c | ||
|
|
9c17813764 | ||
|
|
eb9ec41b78 | ||
|
|
17a484ae4a | ||
|
|
67b87e4593 | ||
|
|
af13ac80ca | ||
|
|
dd86d7c4b5 | ||
|
|
8b9ce5f60d | ||
|
|
476f6e04e7 | ||
|
|
5c1e54eec1 | ||
|
|
7e4c52c869 | ||
|
|
ed9046b4fc | ||
|
|
01c1f87eca | ||
|
|
c764643d52 | ||
|
|
9b5937a1a1 | ||
|
|
794a146116 | ||
|
|
5736d83aa1 | ||
|
|
8a2d0b1aa4 | ||
|
|
12fea12674 | ||
|
|
e1ea2d61ea | ||
|
|
fb50a0c90d | ||
|
|
14af5e67fc | ||
|
|
780500bc35 | ||
|
|
c8d7f35a59 | ||
|
|
2867b6eac5 | ||
|
|
879bfb453e | ||
|
|
6eddc7095b | ||
|
|
a289acc691 | ||
|
|
05ca77b23c | ||
|
|
d2e41693c5 | ||
|
|
bfabc979bb | ||
|
|
2a4c068f81 | ||
|
|
0cd8805e36 | ||
|
|
019940e907 | ||
|
|
02749feea8 | ||
|
|
0788de203f | ||
|
|
7454c46037 | ||
|
|
202f2f03fb | ||
|
|
282b7b73c5 | ||
|
|
cf80df3eca | ||
|
|
47a0018f30 | ||
|
|
ea53a31081 | ||
|
|
8491fd37e8 | ||
|
|
fbcb7376ff | ||
|
|
dfaaac19c6 | ||
|
|
c5a971317d | ||
|
|
725c5beb3f | ||
|
|
5a0882d17a | ||
|
|
7465bf594c | ||
|
|
96ce8c5b74 | ||
|
|
4b7370c0d2 | ||
|
|
59151959a1 | ||
|
|
380e3839c2 | ||
|
|
7a68da9c4b | ||
|
|
b2505dbd5f | ||
|
|
2aac65330b | ||
|
|
3570f3410d | ||
|
|
1f1a52b5f0 | ||
|
|
cdf3e82f6e | ||
|
|
e22f8749db | ||
|
|
2091d129d4 | ||
|
|
ce7dbaf5ab | ||
|
|
7ae3065a36 | ||
|
|
e9d75a6cc7 | ||
|
|
eccc2fc522 | ||
|
|
61e8f0956f | ||
|
|
66aa252a52 | ||
|
|
fbcff93251 | ||
|
|
e95edcba48 | ||
|
|
d25b5dcd56 | ||
|
|
e618806999 | ||
|
|
bfafa2bb39 | ||
|
|
e47b1c1b3b | ||
|
|
4564054423 | ||
|
|
8e221bcd68 | ||
|
|
a13f367b75 | ||
|
|
10435a40e6 | ||
|
|
b7fbe4eb99 | ||
|
|
316718312b | ||
|
|
9465fccbc1 | ||
|
|
92d3125bca | ||
|
|
1b1420d51b | ||
|
|
0a2a5479c6 | ||
|
|
b3a41ee9de | ||
|
|
4cebe4c0ea | ||
|
|
0c3909af4e | ||
|
|
afc7af4ab9 | ||
|
|
ff2a603745 | ||
|
|
8a054c36f0 | ||
|
|
bf0705775a | ||
|
|
469b13dd71 | ||
|
|
fad6dfe1e3 | ||
|
|
0eb5cbf78c | ||
|
|
3d87543300 | ||
|
|
8f50c787c1 | ||
|
|
0637543c2a | ||
|
|
a9a04921b5 | ||
|
|
02c2936e62 | ||
|
|
6e51de48a1 | ||
|
|
fb531107a9 | ||
|
|
39b861c78a | ||
|
|
c9b825a09a | ||
|
|
88d3428249 | ||
|
|
15f41c9777 | ||
|
|
de142a1211 | ||
|
|
2187676f36 | ||
|
|
1cdca0a832 | ||
|
|
384d8ed09b | ||
|
|
8ea5a11f97 | ||
|
|
3916c44793 | ||
|
|
5a227dc719 | ||
|
|
0345a2645d | ||
|
|
07cd7f38b7 | ||
|
|
da1d20d6d5 | ||
|
|
e76014f421 | ||
|
|
723f0e7602 | ||
|
|
eb441c6987 | ||
|
|
4366e5b111 | ||
|
|
3c7241c5bc | ||
|
|
76e376c75e | ||
|
|
14b1ac7068 | ||
|
|
afd71b9241 | ||
|
|
11b8f3ec1a | ||
|
|
f017a2af17 | ||
|
|
7a0235672b | ||
|
|
f756587680 | ||
|
|
5be2f0a6da | ||
|
|
a271c63a2b | ||
|
|
92c84471fd | ||
|
|
d12ae81070 | ||
|
|
f3065cbd6d | ||
|
|
21ec4907c7 | ||
|
|
535728e1c4 | ||
|
|
b7bd3e33ae | ||
|
|
72bbeda46e | ||
|
|
db64da58bd | ||
|
|
85b46dbf0f | ||
|
|
7b562e2312 | ||
|
|
a3f459dff4 | ||
|
|
37ae1d8a4f | ||
|
|
d424910e81 | ||
|
|
1fde2a507c | ||
|
|
87154a3ed0 | ||
|
|
c9f4bc8e92 | ||
|
|
eba2f5a439 | ||
|
|
eec05dae5f | ||
|
|
ca2627635a | ||
|
|
d5e4883fb3 | ||
|
|
85838140fb | ||
|
|
950f869715 | ||
|
|
167f0a2d34 | ||
|
|
eaa6ef5469 | ||
|
|
f8856e2eb1 | ||
|
|
d9562b4164 | ||
|
|
b7d53be99f | ||
|
|
8d012d03e8 | ||
|
|
f1b86fecbb | ||
|
|
f44b737fce | ||
|
|
3f489f9c19 | ||
|
|
c7d6d34372 | ||
|
|
54e3952297 | ||
|
|
5ffda742f5 | ||
|
|
2730a0e329 | ||
|
|
3c25e7eca6 | ||
|
|
c3489123ff | ||
|
|
dc8d496e1c | ||
|
|
a70bbc1fe1 | ||
|
|
ef978f407d | ||
|
|
48443977bd | ||
|
|
63415cf534 | ||
|
|
6211c36712 | ||
|
|
6441add2c9 | ||
|
|
24e27375a4 | ||
|
|
74432a37bb | ||
|
|
ca591b7c1d | ||
|
|
9b6c7c647a | ||
|
|
4d43e109a5 | ||
|
|
b8398cf004 | ||
|
|
26fc5422f9 | ||
|
|
cbb15ab000 | ||
|
|
35898efb13 | ||
|
|
3517ccb604 | ||
|
|
95684df001 | ||
|
|
6c1a17a8bd | ||
|
|
1cdbf27643 | ||
|
|
b0a82fd8e4 | ||
|
|
9bfea81de4 | ||
|
|
f170d4675e | ||
|
|
f6a016281f | ||
|
|
d5fde211a3 | ||
|
|
810b464fe0 | ||
|
|
1b87026411 | ||
|
|
b63b822e21 | ||
|
|
c7e6d475e4 | ||
|
|
4812f6abb4 | ||
|
|
1b6a2a39ff | ||
|
|
dfc722aa05 | ||
|
|
f16f8d00a4 | ||
|
|
babc37072f | ||
|
|
7c46fc37a4 | ||
|
|
8894f1f4f5 | ||
|
|
8a14bd4cfe | ||
|
|
0ed1da79ce | ||
|
|
f44998cd8c | ||
|
|
a865e93312 | ||
|
|
ce09fedc2c | ||
|
|
f3de28f9b7 | ||
|
|
dd9b0953b8 | ||
|
|
2ab5d729cc | ||
|
|
b2b126b51a | ||
|
|
4713dcf8c8 | ||
|
|
b5beacfc54 | ||
|
|
e9ac727cc1 | ||
|
|
d5b6f7ef1a | ||
|
|
8aa90a1f3d | ||
|
|
7750032b50 | ||
|
|
c9ddee83c2 | ||
|
|
8b3c65cf76 | ||
|
|
200a635499 | ||
|
|
802d9096d8 | ||
|
|
233f060b0b | ||
|
|
ac415e24fb | ||
|
|
706b0d2e31 | ||
|
|
4085036e25 | ||
|
|
21cacbfd5f | ||
|
|
e0566cc22a | ||
|
|
6e1a763806 | ||
|
|
ff17f3190a | ||
|
|
9554f1efb9 | ||
|
|
154d07a5cc | ||
|
|
1fa8f8f087 | ||
|
|
045b07f979 | ||
|
|
711297aa81 | ||
|
|
bb70739fc6 | ||
|
|
d18c4d9b33 | ||
|
|
c3e8039c5a | ||
|
|
d9e7b50395 | ||
|
|
67a6970031 | ||
|
|
efd5f9f6db | ||
|
|
309e517e70 | ||
|
|
edafb1fed6 | ||
|
|
d209272379 | ||
|
|
fb7a0d71de | ||
|
|
9120fffd95 | ||
|
|
12e1afb694 | ||
|
|
c355ad9971 | ||
|
|
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 |
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
|
||||
12
.githooks/pre-commit
Executable file
12
.githooks/pre-commit
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Pre-commit hook that runs the suspicious patterns check on staged files
|
||||
|
||||
# Get the repository's root directory
|
||||
repo_root=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Run the suspicious patterns script in pre-commit mode
|
||||
"$repo_root/suspicious_patterns.sh" --pre-commit
|
||||
|
||||
# Exit with the same code as the script
|
||||
exit $?
|
||||
4
.githooks/setup.sh
Normal file
4
.githooks/setup.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Configuring git to use .githooks directory..."
|
||||
git config core.hooksPath .githooks
|
||||
15
.github/actions/xahau-ga-dependencies/action.yml
vendored
15
.github/actions/xahau-ga-dependencies/action.yml
vendored
@@ -134,10 +134,17 @@ runs:
|
||||
- name: Export custom recipes
|
||||
shell: bash
|
||||
run: |
|
||||
conan export external/snappy --version 1.1.10 --user xahaud --channel stable
|
||||
conan export external/soci --version 4.0.3 --user xahaud --channel stable
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable
|
||||
|
||||
# Export snappy if not already exported
|
||||
conan list snappy/1.1.10@xahaud/stable 2>/dev/null | (grep -q "not found" && exit 1 || exit 0) || \
|
||||
conan export external/snappy --version 1.1.10 --user xahaud --channel stable
|
||||
|
||||
# Export soci if not already exported
|
||||
conan list soci/4.0.3@xahaud/stable 2>/dev/null | (grep -q "not found" && exit 1 || exit 0) || \
|
||||
conan export external/soci --version 4.0.3 --user xahaud --channel stable
|
||||
|
||||
# Export wasmedge if not already exported
|
||||
conan list wasmedge/0.11.2@xahaud/stable 2>/dev/null | (grep -q "not found" && exit 1 || exit 0) || \
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
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' \) -not -path "src/magic/magic_enum.h" -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/magic/magic_enum.h" -not -path "src/quickjs/*" -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
- name: Check for differences
|
||||
id: assert
|
||||
run: |
|
||||
|
||||
24
.github/workflows/guard-checker-build.yml
vendored
Normal file
24
.github/workflows/guard-checker-build.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Guard Checker Build
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
guard-checker-build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- run-on: ubuntu-latest
|
||||
- run-on: macos-latest
|
||||
runs-on: ${{ matrix.run-on }}
|
||||
name: Guard Checker Build - ${{ matrix.run-on }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Build Guard Checker
|
||||
run: |
|
||||
cd include/xrpl/hook
|
||||
make guard_checker
|
||||
16
.github/workflows/verify-generated-headers.yml
vendored
16
.github/workflows/verify-generated-headers.yml
vendored
@@ -18,12 +18,26 @@ jobs:
|
||||
generator: bash ./hook/generate_sfcodes.sh
|
||||
- target: hook/tts.h
|
||||
generator: ./hook/generate_tts.sh
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
CLANG_VERSION: 18
|
||||
name: ${{ matrix.target }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install clang-format
|
||||
run: |
|
||||
codename=$( lsb_release --codename --short )
|
||||
sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null <<EOF
|
||||
deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
|
||||
deb-src http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
|
||||
EOF
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-format-${CLANG_VERSION}
|
||||
sudo ln -sf /usr/bin/clang-format-${CLANG_VERSION} /usr/local/bin/clang-format
|
||||
|
||||
- name: Verify ${{ matrix.target }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
19
.github/workflows/xahau-ga-macos.yml
vendored
19
.github/workflows/xahau-ga-macos.yml
vendored
@@ -4,7 +4,8 @@ on:
|
||||
push:
|
||||
branches: ["dev", "candidate", "release"]
|
||||
pull_request:
|
||||
branches: ["dev", "candidate", "release"]
|
||||
branches: ["**"]
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
@@ -14,6 +15,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
if: >
|
||||
github.event_name != 'pull_request' ||
|
||||
contains(fromJson('["dev","candidate","release"]'), github.base_ref) ||
|
||||
contains(join(github.event.pull_request.labels.*.name, ','), 'ci-full-build')
|
||||
strategy:
|
||||
matrix:
|
||||
generator:
|
||||
@@ -43,14 +48,22 @@ jobs:
|
||||
# To isolate environments for each Runner, instead of installing globally with brew,
|
||||
# use mise to isolate environments for each Runner directory.
|
||||
- name: Setup toolchain (mise)
|
||||
uses: jdx/mise-action@v2
|
||||
uses: jdx/mise-action@v3.6.1
|
||||
with:
|
||||
cache: false
|
||||
install: true
|
||||
mise_toml: |
|
||||
[tools]
|
||||
cmake = "3.25.3"
|
||||
python = "3.12"
|
||||
pipx = "latest"
|
||||
conan = "2"
|
||||
ninja = "latest"
|
||||
ccache = "latest"
|
||||
|
||||
- name: Install tools via mise
|
||||
run: |
|
||||
mise install
|
||||
mise use cmake@3.25.3 python@3.12 pipx@latest conan@2 ninja@latest ccache@latest
|
||||
mise reshim
|
||||
echo "$HOME/.local/share/mise/shims" >> "$GITHUB_PATH"
|
||||
|
||||
|
||||
36
.github/workflows/xahau-ga-nix.yml
vendored
36
.github/workflows/xahau-ga-nix.yml
vendored
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches: ["dev", "candidate", "release"]
|
||||
pull_request:
|
||||
branches: ["dev", "candidate", "release"]
|
||||
branches: ["**"]
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
full_matrix:
|
||||
description: "Force full matrix (6 configs)"
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -14,6 +21,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
matrix-setup:
|
||||
if: >
|
||||
github.event_name != 'pull_request' ||
|
||||
contains(fromJson('["dev","candidate","release"]'), github.base_ref) ||
|
||||
contains(join(github.event.pull_request.labels.*.name, ','), 'ci-full-build')
|
||||
runs-on: [self-hosted, generic, 20.04]
|
||||
container: python:3-slim
|
||||
outputs:
|
||||
@@ -111,6 +122,7 @@ jobs:
|
||||
base_ref = "${{ github.base_ref }}" # For PRs, this is the target branch
|
||||
event_name = "${{ github.event_name }}"
|
||||
pr_title = """${{ steps.escape.outputs.title }}"""
|
||||
pr_labels = """${{ join(github.event.pull_request.labels.*.name, ',') }}"""
|
||||
pr_head_sha = "${{ github.event.pull_request.head.sha }}"
|
||||
|
||||
# Get commit message - for PRs, fetch via API since head_commit.message is empty
|
||||
@@ -136,11 +148,24 @@ jobs:
|
||||
print(f"Base ref: {base_ref}")
|
||||
print(f"PR head SHA: {pr_head_sha}")
|
||||
print(f"PR title: {pr_title}")
|
||||
print(f"PR labels: {pr_labels}")
|
||||
print(f"Commit message: {commit_message}")
|
||||
|
||||
# Check for override tags in commit message or PR title
|
||||
force_full = "[ci-nix-full-matrix]" in commit_message or "[ci-nix-full-matrix]" in pr_title
|
||||
# Manual trigger input to force full matrix.
|
||||
manual_full = "${{ github.event.inputs.full_matrix || 'false' }}" == "true"
|
||||
|
||||
# Label/manual overrides, while preserving existing title/commit behavior.
|
||||
force_full = (
|
||||
manual_full
|
||||
or "[ci-nix-full-matrix]" in commit_message
|
||||
or "[ci-nix-full-matrix]" in pr_title
|
||||
or ("ci-full-build" in pr_labels and "ci-nix-full-matrix" in pr_labels)
|
||||
)
|
||||
force_min = (
|
||||
"ci-full-build" in pr_labels
|
||||
)
|
||||
print(f"Force full matrix: {force_full}")
|
||||
print(f"Force min matrix: {force_min}")
|
||||
|
||||
# Check if this is targeting a main branch
|
||||
# For PRs: check base_ref (target branch)
|
||||
@@ -148,8 +173,11 @@ jobs:
|
||||
main_branches = ["refs/heads/dev", "refs/heads/release", "refs/heads/candidate"]
|
||||
|
||||
if force_full:
|
||||
# Override: always use full matrix if tag is present
|
||||
# Override: always use full matrix if forced by manual input or label.
|
||||
use_full = True
|
||||
elif force_min:
|
||||
# Override: always use minimal matrix if ci-full-build label is present.
|
||||
use_full = False
|
||||
elif event_name == "pull_request":
|
||||
# For PRs, base_ref is just the branch name (e.g., "dev", not "refs/heads/dev")
|
||||
# Check if the PR targets release or candidate (more critical branches)
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -76,6 +76,7 @@ docs/html_doc
|
||||
# Xcode
|
||||
.DS_Store
|
||||
*/build/*
|
||||
!/docs/build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
@@ -120,6 +121,8 @@ pkg
|
||||
CMakeUserPresets.json
|
||||
bld.rippled/
|
||||
|
||||
# binary
|
||||
qjsc
|
||||
generated
|
||||
.vscode
|
||||
|
||||
|
||||
75
BUILD.md
75
BUILD.md
@@ -10,7 +10,7 @@
|
||||
## Branches
|
||||
|
||||
For a stable release, choose the `master` branch or one of the [tagged
|
||||
releases](https://github.com/ripple/rippled/releases).
|
||||
releases](https://github.com/Xahau/xahaud/releases).
|
||||
|
||||
```
|
||||
git checkout master
|
||||
@@ -39,13 +39,7 @@ Building rippled generally requires git, Python, Conan, CMake, and a C++ compile
|
||||
- [Conan 2.x](https://conan.io/downloads)
|
||||
- [CMake 3.16](https://cmake.org/download/)
|
||||
|
||||
[^1]: It is possible to build with Conan 2.x,
|
||||
but the instructions are significantly different,
|
||||
which is why we are not recommending it yet.
|
||||
Notably, the `conan profile update` command is removed in 2.x.
|
||||
Profiles must be edited by hand.
|
||||
|
||||
`rippled` is written in the C++20 dialect and includes the `<concepts>` header.
|
||||
`xahaud` is written in the C++20 dialect and includes the `<concepts>` header.
|
||||
The [minimum compiler versions][2] required are:
|
||||
|
||||
| Compiler | Version |
|
||||
@@ -64,17 +58,19 @@ Here are [sample instructions for setting up a C++ development environment on Li
|
||||
|
||||
### Mac
|
||||
|
||||
Many rippled engineers use macOS for development.
|
||||
Many xahaud engineers use macOS for development.
|
||||
|
||||
Here are [sample instructions for setting up a C++ development environment on macOS](./docs/build/environment.md#macos).
|
||||
|
||||
### Windows
|
||||
|
||||
Windows is not recommended for production use at this time.
|
||||
We don't recommend Windows for `xahaud` production at this time. As of
|
||||
November 2025, Ubuntu has the highest level of quality assurance, testing,
|
||||
and support.
|
||||
|
||||
- Additionally, 32-bit Windows development is not supported.
|
||||
|
||||
[Boost]: https://www.boost.org/
|
||||
Windows developers should use Visual Studio 2019. `xahaud` isn't
|
||||
compatible with [Boost](https://www.boost.org/) 1.78 or 1.79, and Conan
|
||||
can't build earlier Boost versions.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -144,8 +140,8 @@ conan profile show default
|
||||
An easy way to do that is to run the shortcut "x64 Native Tools Command
|
||||
Prompt" for the version of Visual Studio that you have installed.
|
||||
|
||||
Windows developers must also build `rippled` and its dependencies for the x64
|
||||
architecture:
|
||||
Windows developers must also build `xahaud` and its dependencies for the x64
|
||||
architecture.
|
||||
|
||||
```
|
||||
# In ~/.conan2/profiles/default, ensure:
|
||||
@@ -153,10 +149,7 @@ Prompt" for the version of Visual Studio that you have installed.
|
||||
arch=x86_64
|
||||
```
|
||||
|
||||
3. (Optional) If you have multiple compilers installed on your platform,
|
||||
make sure that Conan and CMake select the one you want to use.
|
||||
This setting will set the correct variables (`CMAKE_<LANG>_COMPILER`)
|
||||
in the generated CMake toolchain file.
|
||||
### Multiple compilers
|
||||
|
||||
```
|
||||
# In ~/.conan2/profiles/default, add under [conf] section:
|
||||
@@ -173,9 +166,17 @@ Prompt" for the version of Visual Studio that you have installed.
|
||||
CXX=<path>
|
||||
```
|
||||
|
||||
4. Export our [Conan recipe for Snappy](./external/snappy).
|
||||
It doesn't explicitly link the C++ standard library,
|
||||
which allows you to statically link it with GCC, if you want.
|
||||
It should choose the compiler for dependencies as well,
|
||||
but not all of them have a Conan recipe that respects this setting (yet).
|
||||
For the rest, you can set these environment variables.
|
||||
Replace `<path>` with paths to the desired compilers:
|
||||
|
||||
- `conan profile update env.CC=<path> default`
|
||||
- `conan profile update env.CXX=<path> default`
|
||||
|
||||
Export our [Conan recipe for Snappy](./external/snappy).
|
||||
It does not explicitly link the C++ standard library,
|
||||
which allows you to statically link it with GCC, if you want.
|
||||
|
||||
```
|
||||
conan export external/snappy --version 1.1.10 --user xahaud --channel stable
|
||||
@@ -184,6 +185,16 @@ Prompt" for the version of Visual Studio that you have installed.
|
||||
Export our [Conan recipe for RocksDB](./external/rocksdb).
|
||||
It does not override paths to dependencies when building with Visual Studio.
|
||||
|
||||
```
|
||||
# Conan 1.x
|
||||
conan export external/rocksdb rocksdb/6.29.5@
|
||||
# Conan 2.x
|
||||
conan export --version 6.29.5 external/rocksdb
|
||||
```
|
||||
|
||||
Export our [Conan recipe for SOCI](./external/soci).
|
||||
It patches their CMake to correctly import its dependencies.
|
||||
|
||||
```
|
||||
conan export external/soci --version 4.0.3 --user xahaud --channel stable
|
||||
```
|
||||
@@ -194,6 +205,17 @@ It does not override paths to dependencies when building with Visual Studio.
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable
|
||||
```
|
||||
|
||||
Export our [Conan recipe for NuDB](./external/nudb).
|
||||
It fixes some source files to add missing `#include`s.
|
||||
|
||||
|
||||
```
|
||||
# Conan 1.x
|
||||
conan export external/nudb nudb/2.0.8@
|
||||
# Conan 2.x
|
||||
conan export --version 2.0.8 external/nudb
|
||||
```
|
||||
|
||||
### Build and Test
|
||||
|
||||
1. Create a build directory and move into it.
|
||||
@@ -267,13 +289,14 @@ It does not override paths to dependencies when building with Visual Studio.
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
|
||||
**Note:** You can pass build options for `rippled` in this step.
|
||||
**Note:** You can pass build options for `xahaud` in this step.
|
||||
|
||||
5. Build `rippled`.
|
||||
4. Build `xahaud`.
|
||||
|
||||
For a single-configuration generator, it will build whatever configuration
|
||||
you passed for `CMAKE_BUILD_TYPE`. For a multi-configuration generator,
|
||||
you must pass the option `--config` to select the build configuration.
|
||||
The output file is currently named 'rippled'.
|
||||
|
||||
Single-config generators:
|
||||
|
||||
@@ -288,7 +311,7 @@ It does not override paths to dependencies when building with Visual Studio.
|
||||
cmake --build . --config Debug
|
||||
```
|
||||
|
||||
6. Test rippled.
|
||||
5. Test xahaud.
|
||||
|
||||
Single-config generators:
|
||||
|
||||
@@ -303,7 +326,7 @@ It does not override paths to dependencies when building with Visual Studio.
|
||||
./Debug/rippled --unittest
|
||||
```
|
||||
|
||||
The location of `rippled` in your build directory depends on your CMake
|
||||
The location of `xahaud` in your build directory depends on your CMake
|
||||
generator. Pass `--help` to see the rest of the command line options.
|
||||
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ test.toplevel > test.csf
|
||||
test.toplevel > xrpl.json
|
||||
test.unit_test > xrpl.basics
|
||||
xrpl.hook > xrpl.basics
|
||||
xrpl.hook > xrpl.protocol
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.protocol > xrpl.basics
|
||||
xrpl.protocol > xrpl.json
|
||||
@@ -149,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
|
||||
|
||||
@@ -109,7 +109,7 @@ find_package(lz4 REQUIRED)
|
||||
find_package(LibArchive REQUIRED)
|
||||
find_package(SOCI REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
include(deps/WasmEdge)
|
||||
|
||||
option(rocksdb "Enable RocksDB" ON)
|
||||
if(rocksdb)
|
||||
find_package(RocksDB REQUIRED)
|
||||
@@ -118,9 +118,12 @@ if(rocksdb)
|
||||
)
|
||||
target_link_libraries(ripple_libs INTERFACE RocksDB::rocksdb)
|
||||
endif()
|
||||
|
||||
find_package(nudb REQUIRED)
|
||||
find_package(date REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
|
||||
include(deps/WasmEdge)
|
||||
if(TARGET nudb::core)
|
||||
set(nudb nudb::core)
|
||||
elseif(TARGET NuDB::nudb)
|
||||
@@ -132,16 +135,17 @@ target_link_libraries(ripple_libs INTERFACE ${nudb})
|
||||
|
||||
target_link_libraries(ripple_libs INTERFACE
|
||||
ed25519::ed25519
|
||||
LibArchive::LibArchive
|
||||
lz4::lz4
|
||||
OpenSSL::Crypto
|
||||
OpenSSL::SSL
|
||||
# Ripple::grpc_pbufs
|
||||
# Ripple::pbufs
|
||||
secp256k1::secp256k1
|
||||
soci::soci
|
||||
SQLite::SQLite3
|
||||
)
|
||||
|
||||
include(deps/quickjs)
|
||||
|
||||
if(coverage)
|
||||
include(RippledCov)
|
||||
endif()
|
||||
|
||||
@@ -57,12 +57,12 @@ Ensure that your code compiles according to the build instructions in the
|
||||
[`documentation`](https://docs.xahau.network/infrastructure/building-xahau).
|
||||
If you create new source files, they must go under `src/ripple`.
|
||||
You will need to add them to one of the
|
||||
[source lists](./cmake/RippledCore.cmake) in CMake.
|
||||
[source lists](./Builds/CMake/RippledCore.cmake) in CMake.
|
||||
|
||||
Please write tests for your code.
|
||||
If you create new test source files, they must go under `src/test`.
|
||||
You will need to add them to one of the
|
||||
[source lists](./cmake/RippledCore.cmake) in CMake.
|
||||
[source lists](./Builds/CMake/RippledCore.cmake) in CMake.
|
||||
If your test can be run offline, in under 60 seconds, then it can be an
|
||||
automatic test run by `rippled --unittest`.
|
||||
Otherwise, it must be a manual test.
|
||||
|
||||
@@ -60,7 +60,7 @@ git-subtree. See those directories' README files for more details.
|
||||
- [Xrpl Documentation](https://xrpl.org)
|
||||
- [Xahau Documentation](https://xahau.network/)
|
||||
- [Hooks Technical Documentation](https://xrpl-hooks.readme.io/)
|
||||
- **Explorers**: Explore the Xahau ledger using various explorers:
|
||||
- **Explorers**: Explore the Xahau Network using various explorers:
|
||||
- [xahauexplorer.com](https://xahauexplorer.com)
|
||||
- [xahscan.com](https://xahscan.com)
|
||||
- [xahau.xrpl.org](https://xahau.xrpl.org)
|
||||
|
||||
@@ -62,11 +62,11 @@ For these complaints or reports, please [contact our support team](mailto:bugs@x
|
||||
### The following type of security problems are excluded
|
||||
|
||||
1. **In scope**. Only bugs in software under the scope of the program qualify. Currently, that means `xahaud` and `xahau-lib`.
|
||||
2. **Relevant**. A security issue, posing a danger to user funds, privacy or the operation of the Xahau Ledger.
|
||||
2. **Relevant**. A security issue, posing a danger to user funds, privacy or the operation of the Xahau Network.
|
||||
3. **Original and previously unknown**. Bugs that are already known and discussed in public do not qualify. Previously reported bugs, even if publicly unknown, are not eligible.
|
||||
4. **Specific**. We welcome general security advice or recommendations, but we cannot pay bounties for that.
|
||||
5. **Fixable**. There has to be something we can do to permanently fix the problem. Note that bugs in other people’s software may still qualify in some cases. For example, if you find a bug in a library that we use which can compromise the security of software that is in scope and we can get it fixed, you may qualify for a bounty.
|
||||
6. **Unused**. If you use the exploit to attack the Xahau Ledger, you do not qualify for a bounty. If you report a vulnerability used in an ongoing or past attack and there is specific, concrete evidence that suggests you are the attacker we reserve the right not to pay a bounty.
|
||||
6. **Unused**. If you use the exploit to attack the Xahau Network, you do not qualify for a bounty. If you report a vulnerability used in an ongoing or past attack and there is specific, concrete evidence that suggests you are the attacker we reserve the right not to pay a bounty.
|
||||
|
||||
Please note: Reports that are lacking any proof (such as screenshots or other data), detailed information or details on how to reproduce any unexpected result will be investigated but will not be eligible for any reward.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -o errexit
|
||||
|
||||
marker_base=34be0ce4fef20c978df2923c29321ad6cc17facc
|
||||
marker_base=f62f74da10c5936c64bd16cd509a8b68f1464e41
|
||||
marker_commit=${1:-${marker_base}}
|
||||
|
||||
if [ $(git merge-base ${marker_commit} ${marker_base}) != ${marker_base} ]; then
|
||||
|
||||
@@ -51,10 +51,9 @@ export CMAKE_STATIC_LINKER_FLAGS="-static-libstdc++"
|
||||
|
||||
git config --global --add safe.directory /io &&
|
||||
git checkout src/libxrpl/protocol/BuildInfo.cpp &&
|
||||
sed -i s/\"0.0.0\"/\"$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)$(if [ -n "$4" ]; then echo "+$4"; fi)\"/g src/libxrpl/protocol/BuildInfo.cpp &&
|
||||
sed -i s/\"0.0.0\"/\"$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)$(if [ -n "$4" ]; then echo "+$4"; fi)\"/g src/libxrpl/protocol/BuildInfo.cpp &&
|
||||
conan export external/snappy --version 1.1.10 --user xahaud --channel stable &&
|
||||
conan export external/soci --version 4.0.3 --user xahaud --channel stable &&
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable &&
|
||||
cd release-build &&
|
||||
# Install dependencies - tool_requires in conanfile.py handles glibc 2.28 compatibility
|
||||
# for build tools (protoc, grpc plugins, b2) in HBB environment
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
"3C43D9A973AA4443EF3FC38E42DD306160FBFFDAB901CD8BAA15D09F2597EB87",
|
||||
"0285B7E5E08E1A8E4C15636F0591D87F73CB6A7B6452A932AD72BBC8E5D1CBE3",
|
||||
"6E739F4F8B07BED29FC9FF440DA3C301CD14A180DF45819F658FEC2F7DE31427",
|
||||
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6"
|
||||
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6",
|
||||
"DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536"
|
||||
],
|
||||
"Flags": 0,
|
||||
"LedgerEntryType": "Amendments",
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
# true - enables compression
|
||||
# false - disables compression [default].
|
||||
#
|
||||
# The xahaud server can save bandwidth by compressing its peer-to-peer communications,
|
||||
# The rippled server can save bandwidth by compressing its peer-to-peer communications,
|
||||
# at a cost of greater CPU usage. If you enable link compression,
|
||||
# the server automatically compresses communications with peer servers
|
||||
# that also have link compression enabled.
|
||||
@@ -477,6 +477,19 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
# [sntp_servers]
|
||||
#
|
||||
# IP address or domain of NTP servers to use for time synchronization.
|
||||
#
|
||||
# These NTP servers are suitable for xahaud servers located in the United
|
||||
# States:
|
||||
# time.windows.com
|
||||
# time.apple.com
|
||||
# time.nist.gov
|
||||
# pool.ntp.org
|
||||
#
|
||||
#
|
||||
#
|
||||
# [max_transactions]
|
||||
#
|
||||
# Configure the maximum number of transactions to have in the job queue
|
||||
@@ -941,6 +954,12 @@
|
||||
#
|
||||
# path Location to store the database
|
||||
#
|
||||
# Required keys for RWDB:
|
||||
#
|
||||
# online_delete Required. RWDB stores data in memory and will
|
||||
# grow unbounded without online_delete. See the
|
||||
# online_delete section below.
|
||||
#
|
||||
# Optional keys
|
||||
#
|
||||
# cache_size Size of cache for database records. Default is 16384.
|
||||
@@ -1431,7 +1450,7 @@
|
||||
#
|
||||
# ETL commands for Clio. We recommend setting secure_gateway
|
||||
# in this section to a comma-separated list of the addresses
|
||||
# of your Clio servers, in order to bypass xahaud's rate limiting.
|
||||
# of your Clio servers, in order to bypass rippled's rate limiting.
|
||||
#
|
||||
# This port is commented out but can be enabled by removing
|
||||
# the '#' from each corresponding line including the entry under [server]
|
||||
@@ -1505,10 +1524,13 @@ secure_gateway = 127.0.0.1
|
||||
# when the node has approximately two times the "online_delete" value of
|
||||
# ledgers. No external administrative command is required to initiate
|
||||
# deletion.
|
||||
[ledger_history]
|
||||
256
|
||||
|
||||
[node_db]
|
||||
type=NuDB
|
||||
path=/opt/xahaud/db/nudb
|
||||
online_delete=512
|
||||
online_delete=256
|
||||
advisory_delete=0
|
||||
|
||||
[database_path]
|
||||
@@ -1520,7 +1542,18 @@ advisory_delete=0
|
||||
[debug_logfile]
|
||||
/var/log/xahaud/debug.log
|
||||
|
||||
# To use the Xahau test network
|
||||
[sntp_servers]
|
||||
time.windows.com
|
||||
time.apple.com
|
||||
time.nist.gov
|
||||
pool.ntp.org
|
||||
|
||||
# Use the following [ips] section for the main network:
|
||||
[ips]
|
||||
bacab.alloy.ee 21337
|
||||
hubs.xahau.as16089.net 21337
|
||||
|
||||
# To use the Xahau Test Network
|
||||
# (see https://xahau.network/docs/infrastructure/installing-xahaud),
|
||||
# use the following [ips] section:
|
||||
# [ips]
|
||||
@@ -1546,3 +1579,10 @@ validators-xahau.txt
|
||||
# set to ssl_verify to 0.
|
||||
[ssl_verify]
|
||||
1
|
||||
|
||||
# Define which network xahaud is connecting to
|
||||
# 21337 for the Main Xahau Network
|
||||
# 21338 for the Test Xahau Network
|
||||
[network_id]
|
||||
21337
|
||||
# 21338
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,6 +57,7 @@ target_link_libraries(xrpl.imports.main
|
||||
OpenSSL::Crypto
|
||||
Ripple::boost
|
||||
wasmedge::wasmedge
|
||||
NIH::quickjs
|
||||
Ripple::opts
|
||||
Ripple::syslibs
|
||||
absl::random_random
|
||||
@@ -78,12 +79,6 @@ target_link_libraries(xrpl.libxrpl.beast PUBLIC
|
||||
xrpl.libpb
|
||||
)
|
||||
|
||||
# Conditionally add enhanced logging source when BEAST_ENHANCED_LOGGING is enabled
|
||||
if(DEFINED BEAST_ENHANCED_LOGGING AND BEAST_ENHANCED_LOGGING)
|
||||
target_sources(xrpl.libxrpl.beast PRIVATE
|
||||
src/libxrpl/beast/utility/src/beast_EnhancedLogging.cpp)
|
||||
endif()
|
||||
|
||||
# Level 02
|
||||
add_module(xrpl basics)
|
||||
target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast)
|
||||
|
||||
@@ -6,6 +6,7 @@ include(create_symbolic_link)
|
||||
|
||||
install (
|
||||
TARGETS
|
||||
quickjs
|
||||
common
|
||||
opts
|
||||
ripple_syslibs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
find_package(Boost 1.83 REQUIRED
|
||||
find_package(Boost 1.86 REQUIRED
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
@@ -7,6 +7,7 @@ find_package(Boost 1.83 REQUIRED
|
||||
date_time
|
||||
filesystem
|
||||
json
|
||||
json
|
||||
program_options
|
||||
regex
|
||||
system
|
||||
@@ -31,7 +32,6 @@ target_link_libraries(ripple_boost
|
||||
Boost::date_time
|
||||
Boost::filesystem
|
||||
Boost::json
|
||||
Boost::iostreams
|
||||
Boost::program_options
|
||||
Boost::regex
|
||||
Boost::system
|
||||
|
||||
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
|
||||
)
|
||||
@@ -8,7 +8,7 @@
|
||||
# those warnings.
|
||||
if (RIPPLED_SOURCE)
|
||||
execute_process( COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${RIPPLED_SOURCE}/cmake/SociConfig.cmake.patched
|
||||
${RIPPLED_SOURCE}/Builds/CMake/SociConfig.cmake.patched
|
||||
cmake/SociConfig.cmake )
|
||||
endif ()
|
||||
|
||||
|
||||
10
conanfile.py
10
conanfile.py
@@ -50,9 +50,9 @@ class Xrpl(ConanFile):
|
||||
'static': True,
|
||||
'tests': False,
|
||||
'unity': False,
|
||||
'xrpld': False,
|
||||
'with_wasmedge': True,
|
||||
'tool_requires_b2': False,
|
||||
'xrpld': False,
|
||||
|
||||
'date/*:header_only': False,
|
||||
'grpc/*:shared': False,
|
||||
@@ -99,6 +99,7 @@ class Xrpl(ConanFile):
|
||||
self.version = match.group(1)
|
||||
|
||||
def build_requirements(self):
|
||||
# These provide build tools (protoc, grpc plugins) that run during build
|
||||
self.tool_requires('grpc/1.50.1')
|
||||
# Explicitly require b2 (e.g. for building from source for glibc compatibility)
|
||||
if self.options.tool_requires_b2:
|
||||
@@ -109,14 +110,13 @@ class Xrpl(ConanFile):
|
||||
self.options['boost/*'].visibility = 'global'
|
||||
|
||||
def requirements(self):
|
||||
# Force boost version for all dependencies to avoid conflicts
|
||||
self.requires('boost/1.86.0', override=True)
|
||||
self.requires('lz4/1.10.0', force=True)
|
||||
self.requires('protobuf/3.21.9', force=True)
|
||||
# Force sqlite3 version to avoid conflicts with soci
|
||||
self.requires('sqlite3/3.47.0', override=True)
|
||||
# Force our custom snappy build for all dependencies
|
||||
self.requires('snappy/1.1.10@xahaud/stable', override=True)
|
||||
# Force boost version for all dependencies to avoid conflicts
|
||||
self.requires('boost/1.86.0', override=True)
|
||||
self.requires('lz4/1.10.0', force=True)
|
||||
|
||||
if self.options.with_wasmedge:
|
||||
self.requires('wasmedge/0.11.2@xahaud/stable')
|
||||
|
||||
4
docs/build/environment.md
vendored
4
docs/build/environment.md
vendored
@@ -11,11 +11,11 @@ platforms: Linux, macOS, or Windows.
|
||||
Package ecosystems vary across Linux distributions,
|
||||
so there is no one set of instructions that will work for every Linux user.
|
||||
These instructions are written for Ubuntu 22.04.
|
||||
They are largely copied from the [script][1] used to configure our Docker
|
||||
They are largely copied from the [script][1] used to configure a Docker
|
||||
container for continuous integration.
|
||||
That script handles many more responsibilities.
|
||||
These instructions are just the bare minimum to build one configuration of
|
||||
rippled.
|
||||
xahaud.
|
||||
You can check that codebase for other Linux distributions and versions.
|
||||
If you cannot find yours there,
|
||||
then we hope that these instructions can at least guide you in the right
|
||||
|
||||
177
docs/build/install.md
vendored
177
docs/build/install.md
vendored
@@ -1,159 +1,30 @@
|
||||
This document contains instructions for installing rippled.
|
||||
The APT package manager is common on Debian-based Linux distributions like
|
||||
Ubuntu,
|
||||
while the YUM package manager is common on Red Hat-based Linux distributions
|
||||
like CentOS.
|
||||
Installing from source is an option for all platforms,
|
||||
and the only supported option for installing custom builds.
|
||||
Comprehensive instructions for installing and running xahaud are available on the [https://Xahau.Network](https://xahau.network/docs/infrastructure/installing-xahaud) documentation website.
|
||||
|
||||
## Create the Runtime Environment
|
||||
xahaud can be [built from source](../../BUILD.md) or installed using the binary files available from [https://build.xahau.tech](https://build.xahau.tech/). After obtaining a working xahaud binary, users will need to provide a suitable runtime environment. The following setup can be used for Linux or Docker environments.
|
||||
|
||||
## From source
|
||||
|
||||
From a source build, you can install rippled and libxrpl using CMake's
|
||||
`--install` mode:
|
||||
1. Create or download two configuration files: the main xahaud.cfg configuration file and a second validators-xahau.txt file defining which validators or UNL list publishers are trusted. The default location for these files in this xahaud repository is `cfg/`.
|
||||
2. Provide a directory structure that is congruent with the contents of xahaud.cfg. This will include a location for logfiles, such as `/var/log/xahaud/`, as well as database files, `/opt/xahaud/db/`. Configuration files are, by default, sourced from `/etc/xahaud/`. It is possible to provide a symbolic link, if users wish to store configuration files elsewhere.
|
||||
3. If desired, created a xahaud user and group, and change ownership of the binary and directories. Servers used for validating nodes should use the most restrictive permissions possible for `xahaud.cfg`, as the validation token is stored therein.
|
||||
4. If desired, create a systemd service file: `/etc/systemd/system/xahaud.service`, enabling xahaud to run as a daemon. Alternately, run: `/path/to/binary/xahaud --conf=/path/to/xahaud.cfg`.
|
||||
|
||||
## Example systemd Service File
|
||||
```
|
||||
cmake --install . --prefix /opt/local
|
||||
[Unit]
|
||||
Description=Xahaud Daemon
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/path/to/xahaud --silent --conf /path/to/xahaud.cfg
|
||||
Restart=on-failure
|
||||
User=xahaud
|
||||
Group=xahaud
|
||||
LimitNOFILE=65536
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
`C:/Program Files/rippled` on Windows.
|
||||
|
||||
[1]: https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
|
||||
|
||||
|
||||
## With the APT package manager
|
||||
|
||||
1. Update repositories:
|
||||
|
||||
sudo apt update -y
|
||||
|
||||
2. Install utilities:
|
||||
|
||||
sudo apt install -y apt-transport-https ca-certificates wget gnupg
|
||||
|
||||
3. Add Ripple's package-signing GPG key to your list of trusted keys:
|
||||
|
||||
sudo mkdir /usr/local/share/keyrings/
|
||||
wget -q -O - "https://repos.ripple.com/repos/api/gpg/key/public" | gpg --dearmor > ripple-key.gpg
|
||||
sudo mv ripple-key.gpg /usr/local/share/keyrings
|
||||
|
||||
|
||||
4. Check the fingerprint of the newly-added key:
|
||||
|
||||
gpg /usr/local/share/keyrings/ripple-key.gpg
|
||||
|
||||
The output should include an entry for Ripple such as the following:
|
||||
|
||||
gpg: WARNING: no command supplied. Trying to guess what you mean ...
|
||||
pub rsa3072 2019-02-14 [SC] [expires: 2026-02-17]
|
||||
C0010EC205B35A3310DC90DE395F97FFCCAFD9A2
|
||||
uid TechOps Team at Ripple <techops+rippled@ripple.com>
|
||||
sub rsa3072 2019-02-14 [E] [expires: 2026-02-17]
|
||||
|
||||
|
||||
In particular, make sure that the fingerprint matches. (In the above example, the fingerprint is on the third line, starting with `C001`.)
|
||||
|
||||
4. Add the appropriate Ripple repository for your operating system version:
|
||||
|
||||
echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/rippled-deb focal stable" | \
|
||||
sudo tee -a /etc/apt/sources.list.d/ripple.list
|
||||
|
||||
The above example is appropriate for **Ubuntu 20.04 Focal Fossa**. For other operating systems, replace the word `focal` with one of the following:
|
||||
|
||||
- `jammy` for **Ubuntu 22.04 Jammy Jellyfish**
|
||||
- `bionic` for **Ubuntu 18.04 Bionic Beaver**
|
||||
- `bullseye` for **Debian 11 Bullseye**
|
||||
- `buster` for **Debian 10 Buster**
|
||||
|
||||
If you want access to development or pre-release versions of `rippled`, use one of the following instead of `stable`:
|
||||
|
||||
- `unstable` - Pre-release builds ([`release` branch](https://github.com/ripple/rippled/tree/release))
|
||||
- `nightly` - Experimental/development builds ([`develop` branch](https://github.com/ripple/rippled/tree/develop))
|
||||
|
||||
**Warning:** Unstable and nightly builds may be broken at any time. Do not use these builds for production servers.
|
||||
|
||||
5. Fetch the Ripple repository.
|
||||
|
||||
sudo apt -y update
|
||||
|
||||
6. Install the `rippled` software package:
|
||||
|
||||
sudo apt -y install rippled
|
||||
|
||||
7. Check the status of the `rippled` service:
|
||||
|
||||
systemctl status rippled.service
|
||||
|
||||
The `rippled` service should start automatically. If not, you can start it manually:
|
||||
|
||||
sudo systemctl start rippled.service
|
||||
|
||||
8. Optional: allow `rippled` to bind to privileged ports.
|
||||
|
||||
This allows you to serve incoming API requests on port 80 or 443. (If you want to do so, you must also update the config file's port settings.)
|
||||
|
||||
sudo setcap 'cap_net_bind_service=+ep' /opt/ripple/bin/rippled
|
||||
|
||||
|
||||
## With the YUM package manager
|
||||
|
||||
1. Install the Ripple RPM repository:
|
||||
|
||||
Choose the appropriate RPM repository for the stability of releases you want:
|
||||
|
||||
- `stable` for the latest production release (`master` branch)
|
||||
- `unstable` for pre-release builds (`release` branch)
|
||||
- `nightly` for experimental/development builds (`develop` branch)
|
||||
|
||||
*Stable*
|
||||
|
||||
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
|
||||
[ripple-stable]
|
||||
name=XRP Ledger Packages
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/stable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
*Unstable*
|
||||
|
||||
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
|
||||
[ripple-unstable]
|
||||
name=XRP Ledger Packages
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/unstable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/unstable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
*Nightly*
|
||||
|
||||
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
|
||||
[ripple-nightly]
|
||||
name=XRP Ledger Packages
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/nightly/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/nightly/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
2. Fetch the latest repo updates:
|
||||
|
||||
sudo yum -y update
|
||||
|
||||
3. Install the new `rippled` package:
|
||||
|
||||
sudo yum install -y rippled
|
||||
|
||||
4. Configure the `rippled` service to start on boot:
|
||||
|
||||
sudo systemctl enable rippled.service
|
||||
|
||||
5. Start the `rippled` service:
|
||||
|
||||
sudo systemctl start rippled.service
|
||||
After the systemd service file is installed, it must be loaded with: `systemctl daemon-reload`. xahaud can then be enabled: `systemctl enable --now xahaud`.
|
||||
|
||||
@@ -82,7 +82,7 @@ sto_erase(
|
||||
uint32_t field_id);
|
||||
|
||||
extern int64_t
|
||||
etxn_burden(void);
|
||||
etxn_burden();
|
||||
|
||||
extern int64_t
|
||||
etxn_details(uint32_t write_ptr, uint32_t write_len);
|
||||
@@ -94,7 +94,7 @@ extern int64_t
|
||||
etxn_reserve(uint32_t count);
|
||||
|
||||
extern int64_t
|
||||
etxn_generation(void);
|
||||
etxn_generation();
|
||||
|
||||
extern int64_t
|
||||
etxn_nonce(uint32_t write_ptr, uint32_t write_len);
|
||||
@@ -149,7 +149,7 @@ extern int64_t
|
||||
float_divide(int64_t float1, int64_t float2);
|
||||
|
||||
extern int64_t
|
||||
float_one(void);
|
||||
float_one();
|
||||
|
||||
extern int64_t
|
||||
float_mantissa(int64_t float1);
|
||||
@@ -167,13 +167,13 @@ extern int64_t
|
||||
float_root(int64_t float1, uint32_t n);
|
||||
|
||||
extern int64_t
|
||||
fee_base(void);
|
||||
fee_base();
|
||||
|
||||
extern int64_t
|
||||
ledger_seq(void);
|
||||
ledger_seq();
|
||||
|
||||
extern int64_t
|
||||
ledger_last_time(void);
|
||||
ledger_last_time();
|
||||
|
||||
extern int64_t
|
||||
ledger_last_hash(uint32_t write_ptr, uint32_t write_len);
|
||||
@@ -213,13 +213,13 @@ hook_param(
|
||||
uint32_t read_len);
|
||||
|
||||
extern int64_t
|
||||
hook_again(void);
|
||||
hook_again();
|
||||
|
||||
extern int64_t
|
||||
hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags);
|
||||
|
||||
extern int64_t
|
||||
hook_pos(void);
|
||||
hook_pos();
|
||||
|
||||
extern int64_t
|
||||
slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
|
||||
@@ -299,19 +299,19 @@ extern int64_t
|
||||
trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1);
|
||||
|
||||
extern int64_t
|
||||
otxn_burden(void);
|
||||
otxn_burden();
|
||||
|
||||
extern int64_t
|
||||
otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
|
||||
|
||||
extern int64_t
|
||||
otxn_generation(void);
|
||||
otxn_generation();
|
||||
|
||||
extern int64_t
|
||||
otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags);
|
||||
|
||||
extern int64_t
|
||||
otxn_type(void);
|
||||
otxn_type();
|
||||
|
||||
extern int64_t
|
||||
otxn_slot(uint32_t slot_no);
|
||||
@@ -329,5 +329,12 @@ meta_slot(uint32_t slot_no);
|
||||
extern int64_t
|
||||
xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta);
|
||||
|
||||
extern int64_t
|
||||
prepare(
|
||||
uint32_t write_ptr,
|
||||
uint32_t write_len,
|
||||
uint32_t read_ptr,
|
||||
uint32_t read_len);
|
||||
|
||||
#define HOOK_EXTERN
|
||||
#endif // HOOK_EXTERN
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd)
|
||||
|
||||
APPLY_HOOK="$SCRIPT_DIR/../src/xrpld/app/hook/applyHook.h"
|
||||
APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
|
||||
|
||||
{
|
||||
echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/'
|
||||
@@ -19,127 +19,36 @@ APPLY_HOOK="$SCRIPT_DIR/../src/xrpld/app/hook/applyHook.h"
|
||||
return s;
|
||||
}
|
||||
|
||||
function emit(ret, name, argc, argt, argn) {
|
||||
attr = (name == "_g") ? " __attribute__((noduplicate))" : "";
|
||||
if (!first)
|
||||
printf("\n");
|
||||
first = 0;
|
||||
printf("extern %s%s\n", ret, attr);
|
||||
if (argc == 0) {
|
||||
printf("%s(void);\n", name);
|
||||
return;
|
||||
}
|
||||
if (argc <= 3) {
|
||||
line = argt[1] " " argn[1];
|
||||
for (i = 2; i <= argc; ++i)
|
||||
line = line ", " argt[i] " " argn[i];
|
||||
printf("%s(%s);\n", name, line);
|
||||
return;
|
||||
}
|
||||
printf("%s(\n", name);
|
||||
for (i = 1; i <= argc; ++i) {
|
||||
sep = (i < argc) ? "," : ");";
|
||||
printf(" %s %s%s\n", argt[i], argn[i], sep);
|
||||
}
|
||||
}
|
||||
|
||||
function process(buffer, kind, payload, parts, n, i, arg, tokens, argc, argt, argn) {
|
||||
if (kind == "func")
|
||||
sub(/^DECLARE_HOOK_FUNCTION[[:space:]]*\(/, "", buffer);
|
||||
else
|
||||
sub(/^DECLARE_HOOK_FUNCNARG[[:space:]]*\(/, "", buffer);
|
||||
buffer = trim(buffer);
|
||||
sub(/\)[[:space:]]*$/, "", buffer);
|
||||
n = split(buffer, parts, ",");
|
||||
for (i = 1; i <= n; ++i)
|
||||
parts[i] = trim(parts[i]);
|
||||
ret = parts[1];
|
||||
name = parts[2];
|
||||
argc = 0;
|
||||
delete argt;
|
||||
delete argn;
|
||||
for (i = 3; i <= n; ++i) {
|
||||
arg = parts[i];
|
||||
if (arg == "")
|
||||
continue;
|
||||
split(arg, tokens, /[[:space:]]+/);
|
||||
if (length(tokens) < 2)
|
||||
continue;
|
||||
++argc;
|
||||
argt[argc] = tokens[1];
|
||||
argn[argc] = tokens[2];
|
||||
}
|
||||
emit(ret, name, argc, argt, argn);
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
first = 1;
|
||||
in_block = 0;
|
||||
in_macro = 0;
|
||||
}
|
||||
|
||||
{
|
||||
line = $0;
|
||||
if (in_block) {
|
||||
if (line ~ /\*\//) {
|
||||
sub(/.*\*\//, "", line);
|
||||
in_block = 0;
|
||||
}
|
||||
else
|
||||
next;
|
||||
}
|
||||
while (line ~ /\/\*/) {
|
||||
if (line ~ /\/\*.*\*\//) {
|
||||
gsub(/\/\*.*\*\//, "", line);
|
||||
}
|
||||
else {
|
||||
sub(/\/\*.*/, "", line);
|
||||
in_block = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sub(/\/\/.*$/, "", line);
|
||||
line = trim(line);
|
||||
if (line == "")
|
||||
next;
|
||||
|
||||
if (!in_macro && line ~ /^DECLARE_HOOK_FUNCTION\(/) {
|
||||
buffer = line;
|
||||
kind = "func";
|
||||
if (line ~ /\);[[:space:]]*$/) {
|
||||
sub(/\);[[:space:]]*$/, "", buffer);
|
||||
process(buffer, kind);
|
||||
}
|
||||
else
|
||||
in_macro = 1;
|
||||
|
||||
# Skip block comments
|
||||
if (line ~ /\/\*/) {
|
||||
next;
|
||||
}
|
||||
if (!in_macro && line ~ /^DECLARE_HOOK_FUNCNARG\(/) {
|
||||
buffer = line;
|
||||
kind = "narg";
|
||||
if (line ~ /\);[[:space:]]*$/) {
|
||||
sub(/\);[[:space:]]*$/, "", buffer);
|
||||
process(buffer, kind);
|
||||
|
||||
# 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);
|
||||
|
||||
# Check if function name is "_g" to add attribute
|
||||
if (line ~ /[[:space:]]+_g[[:space:]]*\(/) {
|
||||
# Insert __attribute__((noduplicate)) before _g
|
||||
sub(/[[:space:]]+_g/, " __attribute__((noduplicate)) _g", line);
|
||||
}
|
||||
else
|
||||
in_macro = 1;
|
||||
next;
|
||||
|
||||
# printf("\n");
|
||||
|
||||
printf("extern %s\n\n", line);
|
||||
}
|
||||
if (in_macro) {
|
||||
buffer = buffer " " line;
|
||||
if (line ~ /\);[[:space:]]*$/) {
|
||||
sub(/\);[[:space:]]*$/, "", buffer);
|
||||
process(buffer, kind);
|
||||
in_macro = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
printf("\n");
|
||||
}
|
||||
' "$APPLY_HOOK"
|
||||
|
||||
echo '#define HOOK_EXTERN'
|
||||
echo '#endif // HOOK_EXTERN'
|
||||
}
|
||||
} | (
|
||||
cd "$SCRIPT_DIR/.."
|
||||
clang-format --style=file -
|
||||
)
|
||||
|
||||
@@ -152,12 +152,13 @@
|
||||
#define sfEscrowID ((5U << 16U) + 35U)
|
||||
#define sfURITokenID ((5U << 16U) + 36U)
|
||||
#define sfDomainID ((5U << 16U) + 37U)
|
||||
#define sfParentBatchID ((5U << 16U) + 38U)
|
||||
#define sfGovernanceFlags ((5U << 16U) + 99U)
|
||||
#define sfGovernanceMarks ((5U << 16U) + 98U)
|
||||
#define sfEmittedTxnID ((5U << 16U) + 97U)
|
||||
#define sfHookCanEmit ((5U << 16U) + 96U)
|
||||
#define sfHookOnOutgoing ((5U << 16U) + 93U)
|
||||
#define sfHookOnIncoming ((5U << 16U) + 94U)
|
||||
#define sfCron ((5U << 16U) + 95U)
|
||||
#define sfHookCanEmit ((5U << 16U) + 96U)
|
||||
#define sfEmittedTxnID ((5U << 16U) + 97U)
|
||||
#define sfGovernanceMarks ((5U << 16U) + 98U)
|
||||
#define sfGovernanceFlags ((5U << 16U) + 99U)
|
||||
#define sfNumber ((9U << 16U) + 1U)
|
||||
#define sfAmount ((6U << 16U) + 1U)
|
||||
#define sfBalance ((6U << 16U) + 2U)
|
||||
@@ -285,8 +286,6 @@
|
||||
#define sfXChainCreateAccountAttestationCollectionElement ((14U << 16U) + 31U)
|
||||
#define sfPriceData ((14U << 16U) + 32U)
|
||||
#define sfCredential ((14U << 16U) + 33U)
|
||||
#define sfRawTransaction ((14U << 16U) + 34U)
|
||||
#define sfBatchSigner ((14U << 16U) + 35U)
|
||||
#define sfAmountEntry ((14U << 16U) + 91U)
|
||||
#define sfMintURIToken ((14U << 16U) + 92U)
|
||||
#define sfHookEmission ((14U << 16U) + 93U)
|
||||
@@ -316,12 +315,9 @@
|
||||
#define sfAuthorizeCredentials ((15U << 16U) + 26U)
|
||||
#define sfUnauthorizeCredentials ((15U << 16U) + 27U)
|
||||
#define sfAcceptedCredentials ((15U << 16U) + 28U)
|
||||
#define sfPermissions ((15U << 16U) + 29U)
|
||||
#define sfRawTransactions ((15U << 16U) + 30U)
|
||||
#define sfBatchSigners ((15U << 16U) + 31U)
|
||||
#define sfRemarks ((15U << 16U) + 97U)
|
||||
#define sfGenesisMints ((15U << 16U) + 96U)
|
||||
#define sfActiveValidators ((15U << 16U) + 95U)
|
||||
#define sfImportVLKeys ((15U << 16U) + 94U)
|
||||
#define sfHookEmissions ((15U << 16U) + 93U)
|
||||
#define sfAmounts ((15U << 16U) + 92U)
|
||||
#define sfHookEmissions ((15U << 16U) + 93U)
|
||||
#define sfImportVLKeys ((15U << 16U) + 94U)
|
||||
#define sfActiveValidators ((15U << 16U) + 95U)
|
||||
#define sfGenesisMints ((15U << 16U) + 96U)
|
||||
#define sfRemarks ((15U << 16U) + 97U)
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
#define ttNFTOKEN_MODIFY 70
|
||||
#define ttPERMISSIONED_DOMAIN_SET 71
|
||||
#define ttPERMISSIONED_DOMAIN_DELETE 72
|
||||
#define ttBATCH 73
|
||||
#define ttCRON 92
|
||||
#define ttCRON_SET 93
|
||||
#define ttREMARKS_SET 94
|
||||
|
||||
@@ -230,7 +230,8 @@ public:
|
||||
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
|
||||
constexpr Expected(Unexpected<U> e) : Base(E(std::move(e.value())))
|
||||
constexpr Expected(Unexpected<U> e)
|
||||
: Base(boost::outcome_v2::failure(E(std::move(e.value()))))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,29 @@
|
||||
#include <vector>
|
||||
#ifndef HOOKENUM_INCLUDED
|
||||
#define HOOKENUM_INCLUDED 1
|
||||
|
||||
#ifndef GUARD_CHECKER_BUILD
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#else
|
||||
// Override uint256, Feature and Rules for guard checker build
|
||||
#define uint256 std::string
|
||||
#define featureHooksUpdate1 "1"
|
||||
#define featureHooksUpdate2 "1"
|
||||
#define fix20250131 "1"
|
||||
namespace hook_api {
|
||||
struct Rules
|
||||
{
|
||||
constexpr bool
|
||||
enabled(const uint256& feature) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace hook_api
|
||||
#endif
|
||||
|
||||
namespace ripple {
|
||||
enum HookSetOperation : int8_t {
|
||||
hsoINVALID = -1,
|
||||
@@ -241,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?
|
||||
};
|
||||
@@ -278,7 +304,17 @@ enum keylet_code : uint32_t {
|
||||
NFT_OFFER = 23,
|
||||
HOOK_DEFINITION = 24,
|
||||
HOOK_STATE_DIR = 25,
|
||||
CRON = 26
|
||||
CRON = 26,
|
||||
AMM = 27,
|
||||
BRIDGE = 28,
|
||||
XCHAIN_OWNED_CLAIM_ID = 29,
|
||||
XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID = 30,
|
||||
DID = 31,
|
||||
ORACLE = 32,
|
||||
MPTOKEN_ISSUANCE = 33,
|
||||
MPTOKEN = 34,
|
||||
CREDENTIAL = 35,
|
||||
PERMISSIONED_DOMAIN = 36,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -358,6 +394,15 @@ enum ExitType : uint8_t {
|
||||
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;
|
||||
@@ -367,110 +412,63 @@ const uint8_t max_emit = 255;
|
||||
const uint8_t max_params = 16;
|
||||
const double fee_base_multiplier = 1.1f;
|
||||
|
||||
#define I32 0x7FU
|
||||
#define I64 0x7EU
|
||||
|
||||
#define HOOK_WRAP_PARAMS(...) __VA_ARGS__
|
||||
#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE) \
|
||||
{ \
|
||||
#FUNCTION_NAME, \
|
||||
{ \
|
||||
RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE \
|
||||
} \
|
||||
}
|
||||
|
||||
using APIWhitelist = std::map<std::string, std::vector<uint8_t>>;
|
||||
|
||||
// RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and
|
||||
// hookapi.h (include for hooks) this is a map of the api name to its return
|
||||
// code (vec[0] and its parameters vec[>0]) as wasm type codes
|
||||
static const APIWhitelist import_whitelist{
|
||||
// clang-format off
|
||||
HOOK_API_DEFINITION(I32, _g, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, accept, (I32, I32, I64)),
|
||||
HOOK_API_DEFINITION(I64, rollback, (I32, I32, I64)),
|
||||
HOOK_API_DEFINITION(I64, util_raddr, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, util_accid, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, util_verify, (I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, util_sha512h, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, util_keylet, (I32, I32, I32, I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, sto_validate, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, sto_subfield, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, sto_subarray, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, sto_emplace, (I32, I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, sto_erase, (I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, etxn_burden, ()),
|
||||
HOOK_API_DEFINITION(I64, etxn_details, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, etxn_fee_base, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, etxn_reserve, (I32)),
|
||||
HOOK_API_DEFINITION(I64, etxn_generation, ()),
|
||||
HOOK_API_DEFINITION(I64, etxn_nonce, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, emit, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_set, (I32, I64)),
|
||||
HOOK_API_DEFINITION(I64, float_multiply, (I64, I64)),
|
||||
HOOK_API_DEFINITION(I64, float_mulratio, (I64, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_negate, (I64)),
|
||||
HOOK_API_DEFINITION(I64, float_compare, (I64, I64, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_sum, (I64, I64)),
|
||||
HOOK_API_DEFINITION(I64, float_sto, (I32, I32, I32, I32, I32, I32, I64, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_sto_set, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_invert, (I64)),
|
||||
HOOK_API_DEFINITION(I64, float_divide, (I64, I64)),
|
||||
HOOK_API_DEFINITION(I64, float_one, ()),
|
||||
HOOK_API_DEFINITION(I64, float_mantissa, (I64)),
|
||||
HOOK_API_DEFINITION(I64, float_sign, (I64)),
|
||||
HOOK_API_DEFINITION(I64, float_int, (I64, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, float_log, (I64)),
|
||||
HOOK_API_DEFINITION(I64, float_root, (I64, I32)),
|
||||
HOOK_API_DEFINITION(I64, fee_base, ()),
|
||||
HOOK_API_DEFINITION(I64, ledger_seq, ()),
|
||||
HOOK_API_DEFINITION(I64, ledger_last_time, ()),
|
||||
HOOK_API_DEFINITION(I64, ledger_last_hash, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, ledger_nonce, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, ledger_keylet, (I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_account, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_hash, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_param_set, (I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_param, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_again, ()),
|
||||
HOOK_API_DEFINITION(I64, hook_skip, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, hook_pos, ()),
|
||||
HOOK_API_DEFINITION(I64, slot, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_clear, (I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_count, (I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_set, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_size, (I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_subarray, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_subfield, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_type, (I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, slot_float, (I32)),
|
||||
HOOK_API_DEFINITION(I64, state_set, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, state_foreign_set, (I32, I32, I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, state, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, state_foreign, (I32, I32, I32, I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, trace, (I32, I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, trace_num, (I32, I32, I64)),
|
||||
HOOK_API_DEFINITION(I64, trace_float, (I32, I32, I64)),
|
||||
HOOK_API_DEFINITION(I64, otxn_burden, ()),
|
||||
HOOK_API_DEFINITION(I64, otxn_field, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, otxn_generation, ()),
|
||||
HOOK_API_DEFINITION(I64, otxn_id, (I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, otxn_type, ()),
|
||||
HOOK_API_DEFINITION(I64, otxn_slot, (I32)),
|
||||
HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)),
|
||||
HOOK_API_DEFINITION(I64, meta_slot, (I32)),
|
||||
// clang-format on
|
||||
};
|
||||
inline APIWhitelist
|
||||
getImportWhitelist(Rules const& rules)
|
||||
{
|
||||
APIWhitelist whitelist;
|
||||
|
||||
// featureHooks1
|
||||
static const APIWhitelist import_whitelist_1{
|
||||
// clang-format off
|
||||
HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)),
|
||||
// clang-format on
|
||||
};
|
||||
#pragma push_macro("HOOK_API_DEFINITION")
|
||||
#undef HOOK_API_DEFINITION
|
||||
|
||||
#define int64_t 0x7EU
|
||||
#define int32_t 0x7FU
|
||||
#define uint32_t 0x7FU
|
||||
|
||||
#define HOOK_WRAP_PARAMS(...) __VA_ARGS__
|
||||
|
||||
#define HOOK_API_DEFINITION( \
|
||||
RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \
|
||||
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"
|
||||
|
||||
#undef HOOK_API_DEFINITION
|
||||
#undef HOOK_WRAP_PARAMS
|
||||
#undef int64_t
|
||||
#undef int32_t
|
||||
#undef uint32_t
|
||||
#pragma pop_macro("HOOK_API_DEFINITION")
|
||||
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
#undef HOOK_API_DEFINITION
|
||||
#undef I32
|
||||
#undef I64
|
||||
|
||||
enum GuardRulesVersion : uint64_t {
|
||||
GuardRuleFix20250131 = 0x00000001,
|
||||
};
|
||||
|
||||
inline uint64_t
|
||||
getGuardRulesVersion(Rules const& rules)
|
||||
{
|
||||
uint64_t version = 0;
|
||||
if (rules.enabled(fix20250131))
|
||||
version |= GuardRuleFix20250131;
|
||||
return version;
|
||||
}
|
||||
|
||||
}; // namespace hook_api
|
||||
#endif
|
||||
|
||||
@@ -634,7 +634,7 @@ check_guard(
|
||||
}
|
||||
else if (fc_type == 10) // memory.copy
|
||||
{
|
||||
if (rulesVersion & 0x02U)
|
||||
if (rulesVersion & hook_api::GuardRuleFix20250131)
|
||||
GUARD_ERROR("Memory.copy instruction is not allowed.");
|
||||
|
||||
REQUIRE(2);
|
||||
@@ -642,7 +642,7 @@ check_guard(
|
||||
}
|
||||
else if (fc_type == 11) // memory.fill
|
||||
{
|
||||
if (rulesVersion & 0x02U)
|
||||
if (rulesVersion & hook_api::GuardRuleFix20250131)
|
||||
GUARD_ERROR("Memory.fill instruction is not allowed.");
|
||||
|
||||
ADVANCE(1);
|
||||
@@ -826,6 +826,7 @@ validateGuards(
|
||||
std::vector<uint8_t> const& wasm,
|
||||
GuardLog guardLog,
|
||||
std::string guardLogAccStr,
|
||||
hook_api::APIWhitelist const import_whitelist,
|
||||
/* RH NOTE:
|
||||
* rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02
|
||||
* and update 3 is 0x04 ideally at rule version 3 all bits so far are set
|
||||
@@ -835,7 +836,7 @@ validateGuards(
|
||||
* might have unforeseen consequences, without also rolling back further
|
||||
* changes that are fine.
|
||||
*/
|
||||
uint64_t rulesVersion = 0)
|
||||
uint64_t rulesVersion = 0x00)
|
||||
{
|
||||
uint64_t byteCount = wasm.size();
|
||||
|
||||
@@ -1020,31 +1021,24 @@ validateGuards(
|
||||
int type_idx = parseLeb128(wasm, i, &i);
|
||||
CHECK_SHORT_HOOK();
|
||||
|
||||
auto it = import_whitelist.find(import_name);
|
||||
auto it_end = import_whitelist.end();
|
||||
bool found_in_whitelist = (it != it_end);
|
||||
|
||||
if (import_name == "_g")
|
||||
{
|
||||
guard_import_number = func_upto;
|
||||
}
|
||||
else if (
|
||||
hook_api::import_whitelist.find(import_name) ==
|
||||
hook_api::import_whitelist.end())
|
||||
if (!found_in_whitelist)
|
||||
{
|
||||
if (rulesVersion > 0 &&
|
||||
hook_api::import_whitelist_1.find(import_name) !=
|
||||
hook_api::import_whitelist_1.end())
|
||||
{
|
||||
// PASS, this is a version 1 api
|
||||
}
|
||||
else
|
||||
{
|
||||
GUARDLOG(hook::log::IMPORT_ILLEGAL)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook attempted to import a function that does "
|
||||
"not "
|
||||
<< "appear in the hook_api function set: `"
|
||||
<< import_name << "`"
|
||||
<< "\n";
|
||||
return {};
|
||||
}
|
||||
GUARDLOG(hook::log::IMPORT_ILLEGAL)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook attempted to import a function that does "
|
||||
"not "
|
||||
<< "appear in the hook_api function set: `"
|
||||
<< import_name << "`"
|
||||
<< "\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
// add to import map
|
||||
@@ -1259,11 +1253,7 @@ validateGuards(
|
||||
for (auto const& [import_idx, api_name] : usage->second)
|
||||
{
|
||||
auto const& api_signature =
|
||||
hook_api::import_whitelist.find(api_name) !=
|
||||
hook_api::import_whitelist.end()
|
||||
? hook_api::import_whitelist.find(api_name)->second
|
||||
: hook_api::import_whitelist_1.find(api_name)
|
||||
->second;
|
||||
import_whitelist.find(api_name)->second;
|
||||
|
||||
if (!first_signature)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) \
|
||||
N
|
||||
#define VA_NARGS(__drop, ...) \
|
||||
VA_NARGS_IMPL(__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
VA_NARGS_IMPL( \
|
||||
__VA_OPT__(__VA_ARGS__, ) 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#define FIRST(a, b) a
|
||||
#define SECOND(a, b) b
|
||||
#define STRIP_TYPES(...) FOR_VARS(SECOND, 0, __VA_ARGS__)
|
||||
@@ -66,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++])
|
||||
@@ -88,96 +90,174 @@
|
||||
|
||||
#define WASM_VAL_TYPE(T, b) CAT2(TYP_, T)
|
||||
|
||||
#define DECLARE_HOOK_FUNCTION(R, F, ...) \
|
||||
R F(hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx, \
|
||||
__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(...) \
|
||||
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 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 DECLARE_HOOK_FUNCNARG(R, F) \
|
||||
R F(hook::HookContext& hookCtx, \
|
||||
WasmEdge_CallingFrameContext const& frameCtx); \
|
||||
extern WasmEdge_Result WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out); \
|
||||
extern WasmEdge_ValType WasmFunctionResult##F[]; \
|
||||
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
|
||||
extern WasmEdge_String WasmFunctionName##F;
|
||||
#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_HOOK_FUNCTION(R, F, ...) \
|
||||
#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) \
|
||||
{ \
|
||||
int _stack = 0; \
|
||||
FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__); \
|
||||
__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), \
|
||||
STRIP_TYPES(__VA_ARGS__)); \
|
||||
*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[] = { \
|
||||
FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__)}; \
|
||||
__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_ARGS__), \
|
||||
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_ARGS__)
|
||||
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
|
||||
COMMA __VA_ARGS__))
|
||||
|
||||
#define DEFINE_HOOK_FUNCNARG(R, F) \
|
||||
WasmEdge_Result hook_api::WasmFunction##F( \
|
||||
void* data_ptr, \
|
||||
const WasmEdge_CallingFrameContext* frameCtx, \
|
||||
const WasmEdge_Value* in, \
|
||||
WasmEdge_Value* out) \
|
||||
#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) \
|
||||
{ \
|
||||
hook::HookContext* hookCtx = \
|
||||
reinterpret_cast<hook::HookContext*>(data_ptr); \
|
||||
R return_code = hook_api::F( \
|
||||
*hookCtx, *const_cast<WasmEdge_CallingFrameContext*>(frameCtx)); \
|
||||
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \
|
||||
return WasmEdge_Result_Terminate; \
|
||||
out[0] = CAT2(RET_, R(return_code)); \
|
||||
return WasmEdge_Result_Success; \
|
||||
}; \
|
||||
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
|
||||
WASM_VAL_TYPE(R, dummy)}; \
|
||||
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
|
||||
WasmEdge_FunctionTypeCreate({}, 0, 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__(int _stack = 0;) \
|
||||
__VA_OPT__(FOR_VARS(VAR_JSASSIGN, 2, __VA_ARGS__);)
|
||||
|
||||
#define HOOK_SETUP() \
|
||||
#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; \
|
||||
@@ -190,17 +270,18 @@
|
||||
[[maybe_unused]] const uint64_t memory_length = \
|
||||
WasmEdge_MemoryInstanceGetPageSize(memoryCtx) * \
|
||||
WasmEdge_kPageSize; \
|
||||
[[maybe_unused]] auto& api = hookCtx.api(); \
|
||||
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( \
|
||||
@@ -294,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) \
|
||||
{ \
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define GUARD_CHECKER_BUILD
|
||||
#include "Enum.h"
|
||||
#include "Guard.h"
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
@@ -79,7 +81,15 @@ main(int argc, char** argv)
|
||||
|
||||
close(fd);
|
||||
|
||||
auto result = validateGuards(hook, std::cout, "", 3);
|
||||
// Dummy rules for guard checker build
|
||||
hook_api::Rules rules;
|
||||
|
||||
auto result = validateGuards(
|
||||
hook,
|
||||
std::cout,
|
||||
"",
|
||||
hook_api::getImportWhitelist(rules),
|
||||
hook_api::getGuardRulesVersion(rules));
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
682
include/xrpl/hook/hook_api.macro
Normal file
682
include/xrpl/hook/hook_api.macro
Normal file
@@ -0,0 +1,682 @@
|
||||
// int32_t _g(uint32_t guard_id, uint32_t maxiter);
|
||||
HOOK_API_DEFINITION(
|
||||
int32_t, _g, (uint32_t, uint32_t),
|
||||
uint256{})
|
||||
|
||||
// int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
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(
|
||||
int64_t, trace_num, (uint32_t, uint32_t, int64_t),
|
||||
uint256{})
|
||||
|
||||
// int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1);
|
||||
HOOK_API_DEFINITION(
|
||||
int64_t, trace_float, (uint32_t, uint32_t, int64_t),
|
||||
uint256{})
|
||||
|
||||
// int64_t otxn_burden();
|
||||
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{})
|
||||
@@ -1,37 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2024 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.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
inline void
|
||||
serializeBatch(
|
||||
Serializer& msg,
|
||||
std::uint32_t const& flags,
|
||||
std::vector<uint256> const& txids)
|
||||
{
|
||||
msg.add32(HashPrefix::batch);
|
||||
msg.add32(flags);
|
||||
msg.add32(std::uint32_t(txids.size()));
|
||||
for (auto const& txid : txids)
|
||||
msg.addBitString(txid);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -80,7 +80,7 @@ namespace detail {
|
||||
// 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 = 111;
|
||||
static constexpr std::size_t numFeatures = 114;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
|
||||
@@ -96,9 +96,6 @@ enum class HashPrefix : std::uint32_t {
|
||||
|
||||
/** Credentials signature */
|
||||
credential = detail::make_hash_prefix('C', 'R', 'D'),
|
||||
|
||||
/** Batch */
|
||||
batch = detail::make_hash_prefix('B', 'C', 'H'),
|
||||
};
|
||||
|
||||
template <class Hasher>
|
||||
|
||||
@@ -97,6 +97,12 @@ public:
|
||||
|
||||
static IOUAmount
|
||||
minPositiveAmount();
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, IOUAmount const& x)
|
||||
{
|
||||
return os << to_string(x);
|
||||
}
|
||||
};
|
||||
|
||||
inline IOUAmount::IOUAmount(beast::Zero)
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#ifndef RIPPLE_PROTOCOL_IMPORT_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_IMPORT_H_INCLUDED
|
||||
|
||||
// #include <ripple/basics/Log.h>
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
|
||||
@@ -147,8 +147,9 @@ enum LedgerSpecificFlags {
|
||||
0x40000000, // True, has minted tokens in the past
|
||||
lsfDisallowIncomingRemit = // True, no remits allowed to this account
|
||||
0x80000000,
|
||||
lsfAllowTrustLineClawback =
|
||||
0x00001000, // True, enable clawback
|
||||
// 0x0004000 is available
|
||||
lsfAllowTrustLineClawback =
|
||||
0x00001000, // True, enable clawback
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
@@ -163,10 +164,10 @@ enum LedgerSpecificFlags {
|
||||
lsfHighNoRipple = 0x00200000,
|
||||
lsfLowFreeze = 0x00400000, // True, low side has set freeze flag
|
||||
lsfHighFreeze = 0x00800000, // True, high side has set freeze flag
|
||||
lsfAMMNode = 0x01000000, // True, trust line to AMM. Used by client
|
||||
// apps to identify payments via AMM.
|
||||
lsfLowDeepFreeze = 0x02000000, // True, low side has set deep freeze flag
|
||||
lsfHighDeepFreeze = 0x04000000, // True, high side has set deep freeze flag
|
||||
lsfAMMNode = 0x01000000, // True, trust line to AMM. Used by client
|
||||
// apps to identify payments via AMM.
|
||||
|
||||
// ltSIGNER_LIST
|
||||
lsfOneOwnerCount = 0x00010000, // True, uses only one OwnerCount
|
||||
|
||||
@@ -154,13 +154,6 @@ std::size_t constexpr maxPriceScale = 20;
|
||||
*/
|
||||
std::size_t constexpr maxTrim = 25;
|
||||
|
||||
/** The maximum number of delegate permissions an account can grant
|
||||
*/
|
||||
std::size_t constexpr permissionMaxSize = 10;
|
||||
|
||||
/** The maximum number of transactions that can be in a batch. */
|
||||
std::size_t constexpr maxBatchTxCount = 8;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool
|
||||
isFeatureEnabled(uint256 const& feature);
|
||||
|
||||
class DigestAwareReadView;
|
||||
|
||||
/** Rules controlling protocol behavior. */
|
||||
|
||||
@@ -120,16 +120,10 @@ public:
|
||||
@return `true` if valid signature. If invalid, the error message string.
|
||||
*/
|
||||
enum class RequireFullyCanonicalSig : bool { no, yes };
|
||||
|
||||
Expected<void, std::string>
|
||||
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
|
||||
const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkBatchSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
// SQL Functions with metadata.
|
||||
static std::string const&
|
||||
getMetaSQLInsertReplaceHeader();
|
||||
@@ -145,9 +139,6 @@ public:
|
||||
char status,
|
||||
std::string const& escapedMetaData) const;
|
||||
|
||||
std::vector<uint256>
|
||||
getBatchTransactionIDs() const;
|
||||
|
||||
private:
|
||||
Expected<void, std::string>
|
||||
checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const;
|
||||
@@ -157,24 +148,12 @@ private:
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkBatchSingleSign(
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkBatchMultiSign(
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
STBase*
|
||||
copy(std::size_t n, void* buf) const override;
|
||||
STBase*
|
||||
move(std::size_t n, void* buf) override;
|
||||
|
||||
friend class detail::STVar;
|
||||
mutable std::vector<uint256> batch_txn_ids_;
|
||||
};
|
||||
|
||||
bool
|
||||
|
||||
@@ -143,8 +143,8 @@ enum TEMcodes : TERUnderlyingType {
|
||||
|
||||
temARRAY_EMPTY,
|
||||
temARRAY_TOO_LARGE,
|
||||
|
||||
temBAD_TRANSFER_FEE,
|
||||
temINVALID_INNER_BATCH,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -362,6 +362,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecARRAY_TOO_LARGE = 197,
|
||||
tecLOCKED = 198,
|
||||
tecBAD_CREDENTIALS = 199,
|
||||
tecINVALID_HOOK_API_VERSION = 200,
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
@@ -648,27 +649,27 @@ using TER = TERSubset<CanCvtToTER>;
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline bool
|
||||
isTelLocal(TER x) noexcept
|
||||
isTelLocal(TER x)
|
||||
{
|
||||
return (x >= telLOCAL_ERROR && x < temMALFORMED);
|
||||
return ((x) >= telLOCAL_ERROR && (x) < temMALFORMED);
|
||||
}
|
||||
|
||||
inline bool
|
||||
isTemMalformed(TER x) noexcept
|
||||
isTemMalformed(TER x)
|
||||
{
|
||||
return (x >= temMALFORMED && x < tefFAILURE);
|
||||
return ((x) >= temMALFORMED && (x) < tefFAILURE);
|
||||
}
|
||||
|
||||
inline bool
|
||||
isTefFailure(TER x) noexcept
|
||||
isTefFailure(TER x)
|
||||
{
|
||||
return (x >= tefFAILURE && x < terRETRY);
|
||||
return ((x) >= tefFAILURE && (x) < terRETRY);
|
||||
}
|
||||
|
||||
inline bool
|
||||
isTerRetry(TER x) noexcept
|
||||
isTerRetry(TER x)
|
||||
{
|
||||
return (x >= terRETRY && x < tesSUCCESS);
|
||||
return ((x) >= terRETRY && (x) < tesSUCCESS);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -679,13 +680,13 @@ isTesSuccess(T x)
|
||||
}
|
||||
|
||||
inline bool
|
||||
isTesSuccess(TER x) noexcept
|
||||
isTesSuccess(TER x)
|
||||
{
|
||||
return ((x) >= tesSUCCESS) && (x) < tecCLAIM;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isTecClaim(TER x) noexcept
|
||||
isTecClaim(TER x)
|
||||
{
|
||||
return ((x) >= tecCLAIM);
|
||||
}
|
||||
|
||||
@@ -59,9 +59,8 @@ namespace ripple {
|
||||
// Universal Transaction flags:
|
||||
enum UniversalFlags : uint32_t {
|
||||
tfFullyCanonicalSig = 0x80000000,
|
||||
tfInnerBatchTxn = 0x40000000,
|
||||
};
|
||||
constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig | tfInnerBatchTxn;
|
||||
constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig;
|
||||
constexpr std::uint32_t tfUniversalMask = ~tfUniversal;
|
||||
|
||||
// AccountSet flags:
|
||||
@@ -126,7 +125,7 @@ enum TrustSetFlags : uint32_t {
|
||||
tfSetFreeze = 0x00100000,
|
||||
tfClearFreeze = 0x00200000,
|
||||
tfSetDeepFreeze = 0x00400000,
|
||||
tfClearDeepFreeze = 0x00800000,
|
||||
tfClearDeepFreeze = 0x00800000
|
||||
};
|
||||
constexpr std::uint32_t tfTrustSetMask =
|
||||
~(tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple | tfSetFreeze |
|
||||
@@ -275,22 +274,6 @@ enum BridgeModifyFlags : uint32_t {
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
};
|
||||
constexpr std::uint32_t tfBridgeModifyMask = ~(tfUniversal | tfClearAccountCreateAmount);
|
||||
|
||||
// Batch Flags:
|
||||
enum BatchFlags : uint32_t {
|
||||
tfAllOrNothing = 0x00010000,
|
||||
tfOnlyOne = 0x00020000,
|
||||
tfUntilFailure = 0x00040000,
|
||||
tfIndependent = 0x00080000,
|
||||
};
|
||||
/**
|
||||
* @note If nested Batch transactions are supported in the future, the tfInnerBatchTxn flag
|
||||
* will need to be removed from this mask to allow Batch transaction to be inside
|
||||
* the sfRawTransactions array.
|
||||
*/
|
||||
constexpr std::uint32_t const tfBatchMask =
|
||||
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
||||
|
||||
// clang-format on
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -44,10 +44,7 @@ private:
|
||||
CtorHelper);
|
||||
|
||||
public:
|
||||
TxMeta(
|
||||
uint256 const& transactionID,
|
||||
std::uint32_t ledger,
|
||||
std::optional<uint256> parentBatchId = std::nullopt);
|
||||
TxMeta(uint256 const& transactionID, std::uint32_t ledger);
|
||||
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
|
||||
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
|
||||
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
|
||||
@@ -170,27 +167,6 @@ public:
|
||||
return static_cast<bool>(mDelivered);
|
||||
}
|
||||
|
||||
void
|
||||
setParentBatchId(uint256 const& parentBatchId)
|
||||
{
|
||||
mParentBatchId = parentBatchId;
|
||||
}
|
||||
|
||||
uint256
|
||||
getParentBatchId() const
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
hasParentBatchId(),
|
||||
"ripple::TxMeta::getParentBatchId : non-null batch id");
|
||||
return *mParentBatchId;
|
||||
}
|
||||
|
||||
bool
|
||||
hasParentBatchId() const
|
||||
{
|
||||
return static_cast<bool>(mParentBatchId);
|
||||
}
|
||||
|
||||
private:
|
||||
uint256 mTransactionID;
|
||||
std::uint32_t mLedger;
|
||||
@@ -200,7 +176,6 @@ private:
|
||||
std::optional<STAmount> mDelivered;
|
||||
std::optional<STArray> mHookExecutions;
|
||||
std::optional<STArray> mHookEmissions;
|
||||
std::optional<uint256> mParentBatchId;
|
||||
|
||||
STArray mNodes;
|
||||
};
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
#error "undefined macro: XRPL_FIX"
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(JSHooks, 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)
|
||||
XRPL_FEATURE(Credentials, Supported::no, VoteBehavior::DefaultNo)
|
||||
@@ -51,16 +54,18 @@ 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::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_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultYes)
|
||||
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)
|
||||
XRPL_FIX (20250131, Supported::yes, VoteBehavior::DefaultYes)
|
||||
@@ -143,3 +148,4 @@ XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete)
|
||||
XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete)
|
||||
XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -65,7 +65,7 @@ LEDGER_ENTRY_DUPLICATE(ltCRON, 0x0041, Cron, cron, ({
|
||||
{sfRepeatCount, soeREQUIRED},
|
||||
{sfOwnerNode, soeREQUIRED},
|
||||
{sfPreviousTxnID, soeREQUIRED},
|
||||
{sfPreviousTxnLgrSeq, soeREQUIRED}
|
||||
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
||||
}))
|
||||
|
||||
/** A ledger object which describes a check.
|
||||
@@ -94,6 +94,8 @@ LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, ({
|
||||
LEDGER_ENTRY(ltHOOK_DEFINITION, 'D', HookDefinition, hook_definition, ({
|
||||
{sfHookHash, soeREQUIRED},
|
||||
{sfHookOn, soeREQUIRED},
|
||||
{sfHookOnIncoming, soeOPTIONAL},
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
{sfHookNamespace, soeREQUIRED},
|
||||
{sfHookParameters, soeREQUIRED},
|
||||
@@ -130,6 +132,8 @@ LEDGER_ENTRY(ltHOOK, 'H', Hook, hook, ({
|
||||
|
||||
/** The ledger object which records the last (and largest) sequence for a validator list key
|
||||
* as used in the Import amendment
|
||||
|
||||
\sa keylet::import_vlseq
|
||||
*/
|
||||
LEDGER_ENTRY(ltIMPORT_VLSEQ, 0x0049, ImportVLSequence, import_vlseq, ({
|
||||
{sfPublicKey, soeREQUIRED},
|
||||
|
||||
@@ -210,12 +210,13 @@ TYPED_SFIELD(sfOfferID, UINT256, 34)
|
||||
TYPED_SFIELD(sfEscrowID, UINT256, 35)
|
||||
TYPED_SFIELD(sfURITokenID, UINT256, 36)
|
||||
TYPED_SFIELD(sfDomainID, UINT256, 37)
|
||||
TYPED_SFIELD(sfParentBatchID, UINT256, 38)
|
||||
TYPED_SFIELD(sfGovernanceFlags, UINT256, 99)
|
||||
TYPED_SFIELD(sfGovernanceMarks, UINT256, 98)
|
||||
TYPED_SFIELD(sfEmittedTxnID, UINT256, 97)
|
||||
TYPED_SFIELD(sfHookCanEmit, UINT256, 96)
|
||||
TYPED_SFIELD(sfHookOnOutgoing, UINT256, 93)
|
||||
TYPED_SFIELD(sfHookOnIncoming, UINT256, 94)
|
||||
TYPED_SFIELD(sfCron, UINT256, 95)
|
||||
TYPED_SFIELD(sfHookCanEmit, UINT256, 96)
|
||||
TYPED_SFIELD(sfEmittedTxnID, UINT256, 97)
|
||||
TYPED_SFIELD(sfGovernanceMarks, UINT256, 98)
|
||||
TYPED_SFIELD(sfGovernanceFlags, UINT256, 99)
|
||||
|
||||
// number (common)
|
||||
TYPED_SFIELD(sfNumber, NUMBER, 1)
|
||||
@@ -378,8 +379,6 @@ UNTYPED_SFIELD(sfXChainClaimAttestationCollectionElement, OBJECT, 30)
|
||||
UNTYPED_SFIELD(sfXChainCreateAccountAttestationCollectionElement, OBJECT, 31)
|
||||
UNTYPED_SFIELD(sfPriceData, OBJECT, 32)
|
||||
UNTYPED_SFIELD(sfCredential, OBJECT, 33)
|
||||
UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34)
|
||||
UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35)
|
||||
UNTYPED_SFIELD(sfAmountEntry, OBJECT, 91)
|
||||
UNTYPED_SFIELD(sfMintURIToken, OBJECT, 92)
|
||||
UNTYPED_SFIELD(sfHookEmission, OBJECT, 93)
|
||||
@@ -417,12 +416,9 @@ UNTYPED_SFIELD(sfAuthAccounts, ARRAY, 25)
|
||||
UNTYPED_SFIELD(sfAuthorizeCredentials, ARRAY, 26)
|
||||
UNTYPED_SFIELD(sfUnauthorizeCredentials, ARRAY, 27)
|
||||
UNTYPED_SFIELD(sfAcceptedCredentials, ARRAY, 28)
|
||||
UNTYPED_SFIELD(sfPermissions, ARRAY, 29)
|
||||
UNTYPED_SFIELD(sfRawTransactions, ARRAY, 30)
|
||||
UNTYPED_SFIELD(sfBatchSigners, ARRAY, 31, SField::sMD_Default, SField::notSigning)
|
||||
UNTYPED_SFIELD(sfRemarks, ARRAY, 97)
|
||||
UNTYPED_SFIELD(sfGenesisMints, ARRAY, 96)
|
||||
UNTYPED_SFIELD(sfActiveValidators, ARRAY, 95)
|
||||
UNTYPED_SFIELD(sfImportVLKeys, ARRAY, 94)
|
||||
UNTYPED_SFIELD(sfHookEmissions, ARRAY, 93)
|
||||
UNTYPED_SFIELD(sfAmounts, ARRAY, 92)
|
||||
UNTYPED_SFIELD(sfHookEmissions, ARRAY, 93)
|
||||
UNTYPED_SFIELD(sfImportVLKeys, ARRAY, 94)
|
||||
UNTYPED_SFIELD(sfActiveValidators, ARRAY, 95)
|
||||
UNTYPED_SFIELD(sfGenesisMints, ARRAY, 96)
|
||||
UNTYPED_SFIELD(sfRemarks, ARRAY, 97)
|
||||
|
||||
@@ -500,12 +500,6 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 72, PermissionedDomainDelete, ({
|
||||
{sfDomainID, soeREQUIRED},
|
||||
}))
|
||||
|
||||
/** This transaction type batches together transactions. */
|
||||
TRANSACTION(ttBATCH, 73, Batch, ({
|
||||
{sfRawTransactions, soeREQUIRED},
|
||||
{sfBatchSigners, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/* A pseudo-txn alarm signal for invoking a hook, emitted by validators after alarm set conditions are met */
|
||||
TRANSACTION(ttCRON, 92, Cron, ({
|
||||
{sfOwner, soeREQUIRED},
|
||||
|
||||
@@ -78,6 +78,8 @@ JSS(HookCanEmit); // field
|
||||
JSS(HookHash); // field
|
||||
JSS(HookNamespace); // field
|
||||
JSS(HookOn); // field
|
||||
JSS(HookOnIncoming); // field
|
||||
JSS(HookOnOutgoing); // field
|
||||
JSS(Hooks); // field
|
||||
JSS(HookGrants); // field
|
||||
JSS(HookParameters); // field
|
||||
@@ -95,6 +97,7 @@ JSS(Invalid); //
|
||||
JSS(Issuer); // in: Credential transactions
|
||||
JSS(InvoiceID); // field
|
||||
JSS(LastLedgerSequence); // in: TransactionSign; field
|
||||
JSS(FirstLedgerSequence); // in: TransactionSign; field
|
||||
JSS(LastUpdateTime); // field.
|
||||
JSS(LimitAmount); // field.
|
||||
JSS(NetworkID); // field.
|
||||
@@ -109,8 +112,6 @@ JSS(PriceDataSeries); // field.
|
||||
JSS(PriceData); // field.
|
||||
JSS(Provider); // field.
|
||||
JSS(QuoteAsset); // in: Oracle.
|
||||
JSS(RawTransaction); // in: Batch
|
||||
JSS(RawTransactions); // in: BatchJSS(RawTransactions);
|
||||
JSS(SLE_hit_rate); // out: GetCounts.
|
||||
JSS(Scale); // field.
|
||||
JSS(SettleDelay); // in: TransactionSign
|
||||
@@ -121,6 +122,7 @@ JSS(Signer); // field.
|
||||
JSS(Signers); // field.
|
||||
JSS(HookStateData); // field.
|
||||
JSS(HookStateKey); // field.
|
||||
JSS(EmitDetails); // field.
|
||||
JSS(SigningPubKey); // field.
|
||||
JSS(Subject); // in: Credential transactions
|
||||
JSS(TakerGets); // field.
|
||||
|
||||
@@ -129,6 +129,9 @@ ENV CMAKE_EXE_LINKER_FLAGS="-static-libstdc++"
|
||||
ENV LLVM_DIR=/usr/lib64/llvm14/lib/cmake/llvm
|
||||
ENV WasmEdge_LIB=/usr/local/lib64/libwasmedge.a
|
||||
|
||||
ENV CC='ccache gcc'
|
||||
ENV CXX='ccache g++'
|
||||
|
||||
# Install LLD
|
||||
RUN /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && \
|
||||
cd /tmp && \
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#ifdef BEAST_ENHANCED_LOGGING
|
||||
#include <xrpl/beast/utility/EnhancedLogging.h>
|
||||
#include <date/tz.h>
|
||||
#endif
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@@ -92,7 +92,9 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{{sfCreateCode, soeREQUIRED},
|
||||
{sfHookNamespace, soeREQUIRED},
|
||||
{sfHookParameters, soeREQUIRED},
|
||||
{sfHookOn, soeREQUIRED},
|
||||
{sfHookOn, soeOPTIONAL},
|
||||
{sfHookOnIncoming, soeOPTIONAL},
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
{sfHookApiVersion, soeREQUIRED},
|
||||
{sfFlags, soeREQUIRED},
|
||||
@@ -106,8 +108,11 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfHookNamespace, soeOPTIONAL},
|
||||
{sfHookParameters, soeOPTIONAL},
|
||||
{sfHookOn, soeOPTIONAL},
|
||||
{sfHookOnIncoming, soeOPTIONAL},
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
{sfHookApiVersion, soeOPTIONAL},
|
||||
{sfFee, soeOPTIONAL},
|
||||
{sfFlags, soeOPTIONAL}});
|
||||
|
||||
add(sfHookGrant.jsonName,
|
||||
@@ -262,13 +267,6 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfIssuer, soeREQUIRED},
|
||||
{sfCredentialType, soeREQUIRED},
|
||||
});
|
||||
|
||||
add(sfBatchSigner.jsonName.c_str(),
|
||||
sfBatchSigner.getCode(),
|
||||
{{sfAccount, soeREQUIRED},
|
||||
{sfSigningPubKey, soeOPTIONAL},
|
||||
{sfTxnSignature, soeOPTIONAL},
|
||||
{sfSigners, soeOPTIONAL}});
|
||||
}
|
||||
|
||||
InnerObjectFormats const&
|
||||
|
||||
@@ -153,4 +153,12 @@ Rules::operator!=(Rules const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool
|
||||
isFeatureEnabled(uint256 const& feature)
|
||||
{
|
||||
auto const& rules = getCurrentTransactionRules();
|
||||
return rules && rules->enabled(feature);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -17,21 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/hook/Enum.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/json/to_string.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Batch.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
@@ -39,10 +30,6 @@
|
||||
#include <xrpl/protocol/STAccount.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/SeqProxy.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
@@ -243,42 +230,6 @@ STTx::checkSign(
|
||||
return Unexpected("Internal signature check failure.");
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkBatchSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
try
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
getTxnType() == ttBATCH,
|
||||
"STTx::checkBatchSign : not a batch transaction");
|
||||
if (getTxnType() != ttBATCH)
|
||||
{
|
||||
JLOG(debugLog().fatal()) << "not a batch transaction";
|
||||
return Unexpected("Not a batch transaction.");
|
||||
}
|
||||
STArray const& signers{getFieldArray(sfBatchSigners)};
|
||||
for (auto const& signer : signers)
|
||||
{
|
||||
Blob const& signingPubKey = signer.getFieldVL(sfSigningPubKey);
|
||||
auto const result = signingPubKey.empty()
|
||||
? checkBatchMultiSign(signer, requireCanonicalSig, rules)
|
||||
: checkBatchSingleSign(signer, requireCanonicalSig);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
JLOG(debugLog().error())
|
||||
<< "Batch signature check failed: " << e.what();
|
||||
}
|
||||
return Unexpected("Internal batch signature check failure.");
|
||||
}
|
||||
|
||||
Json::Value
|
||||
STTx::getJson(JsonOptions options) const
|
||||
{
|
||||
@@ -358,101 +309,89 @@ STTx::getMetaSQL(
|
||||
getFieldU32(sfSequence) % inLedger % status % rTxn % escapedMetaData);
|
||||
}
|
||||
|
||||
static Expected<void, std::string>
|
||||
singleSignHelper(
|
||||
STObject const& signer,
|
||||
Slice const& data,
|
||||
bool const fullyCanonical)
|
||||
Expected<void, std::string>
|
||||
STTx::checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
{
|
||||
// We don't allow both a non-empty sfSigningPubKey and an sfSigners.
|
||||
// That would allow the transaction to be signed two ways. So if both
|
||||
// fields are present the signature is invalid.
|
||||
if (signer.isFieldPresent(sfSigners))
|
||||
if (isFieldPresent(sfSigners))
|
||||
return Unexpected("Cannot both single- and multi-sign.");
|
||||
|
||||
// wildcard network gets a free pass on all signatures
|
||||
bool const isWildcardNetwork = signer.isFieldPresent(sfNetworkID) &&
|
||||
signer.getFieldU32(sfNetworkID) == 65535;
|
||||
bool const isWildcardNetwork =
|
||||
isFieldPresent(sfNetworkID) && getFieldU32(sfNetworkID) == 65535;
|
||||
|
||||
bool validSig = false;
|
||||
try
|
||||
{
|
||||
auto const spk = signer.getFieldVL(sfSigningPubKey);
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == RequireFullyCanonicalSig::yes);
|
||||
|
||||
auto const spk = getFieldVL(sfSigningPubKey);
|
||||
|
||||
if (publicKeyType(makeSlice(spk)))
|
||||
{
|
||||
Blob const signature = signer.getFieldVL(sfTxnSignature);
|
||||
Blob const signature = getFieldVL(sfTxnSignature);
|
||||
Blob const data = getSigningData(*this);
|
||||
|
||||
validSig = isWildcardNetwork ||
|
||||
verify(PublicKey(makeSlice(spk)),
|
||||
data,
|
||||
makeSlice(data),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
// Assume it was a signature failure.
|
||||
validSig = false;
|
||||
}
|
||||
|
||||
if (!validSig)
|
||||
if (validSig == false)
|
||||
return Unexpected("Invalid signature.");
|
||||
|
||||
// Signature was verified.
|
||||
return {};
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
{
|
||||
auto const data = getSigningData(*this);
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes);
|
||||
return singleSignHelper(*this, makeSlice(data), fullyCanonical);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkBatchSingleSign(
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
{
|
||||
Serializer msg;
|
||||
serializeBatch(msg, getFlags(), getBatchTransactionIDs());
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes);
|
||||
return singleSignHelper(batchSigner, msg.slice(), fullyCanonical);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
multiSignHelper(
|
||||
STObject const& signerObj,
|
||||
bool const fullyCanonical,
|
||||
std::function<Serializer(AccountID const&)> makeMsg,
|
||||
Rules const& rules)
|
||||
STTx::checkMultiSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
// Make sure the MultiSigners are present. Otherwise they are not
|
||||
// attempting multi-signing and we just have a bad SigningPubKey.
|
||||
if (!signerObj.isFieldPresent(sfSigners))
|
||||
if (!isFieldPresent(sfSigners))
|
||||
return Unexpected("Empty SigningPubKey.");
|
||||
|
||||
// We don't allow both an sfSigners and an sfTxnSignature. Both fields
|
||||
// being present would indicate that the transaction is signed both ways.
|
||||
if (signerObj.isFieldPresent(sfTxnSignature))
|
||||
if (isFieldPresent(sfTxnSignature))
|
||||
return Unexpected("Cannot both single- and multi-sign.");
|
||||
|
||||
STArray const& signers{signerObj.getFieldArray(sfSigners)};
|
||||
STArray const& signers{getFieldArray(sfSigners)};
|
||||
|
||||
// There are well known bounds that the number of signers must be within.
|
||||
if (signers.size() < STTx::minMultiSigners ||
|
||||
signers.size() > STTx::maxMultiSigners(&rules))
|
||||
if (signers.size() < minMultiSigners ||
|
||||
signers.size() > maxMultiSigners(&rules))
|
||||
return Unexpected("Invalid Signers array size.");
|
||||
|
||||
// We can ease the computational load inside the loop a bit by
|
||||
// pre-constructing part of the data that we hash. Fill a Serializer
|
||||
// with the stuff that stays constant from signature to signature.
|
||||
Serializer const dataStart{startMultiSigningData(*this)};
|
||||
|
||||
// We also use the sfAccount field inside the loop. Get it once.
|
||||
auto const txnAccountID = signerObj.getAccountID(sfAccount);
|
||||
auto const txnAccountID = getAccountID(sfAccount);
|
||||
|
||||
// Determine whether signatures must be full canonical.
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == RequireFullyCanonicalSig::yes);
|
||||
|
||||
// Signers must be in sorted order by AccountID.
|
||||
AccountID lastAccountID(beast::zero);
|
||||
|
||||
bool const isWildcardNetwork = signerObj.isFieldPresent(sfNetworkID) &&
|
||||
signerObj.getFieldU32(sfNetworkID) == 65535;
|
||||
bool const isWildcardNetwork =
|
||||
isFieldPresent(sfNetworkID) && getFieldU32(sfNetworkID) == 65535;
|
||||
|
||||
for (auto const& signer : signers)
|
||||
{
|
||||
@@ -477,7 +416,11 @@ multiSignHelper(
|
||||
bool validSig = false;
|
||||
try
|
||||
{
|
||||
Serializer s = dataStart;
|
||||
finishMultiSigningData(accountID, s);
|
||||
|
||||
auto spk = signer.getFieldVL(sfSigningPubKey);
|
||||
|
||||
if (publicKeyType(makeSlice(spk)))
|
||||
{
|
||||
Blob const signature = signer.getFieldVL(sfTxnSignature);
|
||||
@@ -485,7 +428,7 @@ multiSignHelper(
|
||||
// wildcard network gets a free pass
|
||||
validSig = isWildcardNetwork ||
|
||||
verify(PublicKey(makeSlice(spk)),
|
||||
makeMsg(accountID).slice(),
|
||||
s.slice(),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
}
|
||||
@@ -504,90 +447,6 @@ multiSignHelper(
|
||||
return {};
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkBatchMultiSign(
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == RequireFullyCanonicalSig::yes);
|
||||
|
||||
// We can ease the computational load inside the loop a bit by
|
||||
// pre-constructing part of the data that we hash. Fill a Serializer
|
||||
// with the stuff that stays constant from signature to signature.
|
||||
Serializer dataStart;
|
||||
serializeBatch(dataStart, getFlags(), getBatchTransactionIDs());
|
||||
return multiSignHelper(
|
||||
batchSigner,
|
||||
fullyCanonical,
|
||||
[&dataStart](AccountID const& accountID) mutable -> Serializer {
|
||||
Serializer s = dataStart;
|
||||
finishMultiSigningData(accountID, s);
|
||||
return s;
|
||||
},
|
||||
rules);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkMultiSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == RequireFullyCanonicalSig::yes);
|
||||
|
||||
// We can ease the computational load inside the loop a bit by
|
||||
// pre-constructing part of the data that we hash. Fill a Serializer
|
||||
// with the stuff that stays constant from signature to signature.
|
||||
Serializer dataStart = startMultiSigningData(*this);
|
||||
return multiSignHelper(
|
||||
*this,
|
||||
fullyCanonical,
|
||||
[&dataStart](AccountID const& accountID) mutable -> Serializer {
|
||||
Serializer s = dataStart;
|
||||
finishMultiSigningData(accountID, s);
|
||||
return s;
|
||||
},
|
||||
rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a batch of transaction IDs from the STTx.
|
||||
*
|
||||
* This function returns a vector of transaction IDs by extracting them from
|
||||
* the field array `sfRawTransactions` within the STTx. If the batch
|
||||
* transaction IDs have already been computed and cached in `batch_txn_ids_`,
|
||||
* it returns the cached vector. Otherwise, it computes the transaction IDs,
|
||||
* caches them, and then returns the vector.
|
||||
*
|
||||
* @return A vector of `uint256` containing the batch transaction IDs.
|
||||
*
|
||||
* @note The function asserts that the `sfRawTransactions` field array is not
|
||||
* empty and that the size of the computed batch transaction IDs matches the
|
||||
* size of the `sfRawTransactions` field array.
|
||||
*/
|
||||
std::vector<uint256>
|
||||
STTx::getBatchTransactionIDs() const
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
getTxnType() == ttBATCH,
|
||||
"STTx::getBatchTransactionIDs : not a batch transaction");
|
||||
XRPL_ASSERT(
|
||||
getFieldArray(sfRawTransactions).size() != 0,
|
||||
"STTx::getBatchTransactionIDs : empty raw transactions");
|
||||
if (batch_txn_ids_.size() != 0)
|
||||
return batch_txn_ids_;
|
||||
|
||||
for (STObject const& rb : getFieldArray(sfRawTransactions))
|
||||
batch_txn_ids_.push_back(rb.getHash(HashPrefix::transactionID));
|
||||
|
||||
XRPL_ASSERT(
|
||||
batch_txn_ids_.size() == getFieldArray(sfRawTransactions).size(),
|
||||
"STTx::getBatchTransactionIDs : batch transaction IDs size mismatch");
|
||||
return batch_txn_ids_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static bool
|
||||
@@ -628,7 +487,7 @@ isMemoOkay(STObject const& st, std::string& reason)
|
||||
if (!paramObj->isFieldPresent(sfHookParameterValue) ||
|
||||
paramObj->getFieldVL(sfHookParameterValue).size() > maxVal)
|
||||
{
|
||||
reason = "HookParameterValue cannot exceed 128 bytes.";
|
||||
reason = "HookParameterValue cannot exceed 256 bytes.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -780,42 +639,6 @@ invalidMPTAmountInTx(STObject const& tx)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isRawTransactionOkay(STObject const& st, std::string& reason)
|
||||
{
|
||||
if (!st.isFieldPresent(sfRawTransactions))
|
||||
return true;
|
||||
|
||||
if (st.isFieldPresent(sfBatchSigners) &&
|
||||
st.getFieldArray(sfBatchSigners).size() > maxBatchTxCount)
|
||||
{
|
||||
reason = "Batch Signers array exceeds max entries.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const& rawTxns = st.getFieldArray(sfRawTransactions);
|
||||
if (rawTxns.size() > maxBatchTxCount)
|
||||
{
|
||||
reason = "Raw Transactions array exceeds max entries.";
|
||||
return false;
|
||||
}
|
||||
for (STObject raw : rawTxns)
|
||||
{
|
||||
try
|
||||
{
|
||||
TxType const tt =
|
||||
safe_cast<TxType>(raw.getFieldU16(sfTransactionType));
|
||||
raw.applyTemplate(getTxFormat(tt)->getSOTemplate());
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
reason = e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
passesLocalChecks(STObject const& st, std::string& reason)
|
||||
{
|
||||
@@ -840,9 +663,6 @@ passesLocalChecks(STObject const& st, std::string& reason)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isRawTransactionOkay(st, reason))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -858,13 +678,11 @@ sterilize(STTx const& stx)
|
||||
bool
|
||||
isPseudoTx(STObject const& tx)
|
||||
{
|
||||
auto const t = tx[~sfTransactionType];
|
||||
|
||||
auto t = tx[~sfTransactionType];
|
||||
if (!t)
|
||||
return false;
|
||||
|
||||
auto const tt = safe_cast<TxType>(*t);
|
||||
|
||||
auto tt = safe_cast<TxType>(*t);
|
||||
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY ||
|
||||
tt == ttEMIT_FAILURE || tt == ttUNL_REPORT || tt == ttCRON;
|
||||
}
|
||||
|
||||
@@ -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."),
|
||||
@@ -222,7 +223,6 @@ transResults()
|
||||
MAKE_ERROR(temARRAY_EMPTY, "Malformed: Array is empty."),
|
||||
MAKE_ERROR(temARRAY_TOO_LARGE, "Malformed: Array is too large."),
|
||||
MAKE_ERROR(temBAD_TRANSFER_FEE, "Malformed: Transfer fee is outside valid range."),
|
||||
MAKE_ERROR(temINVALID_INNER_BATCH, "Malformed: Invalid inner batch transaction."),
|
||||
|
||||
MAKE_ERROR(temHOOK_DATA_TOO_LARGE, "Malformed: The hook CreateCode field is to large to be applied to the ledger."),
|
||||
MAKE_ERROR(terRETRY, "Retry transaction."),
|
||||
|
||||
@@ -49,9 +49,6 @@ TxMeta::TxMeta(
|
||||
|
||||
if (obj.isFieldPresent(sfHookEmissions))
|
||||
setHookEmissions(obj.getFieldArray(sfHookEmissions));
|
||||
|
||||
if (obj.isFieldPresent(sfParentBatchID))
|
||||
setParentBatchId(obj.getFieldH256(sfParentBatchID));
|
||||
}
|
||||
|
||||
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
||||
@@ -78,9 +75,6 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
||||
|
||||
if (obj.isFieldPresent(sfHookEmissions))
|
||||
setHookEmissions(obj.getFieldArray(sfHookEmissions));
|
||||
|
||||
if (obj.isFieldPresent(sfParentBatchID))
|
||||
setParentBatchId(obj.getFieldH256(sfParentBatchID));
|
||||
}
|
||||
|
||||
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
|
||||
@@ -96,15 +90,11 @@ TxMeta::TxMeta(
|
||||
{
|
||||
}
|
||||
|
||||
TxMeta::TxMeta(
|
||||
uint256 const& transactionID,
|
||||
std::uint32_t ledger,
|
||||
std::optional<uint256> parentBatchId)
|
||||
TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
|
||||
: mTransactionID(transactionID)
|
||||
, mLedger(ledger)
|
||||
, mIndex(static_cast<std::uint32_t>(-1))
|
||||
, mResult(255)
|
||||
, mParentBatchId(parentBatchId)
|
||||
, mNodes(sfAffectedNodes)
|
||||
{
|
||||
mNodes.reserve(32);
|
||||
@@ -255,9 +245,6 @@ TxMeta::getAsObject() const
|
||||
if (hasHookEmissions())
|
||||
metaData.setFieldArray(sfHookEmissions, getHookEmissions());
|
||||
|
||||
if (hasParentBatchId())
|
||||
metaData.setFieldH256(sfParentBatchID, getParentBatchId());
|
||||
|
||||
return metaData;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user