Compare commits

..

244 Commits

Author SHA1 Message Date
Richard Holland
5ad6701757 Merge pull request #697 from Xahau/jshooks-merge-20260225
JSHooks merge 20260225
2026-04-30 15:43:47 +10:00
tequ
176d7a1a0c Merge remote-tracking branch 'upstream/dev' into jshooks-merge-20260225 2026-04-30 12:19:08 +09:00
tequ
ebfbb8a900 fix clang-format workflow 2026-02-26 00:23:28 +09:00
tequ
a94e8b9536 update ordering.txt 2026-02-25 23:43:22 +09:00
tequ
13910b23a4 update generate_extern.sh 2026-02-25 23:30:16 +09:00
tequ
6385c56832 fix clang-format workflow to exclude quickjs files 2026-02-25 23:26:43 +09:00
tequ
3c879c7288 Merge branch 'dev' into jshooks 2026-02-25 23:23:46 +09:00
tequ
101ad3cb7e Merge commit 'd18c4d9b33ad42c268ab1e97606da6368e89587d' into jshooks 2026-02-25 22:59:23 +09:00
tequ
21a5e82fad Allow update JSHook Fee on Install/Update (#577)
* Allow update JSHook Fee on Install/Update, handle Instruction Limit Reach properly

* use `JS_FEE_OUT_OF_RANGE` as hook_log_code  instead `JS_FEE_TOO_HIGH`
2025-10-09 20:59:51 +11:00
tequ
c44b50b98c Fix slot to return bigint when specified true for second argument (#573) 2025-08-21 07:49:40 +07:00
Niq Dudfield
444152d077 fix: gcc 13 compile error, per #557 (#564) 2025-08-14 19:06:38 +07:00
Nicholas Dudfield
d8c9e89043 merge: origin/dev into jshooks, accepting upstream changes 2025-08-14 16:29:41 +07:00
tequ
285ea1d4e6 add checks the length of currency and issuer for float_sto (#518)
fix #461
2025-08-14 18:44:26 +10:00
tequ
b619d03b22 Fix hook_param_set to support deletion (#551) 2025-08-14 18:41:40 +10:00
tequ
34fd31dabe Fix JSHooks Fee validation (#550) 2025-08-14 18:01:14 +10:00
tequ
a6c4e39235 Improve validation for state_foreign_set (#554)
* Fix `FromJSIntArrayOrHexString` `[]` or `”"` return vector(size=0), not nullptr.

* improve validation for `state_foreign_set`
2025-07-29 12:40:53 +07:00
tequ
50a6499112 Fix FromJSIntArrayOrHexString [] or ”" return vector(size=0), not nullptr. (#553) 2025-07-29 12:40:39 +07:00
tequ
429f3289d8 Merge branch 'dev' into jshooks 2025-07-16 13:27:02 +09:00
Nicholas Dudfield
257c46ec9c chore: remove duplicate cmake policy directive from bad merge 2025-05-15 08:57:42 +07:00
Nicholas Dudfield
637d626518 Merge remote-tracking branch 'origin/dev' into jshooks 2025-05-14 19:37:45 +07:00
Nicholas Dudfield
cce9d372e7 [CONAN] Disable not working static containers 2025-04-04 09:09:46 +07:00
Nicholas Dudfield
aa571df467 Fix missing includes in Catalogue.cpp for non-unity builds 2025-04-04 09:00:43 +07:00
Nicholas Dudfield
ae8f6a16ed Merge remote-tracking branch 'origin/dev' into jshooks 2025-04-04 08:40:04 +07:00
Denis Angell
64441f7f40 Merge branch 'tmp-conan' into jshooks 2025-03-30 16:50:43 +02:00
Denis Angell
0bf50c5dc7 eof 2025-03-30 16:48:43 +02:00
Denis Angell
8b0592ce06 Update xahau-sh-build-in-docker.yml 2025-03-29 04:22:35 +01:00
Denis Angell
c27e2a9c05 Update xahau-sh-build-in-docker.yml 2025-03-29 03:26:09 +01:00
Denis Angell
f8d22bbc24 add caching 2025-03-29 03:08:58 +01:00
Denis Angell
95ab35a185 Update release-builder.sh 2025-03-29 02:43:43 +01:00
Denis Angell
313ad7134b test workflow 2025-03-29 02:40:38 +01:00
Denis Angell
859dcbcabf remove EXIT_IF_CONTAINER_RUNNING 2025-03-29 02:26:01 +01:00
Denis Angell
a8e9448b1a revert docker dependency cache 2025-03-29 02:15:13 +01:00
Denis Angell
cab4d63a07 revert some cmake builds 2025-03-28 20:44:09 +01:00
Denis Angell
9a90a7ffdc optional release builder 2025-03-28 20:42:18 +01:00
Denis Angell
ddbbe91e5a attempt fix builder 2025-03-28 19:32:37 +01:00
Denis Angell
2d9ac91cd1 fix build dir 2025-03-28 14:35:41 +01:00
Denis Angell
9532ea7dec tmp fix docker release builder 2025-03-28 12:01:56 +01:00
Denis Angell
ed243745f8 fix checkpatterns 2025-03-28 11:49:45 +01:00
Denis Angell
5eac2d3e44 change on fields 2025-03-28 11:44:22 +01:00
Denis Angell
245cf4a676 refactor checkpatterns remove comments 2025-03-28 10:44:18 +01:00
Denis Angell
864734f607 Update xahau-sh-build-in-docker.yml 2025-03-28 10:35:21 +01:00
Niq Dudfield
689740d818 Use GA runners with conan/ccache caches (#482) 2025-03-28 10:29:55 +01:00
Nicholas Dudfield
a8c80e99c0 [CONAN] GA only needs to declare push with ignore-branches 2025-03-28 13:57:38 +07:00
Nicholas Dudfield
486003f1a8 [CONAN] Do not build on sh runner for PRs targeting dev 2025-03-28 13:39:04 +07:00
Nicholas Dudfield
c9f0fe02a1 [CONAN] Namespace xahau actions/workflows for easier upstream 2025-03-28 13:27:03 +07:00
Nicholas Dudfield
a9c096e59c Add :log-test-names: target for --unittest-arg 2025-03-28 08:47:07 +07:00
Nicholas Dudfield
a83a157058 [CONAN] Remove straggling .build_deps mention 2025-03-28 08:46:40 +07:00
Nicholas Dudfield
5e255e560f [CONAN] Fix Claude's mess 2025-03-28 08:09:25 +07:00
Nicholas Dudfield
c953ee326d [CONAN] Move caching steps into build/dependencies actions 2025-03-28 07:52:08 +07:00
Nicholas Dudfield
053a10a236 [CONAN] clean up comments 2025-03-27 12:38:22 +07:00
Nicholas Dudfield
c53dcf1422 feat: add RUN_TARGET_PATTERN macro with --unittest-arg regex 2025-03-27 12:38:10 +07:00
Nicholas Dudfield
34b148bda0 [CONAN] better ccache keys 2025-03-26 08:06:12 +07:00
Nicholas Dudfield
19111a3739 [CONAN] use always() and step conclusion 2025-03-25 21:03:12 +07:00
Nicholas Dudfield
3f98c15910 [CONAN] use step conclusion 2025-03-25 20:44:32 +07:00
Nicholas Dudfield
942227f8c3 [CONAN] stable fallback cache key 2025-03-25 20:17:53 +07:00
Nicholas Dudfield
e9461c827c [CONAN] prime .ccache 2025-03-25 19:47:37 +07:00
Nicholas Dudfield
3d9423dda6 [CONAN] use dummy jobs 2025-03-25 19:24:06 +07:00
Nicholas Dudfield
5d41688e36 [CONAN] fallback cache key with run_id 2025-03-25 19:03:55 +07:00
Nicholas Dudfield
9bd6d2244e [CONAN] dummy tests for now 2025-03-25 17:47:00 +07:00
Denis Angell
48919f028c [GA] Remove build caching 2025-03-25 11:40:18 +01:00
Nicholas Dudfield
46d745b43f [CONAN] include-hidden-folders: true 2025-03-25 17:34:57 +07:00
Nicholas Dudfield
5365bbcfe8 [CONAN] fix MacOS ccache folder 2025-03-25 16:45:44 +07:00
Denis Angell
9c26f1f213 [GA] revert 2025-03-25 10:45:28 +01:00
Denis Angell
69b7728b2d [GA] tmp disable build cache 2025-03-25 10:37:17 +01:00
Nicholas Dudfield
15b679b1a7 [CONAN] cache ccache folder 2025-03-25 16:32:35 +07:00
Denis Angell
9178aa9d8a [GA] remove unused workflows 2025-03-25 10:17:33 +01:00
Denis Angell
17fdd09640 [GA] update conan profile 2025-03-25 10:13:05 +01:00
Denis Angell
40dc69d642 [GA] conan mac os build 2025-03-25 10:06:17 +01:00
Nicholas Dudfield
e8560c2198 [CONAN] try using glob 2025-03-25 15:50:18 +07:00
tequ
ca7533c14a fix zero XFL (#481) 2025-03-25 14:52:52 +07:00
Nicholas Dudfield
eba913a68e [CONAN] try using abs path 2025-03-25 14:42:24 +07:00
Nicholas Dudfield
ec849e0899 [CONAN] cache build directory too 2025-03-25 14:09:24 +07:00
Nicholas Dudfield
314fb6c9e0 [CONAN] cache build directory too 2025-03-25 14:03:09 +07:00
Nicholas Dudfield
643cd9fef1 Mark header file as generated 2025-03-25 13:24:25 +07:00
Nicholas Dudfield
3593d67df9 [CONAN] manually handle cache saving step in MacOS 2025-03-25 13:24:13 +07:00
Nicholas Dudfield
5571827be2 Merge branch 'tequdev/jshooks-date' into jshooks 2025-03-25 13:07:25 +07:00
Nicholas Dudfield
cfbfd762e8 [CONAN] manually handle cache saving step 2025-03-25 12:40:58 +07:00
Nicholas Dudfield
c25fd875a8 [CONAN] no access to 8 core runner 2025-03-25 12:31:31 +07:00
Nicholas Dudfield
043f1e96b6 [CONAN] install nproc 2025-03-25 12:26:15 +07:00
tequ
17dfca6e61 add Emit tests (#478)
* add tests for emits

* clang-format

* fix otxn_burden

* remove std:cout

* fix tests
2025-03-25 11:53:41 +07:00
Nicholas Dudfield
74681718dd [CONAN] fix typo and redundant deps step 2025-03-25 11:35:46 +07:00
Nicholas Dudfield
167417bfed [CONAN] remove redundant step 2025-03-25 09:35:29 +07:00
Nicholas Dudfield
2dd22648e8 [CONAN] use v4 -artifacts 2025-03-25 09:32:14 +07:00
Nicholas Dudfield
e89aa05a2a [CONAN] use simpler GA runners with conan cache 2025-03-25 09:26:32 +07:00
Nicholas Dudfield
8a5ccbf870 [CONAN] use simpler GA runners with conan cache 2025-03-25 09:09:18 +07:00
Nicholas Dudfield
f6f87e468a [CONAN] use simpler GA runners with conan cache 2025-03-25 09:06:22 +07:00
Nicholas Dudfield
d7167a9ebe [CONAN] use macos-15 2025-03-25 08:15:03 +07:00
Nicholas Dudfield
7446dddddb [CONAN] simplify matrix 2025-03-24 19:13:35 +07:00
Nicholas Dudfield
d9388e1e51 [CONAN] fix typo 2025-03-24 19:03:16 +07:00
Nicholas Dudfield
73c1748241 [CONAN] simplify matrix 2025-03-24 19:00:54 +07:00
Denis Angell
58e3840345 remove cxxflags for macos action 2025-03-24 12:02:01 +01:00
Nicholas Dudfield
61135c0ecb [CONAN] clean up conf experiments 2025-03-24 17:09:39 +07:00
Nicholas Dudfield
42a44d0cb8 [CONAN] clear the tools.build:cxxflags 2025-03-24 16:54:12 +07:00
Nicholas Dudfield
d37039897e [CONAN] clear the tools.build:cxxflags 2025-03-24 16:50:33 +07:00
Nicholas Dudfield
2061d6d44c [CONAN] clear cache 2025-03-24 16:40:59 +07:00
Nicholas Dudfield
8ea35ace02 [CONAN] remove DBOOST_ASIO_DISABLE_CONCEPTS define 2025-03-24 16:34:41 +07:00
Nicholas Dudfield
a203314c68 [CONAN] check clang --version 2025-03-24 16:32:47 +07:00
Nicholas Dudfield
092a29cd18 [CONAN] Use self-hosted runner again 2025-03-24 16:26:37 +07:00
Nicholas Dudfield
1ba18875ac [CONAN] Do not build cobalt 2025-03-24 16:12:34 +07:00
Nicholas Dudfield
2da58fe18f [CONAN] Run MacOS builds on GH runners 2025-03-24 15:57:05 +07:00
Nicholas Dudfield
8d7cc68bda Merge remote-tracking branch 'origin/tmp-conan' into jshooks 2025-03-23 11:09:17 +07:00
Denis Angell
b73dd584e7 Merge branch 'dev' into tmp-conan 2025-03-21 15:15:03 +01:00
Denis Angell
0726789d77 update conan to 1.86 2025-03-21 15:09:59 +01:00
Nicholas Dudfield
05bd9c6ea8 Use official shell script 2025-03-18 17:25:10 +07:00
Nicholas Dudfield
f9e7ea95fd Test for NO_FREE_SLOTS 2025-03-18 17:08:43 +07:00
tequ
618a933241 Add xpop_slot test (#476)
* add xpop_slot test

* clang-format
2025-03-18 17:07:12 +07:00
Nicholas Dudfield
752dbf34ee Automatically add MacOS gsed/ggrep paths to PATH if exist 2025-03-18 15:04:50 +07:00
tequ
fcf3848814 Add tests for fee_base, ledger_keylet, meta_slot (#469)
* add tests for fee_base, ledger_keylet, meta_slot

* clang-format

* clang-format

* update SetJSHook_wasm.h
2025-03-18 15:01:36 +07:00
Nicholas Dudfield
e4a6aecc18 Bump numFeatures 2025-03-18 14:55:50 +07:00
tequ
1c4ebfe3ad Updated the jshook build script so that it works on macOS and Ubuntu (#464) 2025-03-18 13:18:30 +07:00
Nicholas Dudfield
f97165e4bc Return DOESNT_EXIST in JSHooks sto_erase #463 2025-03-18 13:16:53 +07:00
Nicholas Dudfield
fc50c0fb0a Free out array in slot before returning special case int64 #467 2025-03-18 13:15:38 +07:00
Nicholas Dudfield
1b12b400d7 Add missing JS_FreeValue calls for early returns #468 2025-03-18 13:14:23 +07:00
Nicholas Dudfield
f3ee0dd322 Fix validate exception handling #473 2025-03-18 13:08:40 +07:00
Nicholas Dudfield
d9659dc226 Merge remote-tracking branch 'origin/dev' into jshooks 2025-03-18 13:03:10 +07:00
Nicholas Dudfield
fb7af36cef Update jshooks header 2025-03-18 11:46:22 +07:00
tequ
4bfe27d11f Enable JS Date on using parent ledger close time 2025-03-17 13:40:59 +09:00
tequ
eaa2cc9e5c [JSHooks] Add sto tests (#460) 2025-03-12 11:56:37 +01:00
tequ
6aa1ff87b9 add tests for float_sto, float_sto_set, float_sum (#462) 2025-03-12 11:39:12 +01:00
Denis Angell
5ef3795cea [fix] release build issue 2025-03-06 08:47:01 +01:00
Denis Angell
da5f1d189b Merge branch 'dev' into tmp-conan 2025-03-05 08:22:27 +01:00
Denis Angell
6fdf788b13 Merge branch 'dev' into tmp-conan 2025-02-28 10:22:52 +01:00
Niq Dudfield
61f45055a7 feat(quickjs): add test_sto_emplace (#448) 2025-02-27 07:42:14 +01:00
Denis Angell
f9e7fed929 [revert] typo 2025-02-26 11:38:12 +01:00
Denis Angell
5cfe566489 [fold] update test wasm 2025-02-24 10:13:44 +01:00
Denis Angell
04409616ed [fold] clang-format 2025-02-24 10:02:09 +01:00
Denis Angell
ca04c2a802 float_sto_set return bigint
Co-authored-by: tequ <git@tequ.dev>
2025-02-24 09:58:45 +01:00
Denis Angell
f868b4d6e6 reorder free context
Co-authored-by: tequ <git@tequ.dev>
2025-02-24 09:58:15 +01:00
Denis Angell
5502453de8 [fold] clang-format 2025-02-24 09:49:19 +01:00
Denis Angell
359ab70ba0 Merge branch 'dev' into jshooks 2025-02-24 09:31:28 +01:00
tequ
d82f60705d add replacer for Stringify bigint value (#437) 2025-02-24 09:28:12 +01:00
tequ
15515b84f8 fix sto_from_json error (#438) 2025-02-24 09:27:21 +01:00
tequ
8b29fc5ee1 Add bytecode validity check on SetHook (#439) 2025-02-24 09:26:31 +01:00
tequ
92be8146e8 fix JSHooks tests (#446) 2025-02-24 09:25:45 +01:00
Denis Angell
c0f55d0b00 Merge branch 'dev' into jshooks 2025-02-21 11:08:02 +01:00
Denis Angell
802ea6c568 [temp] remove negative rate test 2025-02-11 14:32:29 +01:00
Denis Angell
ecc779346e Merge branch 'dev' into tmp-conan 2025-02-11 12:11:27 +01:00
Denis Angell
680c6095d4 Update macos.yml 2025-02-11 12:06:20 +01:00
Denis Angell
6858861660 fix failing test 2025-02-07 11:01:20 +01:00
Denis Angell
9faef17407 fix bad commit 2025-02-06 11:13:29 +01:00
Denis Angell
ee68cc2cd2 clang-format 2025-02-05 11:31:06 +01:00
Denis Angell
7c360bad33 add optional include 2025-02-05 11:31:00 +01:00
Denis Angell
26a66bc2ef fix misc warnings 2025-02-04 12:24:34 +01:00
Denis Angell
4b93e1657f fix macos github action 2025-02-04 12:18:32 +01:00
Denis Angell
cd45285cab include optional 2025-02-04 12:18:25 +01:00
Denis Angell
b7acfb9803 fix misc warnings 2025-02-04 12:18:09 +01:00
Denis Angell
97a10d6556 [fold] fix test 2025-02-04 12:08:12 +01:00
Denis Angell
fe43029272 [fold] clang-format 2025-02-02 23:13:25 +01:00
Denis Angell
bf33b6f637 [fold] update conan 2025-02-02 22:25:33 +01:00
Denis Angell
c27518b846 [fold] use rippleci docker image 2025-02-02 22:23:26 +01:00
Denis Angell
7d8f5de93d [fold] remove conan patch 2025-02-02 22:23:15 +01:00
Denis Angell
858ea1bf25 [fold] add external snappy 2025-02-02 21:46:08 +01:00
Denis Angell
7162fe0497 [fold] upgrade artifact@v4 2025-02-02 21:09:52 +01:00
Denis Angell
56c0e0dd5f [fold] fix bad assert 2025-02-02 21:07:09 +01:00
Denis Angell
20ca066454 [fold] update workflow 2025-02-02 21:06:55 +01:00
Denis Angell
171610d1a9 [release] add release build 2025-02-01 16:54:35 +01:00
Denis Angell
2f6cf0ab4b [patch] remit transfer rate 2025-02-01 13:11:56 +01:00
Denis Angell
71884ad48a sync 2025-02-01 12:11:01 +01:00
Denis Angell
799a056313 conan 2025-02-01 12:00:35 +01:00
tequ
eec61f16c9 JSHooks Instruction Count (#423) 2025-01-22 08:39:20 +10:00
tequ
1bed7f1196 fix jshooks build error (#410) 2024-12-16 12:58:40 -05:00
RichardAH
211e63c568 Merge pull request #386 from tequdev/fix-jshooks-at-macos-build
Co-authored-by: Denis Angell <dangell@transia.co>
2024-12-11 11:36:06 +10:00
RichardAH
81413a5ce8 Merge branch 'jshooks' into fix-jshooks-at-macos-build 2024-12-11 11:32:39 +10:00
RichardAH
36d630bed3 Merge branch 'dev' into jshooks 2024-11-15 08:38:14 +10:00
Denis Angell
4f901788f4 [fold] preprocessor macros 2024-11-11 11:13:57 +01:00
tequ
72e773cbff fix: not to use std::lexicographical_compare_three_way 2024-10-28 16:02:56 +09:00
tequ
39ec8fb901 fix: build error no type named 'Reader' in namespace 'Json' 2024-10-28 16:02:16 +09:00
Denis Angell
534870f2f0 Merge branch 'dev' into jshooks 2024-10-23 12:39:44 +02:00
Denis Angell
db245d237c build for mac 2024-10-23 12:37:19 +02:00
Denis Angell
f3118ef8fa fix return error 2024-09-19 13:27:16 +02:00
Denis Angell
ee21449757 float_sign should be int not bigint 2024-09-19 11:30:11 +02:00
Denis Angell
9e7bee5564 fix slot_float return 2024-09-19 11:26:33 +02:00
Wietse Wind
8cb2bbb693 Workaround CentOS7 EOL 2024-08-18 02:20:43 +02:00
Richard Holland
c240c1553b rename HooksV1 feature to JSHooks feature 2024-08-04 10:11:11 +10:00
Denis Angell
a498ebeac4 update tests 2024-07-30 12:25:51 +02:00
Denis Angell
b13cab4ced add proper error handling 2024-07-30 12:18:49 +02:00
Denis Angell
783bff75a0 add feature 2024-07-30 12:17:00 +02:00
Denis Angell
c1610a6dda fix v1 errors 2024-07-29 11:27:21 +02:00
Richard Holland
f829a79d54 better exit handling accept/rollback/exception/instruction limit 2024-07-17 15:14:03 +10:00
Denis Angell
f35704c91f add tests 2024-07-16 12:58:01 +02:00
Richard Holland
9db9ad2123 add error logging for qjs 2024-07-16 12:31:02 +10:00
Richard Holland
f96daa0014 TextEncoder/Decoder working in jshooks 2024-07-15 15:57:05 +10:00
Denis Angell
5c7ec5f36f more testing 2024-07-12 22:51:35 +02:00
Denis Angell
c662a8b0d2 comment out debug 2024-07-12 22:47:38 +02:00
Denis Angell
a983120b5d patch state_foreign_set delete 2024-07-12 22:36:44 +02:00
Richard Holland
f12b8cbb2d qjs modules, compiling not tested 2024-07-11 11:31:29 +10:00
Richard Holland
f591290589 first iteration of adding an instruction limit to jshooks 2024-07-08 12:49:36 +10:00
Richard Holland
f2becaf140 remove promise, date and proxy from the jsvm 2024-07-04 11:50:54 +10:00
Richard Holland
e4c6add794 make accept/rollback actually exit the jsvm 2024-07-04 10:50:01 +10:00
Denis Angell
78280e4b8c fix sto_subarray 2024-06-03 11:06:56 +02:00
Denis Angell
178fdbaff6 remove dummy arg causes INVALID_ARGUMENT for keylets without args 2024-05-31 12:05:10 +02:00
Denis Angell
34d7435ff3 cont. tests 2024-05-30 15:41:38 +02:00
Denis Angell
6429ec609d cont. tests 2024-05-30 15:39:05 +02:00
Wietse Wind
bea1697baa Fix JS float_int return JS instead of JSXFL 2024-05-30 12:06:15 +02:00
Wietse Wind
2b111b7f23 Fix account_tx sluggishness as per https://github.com/XRPLF/rippled/commit/2e9261cb (#330) 2024-05-30 11:47:05 +02:00
Denis Angell
5254595063 add tests 2024-05-30 09:30:19 +02:00
Wietse Wind
52456a2d51 CI Split jobs with prev job dependency & CI on jshooks (#320) (#328)
* CI on `jshooks` branch

* CI Split jobs with prev job dependency

* No multi branch worker in parallel

---------

Co-authored-by: Denis Angell <dangell@transia.co>
2024-05-29 13:48:39 +02:00
Wietse Wind
b340824711 Merge pull request #326 from Xahau/dev
CI on `jshooks` branch (#317)
2024-05-29 13:45:06 +02:00
Denis Angell
f5bb779f61 nit: reorder fields 2024-05-28 17:02:11 +02:00
Denis Angell
bf99a1b05d fix sto_emplace 2024-05-28 15:34:09 +02:00
Denis Angell
d1e5eb87f5 Revert "dump"
This reverts commit b650d72f0b.
2024-05-28 15:32:44 +02:00
Denis Angell
b650d72f0b dump 2024-05-28 15:30:07 +02:00
Denis Angell
7567277dd8 [fold] denis error 2024-05-25 16:28:31 +02:00
Denis Angell
13719a1357 fix_float 2024-05-25 13:52:15 +02:00
Denis Angell
033dedf979 fix float_set 2024-05-24 14:23:01 +02:00
Richard Holland
6973540d52 fix account type on js otxn_field 2024-05-24 10:07:05 +10:00
Richard Holland
c9dcff90fa fix js otxn_id hook_account bugs 2024-05-24 10:07:05 +10:00
Richard Holland
71675c4fed js slot_json sto_to_json sto_from_json meta_slot xpop_slot 2024-05-24 10:07:05 +10:00
Denis Angell
70bc2d3283 more js hook tests 2024-05-24 10:07:05 +10:00
Denis Angell
c4d0fc0e0f [fold] tmp use hsov1
Will remove later just did this to avoid to many updates
2024-05-24 10:07:05 +10:00
Denis Angell
5d61eea709 clean up test code 2024-05-24 10:07:05 +10:00
Denis Angell
f4ffe4a3e0 add set js hook tests 2024-05-24 10:07:05 +10:00
Denis Angell
59ecbd9932 add hso w/ api version 2024-05-24 10:07:05 +10:00
Richard Holland
6c3da46a1b js prepare/emit working 2024-05-24 10:07:05 +10:00
Richard Holland
46308e33b0 js prepare otxn_json, compiling not tested 2024-05-24 10:07:05 +10:00
Richard Holland
1f7355719d js emit 2024-05-24 10:07:05 +10:00
Richard Holland
7cc395b284 js float_set float_multiply float_mulratio float_negate float_compare float_sum float_sto float_sto_set float_invert float_divide float_one float_mantissa float_sign float_int float_log float_root 2024-05-24 10:07:05 +10:00
Richard Holland
a634318e8d js sto_validate sto_subfield sto_subarray sto_emplace sto_erase, compiling not tested 2024-05-24 10:07:05 +10:00
Denis Angell
82e754d180 Update quickjs.cmake 2024-05-24 10:07:05 +10:00
Denis Angell
9e72931bbb fix quickjs build 2024-05-24 10:07:05 +10:00
Richard Holland
842a0388d1 enable js slot apis 2024-05-24 10:07:05 +10:00
Richard Holland
280ba7d5de js slot slot_clear slot_count slot_set slot_size slot_subarray slot_subfield slot_type slot_float compiling not tested 2024-05-24 10:07:05 +10:00
Richard Holland
7b0bc67242 js state, state_foreign, state_set, state_foreign_set, compiling untested 2024-05-24 10:07:05 +10:00
Richard Holland
8e172e1846 js hook_param hook_param_set hook_skip hook_pos 2024-05-24 10:07:05 +10:00
Richard Holland
7497d619bf js hook_hash, hook_again, fee_base, ledger_seq, ledger_last_hash, ledger_last_time, ledger_nonce, ledger_keylet 2024-05-24 10:07:05 +10:00
Richard Holland
34a159b662 js etxn_fee_base/details/reserve/generation/nonce hook_account 2024-05-24 10:07:05 +10:00
Richard Holland
663910c78a js otxn_field otxn_generation otxn_burden etxn_burden 2024-05-24 10:07:05 +10:00
Richard Holland
40b9aa7aed js otxn_param otxn_slot 2024-05-24 10:07:05 +10:00
Richard Holland
ec7d603bf9 js otxn_type 2024-05-24 10:07:05 +10:00
Richard Holland
f9137000e3 js util_keylet untested compiling 2024-05-24 10:07:05 +10:00
Richard Holland
c3cf4b5999 start of js util_keylet 2024-05-24 10:07:05 +10:00
Richard Holland
6954abdd04 bug fix, debugging print 2024-05-24 10:07:05 +10:00
Richard Holland
38a4b3c1b9 js util_sha512h 2024-05-24 10:07:05 +10:00
Richard Holland
7e12b46169 js util_verify 2024-05-24 10:07:05 +10:00
Richard Holland
4e91d5887f js util_accid 2024-05-24 10:07:05 +10:00
Richard Holland
f051b87176 js util_raddr 2024-05-24 10:07:05 +10:00
Richard Holland
98d39db305 otxnid, trace apis for js hooks 2024-05-24 10:07:05 +10:00
Richard Holland
80df3adac7 hookjs rollback 2024-05-24 10:07:05 +10:00
Richard Holland
a2c3567caf first js hookapi working (accept) 2024-05-24 10:07:05 +10:00
Richard Holland
206773dcf4 debug 2024-05-24 10:07:05 +10:00
Richard Holland
54c00d0364 bug fixes 2024-05-24 10:07:05 +10:00
Richard Holland
71a6f9c4d5 compiling 2024-05-24 10:07:05 +10:00
Richard Holland
9ab33d580d more progress on jsvm 2024-05-24 10:07:05 +10:00
Richard Holland
0bd65bbb56 quickjs running inside xahaud 2024-05-24 10:07:05 +10:00
311 changed files with 130948 additions and 32109 deletions

View File

@@ -1,37 +1,6 @@
codecov:
require_ci_to_pass: true
comment:
behavior: default
layout: reach,diff,flags,tree,reach
show_carryforward_flags: false
coverage:
range: "60..80"
precision: 1
round: nearest
status:
project:
default:
target: 60%
threshold: 2%
patch:
default:
target: auto
threshold: 2%
changes: false
github_checks:
annotations: true
parsers:
cobertura:
partials_as_hits: true
handle_missing_conditions : true
slack_app: false
ignore:
- "src/test/"
- "include/xrpl/beast/test/"
- "include/xrpl/beast/unit_test/"

View File

@@ -1,25 +1,8 @@
# This feature requires Git >= 2.24
# To use it by default in git blame:
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Format first-party source according to .clang-format
50760c693510894ca368e90369b0cc2dabfd07f3
# Reintroduce Clang-Format & Levelization
da1d20d6d5d862716125d60899b80fab5302954a
# Consolidate external libraries
da1d20d6d5d862716125d60899b80fab5302954a
# Rename .hpp to .h
0345a2645d0f5ad900f4fbbcaff96040d3a887fc
# Format formerly .hpp files
5a227dc719016e10045e17c9396ad401118044f1
# Rewrite includes
e61880699997398f5a746e6c4034edc7632661f5
# Move CMake directory (#4997)
e47b1c1b3b97c3f6d11858ee02f463596e29e7f0
# Rearrange sources (#4997)
bfafa2bb39e562901736d656806bd700c3699a2f
# Rewrite includes (#4997)
e61880699997398f5a746e6c4034edc7632661f5
# Recompute loops (#4997)
d25b5dcd568bb96c18e347d55fac10fe901a1bfb
# Reformat code with clang-format-18
02749feea88ce61c1f7eeb2d61a57d8ecf07ab11
e2384885f5f630c8f0ffe4bf21a169b433a16858
241b9ddde9e11beb7480600fd5ed90e1ef109b21
760f16f56835663d9286bd29294d074de26a7ba6
0eebe6a5f4246fced516d52b83ec4e7f47373edd

3
.gitattributes vendored
View File

@@ -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

View File

@@ -40,7 +40,7 @@ jobs:
run: |
# Download install.sh
curl -o /tmp/wasienv-install.sh https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh
# Replace /bin to /local/bin
sed -i 's|/bin|/local/bin|g' /tmp/wasienv-install.sh

View File

@@ -20,7 +20,7 @@ jobs:
sudo apt-get update
sudo apt-get install clang-format-${CLANG_VERSION}
- name: Format first-party sources
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-${CLANG_VERSION} -i {} +
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -not -path "src/quickjs/*" -exec clang-format-${CLANG_VERSION} -i {} +
- name: Check for differences
id: assert
run: |

5
.gitignore vendored
View File

@@ -124,11 +124,10 @@ pkg
CMakeUserPresets.json
bld.rippled/
# binary
qjsc
generated
.vscode
# AI docs (local working documents)
.ai-docs/
# Suggested in-tree build directory
/.build/

4
.testnet/.gitignore vendored
View File

@@ -1,4 +0,0 @@
output/
__pycache__/
scenarios/odd-cases/
scenarios/suite-experiments.yml

View File

@@ -1,29 +0,0 @@
"""Scenario: ConsensusEntropy amendment crashes non-supporting node.
Votes ConsensusEntropy accept on all nodes except n4, then waits for n4
to crash as the amendment activates without its support.
x-testnet run --scenario-script consensus_entropy_crash.py
"""
from helpers import CONSENSUS_ENTROPY_FEATURE
async def scenario(ctx, log):
await ctx.wait_for_ledger_close()
ctx.feature(CONSENSUS_ENTROPY_FEATURE, vetoed=False, exclude_nodes=[4])
log("Waiting for ConsensusEntropy to be voted for...")
await ctx.wait_for_feature(
CONSENSUS_ENTROPY_FEATURE,
check=lambda s: not s.get("vetoed"),
exclude_nodes=[4],
timeout=60,
)
log("Waiting for n4 to crash...")
op = await ctx.wait_for_nodes_down(nodes=[4], timeout=600)
ctx.assert_log("unsupported amendments activated", since=op.started, nodes=[4])
ctx.assert_exit_status(0, nodes=[4])
log("PASS: n4 shut down due to unsupported amendment")

View File

@@ -1,52 +0,0 @@
""":descr: entropy stays valid under transaction load"""
from __future__ import annotations
from helpers import require_entropy, get_entropy_tx, assert_valid_entropy
variants = [
{"label": "light", "min_txns": 5, "max_txns": 10},
{"label": "heavy", "min_txns": 50, "max_txns": 60},
{"label": "super_heavy", "min_txns": 90, "max_txns": 120},
]
async def scenario(ctx, log, *, min_txns=5, max_txns=10, **_):
await require_entropy(ctx, log)
gen = ctx.txn_generator(min_txns=min_txns, max_txns=max_txns)
await gen.start()
await gen.wait_until_ready()
log(f"Transaction generator ready ({min_txns}-{max_txns} txns/ledger)")
# Wait for pipeline warmup + a few txn-bearing ledgers.
await ctx.wait_for_ledgers(3, node_id=0, timeout=60)
start_seq = ctx.validated_ledger_index(0)
await ctx.wait_for_ledgers(10, node_id=0, timeout=120)
end_seq = ctx.validated_ledger_index(0)
log(f"Inspecting ledgers {start_seq + 1}{end_seq}")
digests = set()
total_user_txns = 0
for seq in range(start_seq + 1, end_seq + 1):
ce, user_txns = get_entropy_tx(ctx, seq)
digest, count = assert_valid_entropy(ce, seq, seen_digests=digests)
total_user_txns += len(user_txns)
log(
f" Ledger {seq}: EntropyCount={count} "
f"user_txns={len(user_txns)} Digest={digest[:16]}..."
)
await gen.stop()
log(
f"Verified {end_seq - start_seq} ledgers: {total_user_txns} user txns, "
f"all entropy valid and unique"
)
if total_user_txns == 0:
raise AssertionError("No user transactions were included in any ledger")
log("PASS")

View File

@@ -1,139 +0,0 @@
""":descr: 4/5 liveness, 3/5 fallback-entropy (Tier 3), recovery"""
from __future__ import annotations
from helpers import ZERO_DIGEST, require_entropy, get_entropy_tx, entropy_fields
async def scenario(ctx, log):
await require_entropy(ctx, log)
# Baseline: wait 1 ledger to confirm network is healthy.
await ctx.wait_for_ledgers(1, node_id=0, timeout=30)
# --- 4/5 liveness ---
ctx.stop_node(4)
await ctx.wait_for_nodes_down(nodes=[4], timeout=30)
await ctx.wait_for_ledgers(1, node_id=0, timeout=30)
log("4/5: liveness OK")
# Snapshot validated seq before dropping to 3/5.
val_before = ctx.validated_ledger_index(0)
# --- 3/5 degraded window ---
ctx.stop_node(3)
await ctx.wait_for_nodes_down(nodes=[3], timeout=30)
# 10s ≈ 3 rounds at 3s cadence.
await ctx.sleep(10)
val_after = ctx.validated_ledger_index(0)
log(f"3/5: validated ledger {val_before}{val_after}")
# Accepted/built ledgers may still later appear as validated once the full
# network rejoins. For ConsensusEntropy the key invariant is that every
# ledger created during this sub-quorum window carries FALLBACK entropy
# (Tier 3: non-zero consensus-bound digest, EntropyCount=0) — never
# validator-tier entropy.
degraded_fallback = 0
degraded_end = val_after or val_before
if val_before and degraded_end and degraded_end > val_before:
for seq in range(val_before + 1, degraded_end + 1):
ce, _ = get_entropy_tx(ctx, seq)
digest, entropy_count, is_fallback = entropy_fields(ce)
if not is_fallback:
raise AssertionError(
f"Ledger {seq}: expected fallback entropy during 3/5 "
f"window, got Digest={digest[:16]}... "
f"EntropyCount={entropy_count}"
)
if digest == ZERO_DIGEST:
raise AssertionError(
f"Ledger {seq}: fallback digest should be non-zero "
f"(Tier 3), got zero"
)
degraded_fallback += 1
log(
f" Degraded ledger {seq}: EntropyCount={entropy_count} "
f"FALLBACK"
)
log(f"3/5 entropy summary: {degraded_fallback} fallback")
# Log checks tied to current transition mechanics:
# - commit-set SHAMap publication is the observable output of entering the
# commit sidecar phase
# - ConvergingCommit transition is the gateway out of seq=0-only behavior
# - reason=impossible-quorum is the explicit degraded-window fallback path
ctx.log_level("LedgerConsensus", "trace")
ctx.log_level("ConsensusExtensions", "trace")
op = await ctx.sleep(6, name="stall_window")
ctx.assert_not_log(
r"RNG: transitioned to ConvergingCommit", within=op.window, nodes=[0, 1, 2]
)
ctx.assert_not_log(
r"RNG: built commitSet SHAMap", within=op.window, nodes=[0, 1, 2]
)
gate_blocked = ctx.search_logs(
r"STALLDIAG: establish gate blocked reason=(pause|no-tx-consensus)",
within=op.window,
nodes=[0, 1, 2],
)
log(f"3/5: establish gate-blocked logs in 6s: {gate_blocked.count}")
impossible = ctx.search_logs(
r"RNG: skipping commit wait reason=impossible-quorum",
within=op.window,
nodes=[0, 1, 2],
)
log(f"3/5: RNG impossible-quorum skips in 6s: {impossible.count}")
# --- Recovery: restart nodes, verify ledger advancement ---
ctx.start_node(3)
ctx.start_node(4)
await ctx.wait_for_ledgers(1, node_id=0, timeout=120)
val_recovered = ctx.validated_ledger_index(0)
pre_recovery = max(v for v in [val_before, val_after] if v is not None)
log(f"Recovered: validated seq {pre_recovery}{val_recovered}")
if not val_recovered or val_recovered <= pre_recovery:
raise AssertionError(
f"Validated ledger did not advance after recovery "
f"({pre_recovery}{val_recovered})"
)
# Inspect post-recovery ledgers separately from the degraded window above.
# Once the network is back at quorum, validator-tier entropy is expected
# again (transitional fallback ledgers are fine) and must be quorum-met.
fallback_count = 0
validator_count = 0
for seq in range(pre_recovery + 1, val_recovered + 1):
ce, _ = get_entropy_tx(ctx, seq)
digest, entropy_count, is_fallback = entropy_fields(ce)
if is_fallback:
fallback_count += 1
else:
validator_count += 1
if entropy_count < 4:
raise AssertionError(
f"Ledger {seq}: validator entropy with sub-quorum "
f"EntropyCount={entropy_count} (need >= 4)"
)
log(
f" Ledger {seq}: EntropyCount={entropy_count} "
f"{'FALLBACK' if is_fallback else 'VALIDATOR'}"
)
log(
f"Entropy summary: {fallback_count} fallback, "
f"{validator_count} validator"
)
log("PASS")

View File

@@ -1,44 +0,0 @@
""":descr: drop 2 nodes (3/5 stall), restart both, verify recovery"""
from __future__ import annotations
from helpers import require_entropy
async def scenario(ctx, log):
await require_entropy(ctx, log)
await ctx.wait_for_ledgers(1, node_id=0, timeout=60)
log("Baseline OK")
# Drop 2 nodes → validation stall.
ctx.stop_node(3)
ctx.stop_node(4)
await ctx.wait_for_nodes_down(nodes=[3, 4], timeout=30)
info = ctx.rpc.server_info(node_id=0)
val_before = info.get("info", {}).get("validated_ledger", {}).get("seq", 0)
log(f"Stalled at validated seq {val_before}")
# Let it sit for a few rounds in degraded state.
await ctx.sleep(6)
# Bring both nodes back.
ctx.start_node(3)
ctx.start_node(4)
log("Restarted n3 and n4, waiting for recovery...")
# Recovery: wait for ANY validated ledger advance on n0.
await ctx.wait_for_ledger_close(node_id=0, timeout=60)
info = ctx.rpc.server_info(node_id=0)
val_after = info.get("info", {}).get("validated_ledger", {}).get("seq", 0)
log(f"Recovered: validated seq {val_before}{val_after}")
if val_after <= val_before:
raise AssertionError(
f"Validated ledger did not advance after recovery "
f"({val_before}{val_after})"
)
log("PASS")

View File

@@ -1,27 +0,0 @@
""":descr: all 5 nodes healthy, every ledger has valid unique quorum-met entropy"""
from __future__ import annotations
from helpers import require_entropy, get_entropy_tx, assert_valid_entropy
async def scenario(ctx, log):
await require_entropy(ctx, log)
# Wait for RNG pipeline to warm up past bootstrap skip.
await ctx.wait_for_ledgers(3, node_id=0, timeout=60)
log("Pipeline warmed up")
start_seq = ctx.validated_ledger_index(0)
await ctx.wait_for_ledgers(10, node_id=0, timeout=120)
end_seq = ctx.validated_ledger_index(0)
log(f"Inspecting ledgers {start_seq + 1}{end_seq}")
digests = set()
for seq in range(start_seq + 1, end_seq + 1):
ce, _ = get_entropy_tx(ctx, seq)
digest, count = assert_valid_entropy(ce, seq, seen_digests=digests)
log(f" Ledger {seq}: EntropyCount={count} Digest={digest[:16]}...")
log(f"Verified {end_seq - start_seq} ledgers: all quorum entropy, all unique")
log("PASS")

View File

@@ -1,88 +0,0 @@
defaults:
network:
node_count: 5
launcher: tmux
find_ports: true
slave_delay: 0.2
features:
- ConsensusEntropy
- Export
track_features:
- ConsensusEntropy
- Export
log_levels:
TxQ: info
Protocol: debug
Peer: debug
LedgerConsensus: debug
ConsensusExtensions: debug
NetworkOPs: info
env:
XAHAU_RESOURCE_PER_PORT: "1"
XAHAU_RNG_POLL_MS: "333"
tests:
# --- CE + Export (80% quorum, SHAMap convergence) ---
- name: steady_state_export_ce
script: .testnet/scenarios/export/steady_state_export.py
- name: retriable_export_ce
script: .testnet/scenarios/export/retriable_export.py
- name: export_degradation_ce
script: .testnet/scenarios/export/export_degradation.py
network:
node_env:
3:
XAHAUD_NO_EXPORT_SIG: "1"
4:
XAHAUD_NO_EXPORT_SIG: "1"
# CE + Export: 1 node suppressed, 4/5 = 80% quorum, should succeed
- name: export_ce_one_node_down
script: .testnet/scenarios/export/export_quorum.py
params:
expect_success: true
network:
node_env:
4:
XAHAUD_NO_EXPORT_SIG: "1"
# --- Export only, no CE (80% active-view quorum) ---
- name: export_only_all_up
script: .testnet/scenarios/export/export_quorum.py
params:
expect_success: true
network:
features:
- Export
track_features:
- Export
- name: export_only_one_node_down
script: .testnet/scenarios/export/export_quorum.py
params:
expect_success: true
network:
features:
- Export
track_features:
- Export
node_env:
4:
XAHAUD_NO_EXPORT_SIG: "1"
- name: export_only_two_nodes_down
script: .testnet/scenarios/export/export_quorum.py
params:
expect_success: false
network:
features:
- Export
track_features:
- Export
node_env:
3:
XAHAUD_NO_EXPORT_SIG: "1"
4:
XAHAUD_NO_EXPORT_SIG: "1"

View File

@@ -1,118 +0,0 @@
""":descr: Submit ttEXPORT with 2 nodes suppressing export sigs, verify it
retries via terRETRY_EXPORT until LLS expiry (insufficient signatures).
Nodes 3 and 4 have XAHAUD_NO_EXPORT_SIG=1, so only 3/5 nodes provide
export signatures. With 80% quorum = ceil(5*0.8) = 4 required, the
export cannot reach quorum and should expire via tecEXPORT_EXPIRED.
Flow:
1. Fund alice and bob
2. alice submits ttEXPORT with tight LLS
3. Export retries (only 3/5 sigs available, need 4)
4. Verify export expires with tecEXPORT_EXPIRED
5. Verify subsequent payment still works (sequence not permanently blocked)
"""
from __future__ import annotations
from export_helpers import require_export, assert_shadow_ticket
async def scenario(ctx, log):
await require_export(ctx, log)
# --- Setup ---
await ctx.fund_accounts({"alice": 10000, "bob": 1000})
log("Accounts funded")
alice = ctx.account("alice")
bob = ctx.account("bob")
current_seq = ctx.validated_ledger_index(0)
log(f"Current ledger: {current_seq}")
log("Nodes 3,4 have XAHAUD_NO_EXPORT_SIG=1 (3/5 sigs, need 4)")
# --- Submit ttEXPORT (should retry then expire -- only 3/5 sigs) ---
export_start = ctx.mark("export-degradation-submit-start")
result = await ctx.submit_and_wait(
{
"TransactionType": "Export",
"LastLedgerSequence": current_seq + 8,
"Fee": "1000000",
"ExportedTxn": {
"TransactionType": "Payment",
"Account": alice.address,
"Destination": bob.address,
"Amount": "1000000",
"Fee": "10",
"Sequence": 0,
"TicketSequence": 1,
"FirstLedgerSequence": current_seq + 1,
"LastLedgerSequence": current_seq + 6,
"Flags": 2147483648,
"SigningPubKey": "",
},
},
alice.wallet,
timeout=60,
)
export_end = ctx.mark("export-degradation-submit-end")
final_seq = ctx.validated_ledger_index(0)
engine_result = result.get("engine_result", "")
log(f"Export completed at ledger {final_seq}, result: {engine_result}")
# With only 3/5 sigs and 80% quorum (4 required), export MUST fail
if engine_result == "tesSUCCESS":
raise AssertionError(
"Export should NOT have succeeded with only 3/5 sigs "
"(need 4 for 80% quorum) -- check XAHAUD_NO_EXPORT_SIG config"
)
# Should be tecEXPORT_EXPIRED (LLS reached without quorum)
if engine_result != "tecEXPORT_EXPIRED":
log(f"WARNING: expected tecEXPORT_EXPIRED, got {engine_result}")
log(f"Export failed as expected ({engine_result})")
retry_logs = ctx.assert_log(
r"Export: insufficient signatures .*result=terRETRY_EXPORT",
since=export_start,
until=export_end,
)
log(f"Export insufficient-signature retries: {retry_logs.count}")
expired_logs = ctx.assert_log(
r"Export: last ledger expired .*result=tecEXPORT_EXPIRED",
since=export_start,
until=export_end,
)
log(f"Export LLS expiry logs: {expired_logs.count}")
# No shadow ticket should exist (export never reached quorum)
assert_shadow_ticket(ctx, alice.address, log, expect_exists=False)
# --- Verify subsequent payment works regardless ---
log("Submitting payment from alice to bob...")
pay_result = await ctx.submit_and_wait(
{
"TransactionType": "Payment",
"Destination": bob.address,
"Amount": "1000000",
"Fee": "12",
},
alice.wallet,
timeout=30,
)
pay_engine = pay_result.get("engine_result", "")
log(f"Payment result: {pay_engine}")
if pay_engine != "tesSUCCESS":
raise AssertionError(
f"Payment failed after expired export: {pay_engine} "
f"-- sequence may be blocked"
)
log("Payment succeeded -- account not permanently blocked")
log("PASS")

View File

@@ -1,146 +0,0 @@
"""Shared helpers for Export scenario tests."""
from __future__ import annotations
from xahaud_scripts.testnet.config import feature_name_to_hash
async def require_export(ctx, log):
"""Wait for first ledger and assert Export is enabled."""
await ctx.wait_for_ledger_close(timeout=120)
feature = ctx.feature_check(feature_name_to_hash("Export"), node_id=0)
if not feature or not feature.get("enabled", False):
raise AssertionError(f"Export not enabled: {feature}")
log("Export enabled")
def find_export_txns(ctx, seq):
"""Find Export transactions in a ledger.
Returns list of Export transaction dicts.
"""
result = ctx.ledger(seq, transactions=True)
if not result:
return []
txns = result.get("ledger", {}).get("transactions", [])
return [tx for tx in txns if tx.get("TransactionType") == "Export"]
def dst_param(address):
"""Encode an address as a HookParameter entry for the DST param."""
from xrpl.core.addresscodec import decode_classic_address
dst_hex = decode_classic_address(address).hex().upper()
return {
"HookParameter": {
"HookParameterName": "445354", # "DST"
"HookParameterValue": dst_hex,
}
}
def assert_hook_accepted(meta, log, *, expected_emits=1):
"""Assert hook executed with ACCEPT and the expected emit count.
Checks sfHookExecutions in transaction metadata.
Returns the hook execution entry for further inspection.
"""
hook_execs = meta.get("HookExecutions", [])
if not hook_execs:
raise AssertionError("No HookExecutions in metadata")
exec_entry = hook_execs[0].get("HookExecution", {})
hook_result = exec_entry.get("HookResult", -1)
emit_count = exec_entry.get("HookEmitCount", -1)
return_code = exec_entry.get("HookReturnCode", "")
log(f" HookResult={hook_result} EmitCount={emit_count} ReturnCode={return_code}")
# HookResult 3 = ExitType::ACCEPT
if hook_result != 3:
raise AssertionError(
f"Hook did not ACCEPT: HookResult={hook_result} "
f"ReturnCode={return_code}"
)
if emit_count != expected_emits:
raise AssertionError(
f"Expected {expected_emits} emits, got {emit_count}"
)
# ReturnCode 0 = success; non-zero = ASSERT line number in hook
if return_code and str(return_code) != "0":
raise AssertionError(
f"Hook returned error code {return_code} "
f"(likely ASSERT failure at that line)"
)
return exec_entry
def assert_export_result(meta, log, *, require_signers=True):
"""Assert ExportResult is present and well-formed in metadata.
Returns the ExportResult dict.
"""
export_result = meta.get("ExportResult", {})
if not export_result:
raise AssertionError("ExportResult not found in metadata")
# Must have LedgerSequence and TransactionHash
if "LedgerSequence" not in export_result:
raise AssertionError("ExportResult missing LedgerSequence")
if "TransactionHash" not in export_result:
raise AssertionError("ExportResult missing TransactionHash")
# Must have the inner ExportedTxn object
inner = export_result.get("ExportedTxn", {})
if not inner:
raise AssertionError("ExportResult missing ExportedTxn (multisigned blob)")
log(f" ExportResult: seq={export_result['LedgerSequence']} "
f"hash={export_result['TransactionHash'][:16]}...")
# Inner tx should have Account, Destination, TransactionType
if "Account" not in inner:
raise AssertionError("ExportedTxn missing Account")
if "TransactionType" not in inner:
raise AssertionError("ExportedTxn missing TransactionType")
# Should have empty SigningPubKey (multisigned)
if inner.get("SigningPubKey", "NOT_EMPTY") != "":
raise AssertionError(
f"ExportedTxn SigningPubKey should be empty, "
f"got '{inner.get('SigningPubKey')}'"
)
if require_signers:
signers = inner.get("Signers", [])
if not signers:
raise AssertionError("ExportedTxn has no Signers (multisig not applied)")
log(f" Signers: {len(signers)} validator(s)")
return export_result
def assert_shadow_ticket(ctx, account_address, log, *, expect_exists=True):
"""Assert shadow ticket exists (or doesn't) for the account."""
obj_result = ctx.rpc.request(
0, "account_objects", {"account": account_address}
)
all_objects = (obj_result or {}).get("account_objects", [])
shadow_tickets = [
obj for obj in all_objects
if obj.get("LedgerEntryType") == "ShadowTicket"
]
log(f" Shadow tickets: {len(shadow_tickets)}")
if expect_exists and not shadow_tickets:
raise AssertionError("Expected shadow ticket but none found")
if not expect_exists and shadow_tickets:
raise AssertionError(
f"Expected no shadow tickets but found {len(shadow_tickets)}"
)
return shadow_tickets

View File

@@ -1,112 +0,0 @@
""":descr: Test Export quorum behavior. When enough active validators sign,
the export should succeed whether or not CE is enabled. When fewer than the
active-view quorum sign, the export should expire.
Parameterized via `expect_success` kwarg from suite.yml.
Flow:
1. Fund alice and bob
2. alice submits ttEXPORT
3. Verify result matches expectation (tesSUCCESS or tecEXPORT_EXPIRED)
4. Verify ExportResult + shadow ticket on success, absence on failure
5. Verify subsequent payment works regardless
"""
from __future__ import annotations
from export_helpers import (
require_export,
assert_export_result,
assert_shadow_ticket,
)
async def scenario(ctx, log, expect_success=True):
await require_export(ctx, log)
# --- Setup ---
await ctx.fund_accounts({"alice": 10000, "bob": 1000})
log("Accounts funded")
alice = ctx.account("alice")
bob = ctx.account("bob")
current_seq = ctx.validated_ledger_index(0)
log(f"Current ledger: {current_seq}")
outcome = "success" if expect_success else "failure (below quorum)"
log(f"Expecting export {outcome}")
# --- Submit ttEXPORT ---
result = await ctx.submit_and_wait(
{
"TransactionType": "Export",
"LastLedgerSequence": current_seq + 10,
"Fee": "1000000",
"ExportedTxn": {
"TransactionType": "Payment",
"Account": alice.address,
"Destination": bob.address,
"Amount": "1000000",
"Fee": "10",
"Sequence": 0,
"TicketSequence": 1,
"FirstLedgerSequence": current_seq + 1,
"LastLedgerSequence": current_seq + 8,
"Flags": 2147483648,
"SigningPubKey": "",
},
},
alice.wallet,
timeout=60,
)
final_seq = ctx.validated_ledger_index(0)
engine_result = result.get("engine_result", "")
meta = result.get("meta", {})
log(f"Export at ledger {final_seq}, result: {engine_result}")
if expect_success:
if engine_result != "tesSUCCESS":
raise AssertionError(
f"Expected tesSUCCESS, got {engine_result}"
)
# Assert ExportResult is well-formed with signers
assert_export_result(meta, log, require_signers=True)
# Assert shadow ticket was created
assert_shadow_ticket(ctx, alice.address, log, expect_exists=True)
log("Export succeeded as expected (active-view quorum reached)")
else:
if engine_result == "tesSUCCESS":
raise AssertionError(
"Export should NOT have succeeded below active-view quorum"
)
log(f"Export failed as expected ({engine_result})")
# No shadow ticket should exist
assert_shadow_ticket(ctx, alice.address, log, expect_exists=False)
# --- Verify subsequent payment works ---
log("Submitting payment from alice to bob...")
pay_result = await ctx.submit_and_wait(
{
"TransactionType": "Payment",
"Destination": bob.address,
"Amount": "1000000",
"Fee": "12",
},
alice.wallet,
timeout=30,
)
pay_engine = pay_result.get("engine_result", "")
log(f"Payment result: {pay_engine}")
if pay_engine != "tesSUCCESS":
raise AssertionError(f"Payment failed: {pay_engine}")
log("Payment succeeded -- account not blocked")
log("PASS")

View File

@@ -1,94 +0,0 @@
""":descr: Submit ttEXPORT directly (no hook), verify it succeeds with
ExportResult in metadata. Then submit a payment from the same account
to verify sequence handling doesn't block subsequent transactions.
Flow:
1. Fund alice and bob
2. alice submits ttEXPORT with inner payment -> tesSUCCESS (provisional)
3. Validators attach sigs via proposals -> quorum -> ExportResult in metadata
4. alice submits a Payment to bob -> should succeed (sequence not blocked)
"""
from __future__ import annotations
from export_helpers import require_export, assert_export_result, assert_shadow_ticket
async def scenario(ctx, log):
await require_export(ctx, log)
# --- Setup ---
await ctx.fund_accounts({"alice": 10000, "bob": 1000})
log("Accounts funded")
alice = ctx.account("alice")
bob = ctx.account("bob")
current_seq = ctx.validated_ledger_index(0)
log(f"Current ledger: {current_seq}")
# --- 1. Submit ttEXPORT ---
result = await ctx.submit_and_wait(
{
"TransactionType": "Export",
"LastLedgerSequence": current_seq + 15,
"Fee": "1000000",
"ExportedTxn": {
"TransactionType": "Payment",
"Account": alice.address,
"Destination": bob.address,
"Amount": "1000000",
"Fee": "10",
"Sequence": 0,
"TicketSequence": 1,
"FirstLedgerSequence": current_seq + 1,
"LastLedgerSequence": current_seq + 10,
"Flags": 2147483648,
"SigningPubKey": "",
},
},
alice.wallet,
timeout=60,
)
export_seq = ctx.validated_ledger_index(0)
engine_result = result.get("engine_result", "")
log(f"Export completed at ledger {export_seq}, result: {engine_result}")
if engine_result != "tesSUCCESS":
raise AssertionError(
f"Expected tesSUCCESS for export, got {engine_result}"
)
# Assert ExportResult is well-formed with signers
meta = result.get("meta", {})
assert_export_result(meta, log, require_signers=True)
# Assert shadow ticket was created
assert_shadow_ticket(ctx, alice.address, log, expect_exists=True)
# --- 2. Submit Payment from same account ---
log("Submitting payment from alice to bob...")
pay_result = await ctx.submit_and_wait(
{
"TransactionType": "Payment",
"Destination": bob.address,
"Amount": "1000000",
"Fee": "12",
},
alice.wallet,
timeout=30,
)
pay_engine = pay_result.get("engine_result", "")
log(f"Payment result: {pay_engine}")
if pay_engine != "tesSUCCESS":
raise AssertionError(f"Payment failed: {pay_engine}")
log(
f"Both transactions succeeded: "
f"Export at ledger {export_seq}, Payment at ledger {ctx.validated_ledger_index(0)}"
)
log("Sequence handling OK - export didn't block subsequent txns")
log("PASS")

View File

@@ -1,211 +0,0 @@
""":descr: install xport hook, trigger export, verify emitted ttEXPORT lifecycle
1. Fund alice (hook holder), bob (trigger), carol (export destination)
2. Install xport hook on alice
3. bob pays alice with DST=carol → hook calls xport() → emits ttEXPORT
4. Emitted ttEXPORT enters open ledger, validators attach sigs via proposals
5. Verify Export transaction appears in a subsequent ledger
"""
from __future__ import annotations
from export_helpers import (
require_export,
find_export_txns,
dst_param,
assert_hook_accepted,
assert_export_result,
assert_shadow_ticket,
)
# C source for the xport hook — verbatim from src/test/app/Export_test_hooks.h
# On Payment to the hook account, exports a 1 XAH payment to the DST param.
XPORT_HOOK_C = r"""
#include <stdint.h>
extern int32_t _g(uint32_t id, uint32_t maxiter);
extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t xport(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
extern int64_t xport_reserve(uint32_t count);
extern int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
extern int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t name_ptr, uint32_t name_len);
extern int64_t otxn_type(void);
extern int64_t ledger_seq(void);
#define SBUF(x) (uint32_t)(x), sizeof(x)
#define ASSERT(x) if (!(x)) rollback((uint32_t)#x, sizeof(#x), __LINE__)
#define ttPAYMENT 0
#define tfCANONICAL 0x80000000UL
#define amAMOUNT 1
#define amFEE 8
#define atACCOUNT 1
#define atDESTINATION 3
#define ENCODE_TT(buf_out, tt) \
buf_out[0] = 0x12U; buf_out[1] = (tt >> 8) & 0xFFU; buf_out[2] = tt & 0xFFU; buf_out += 3;
#define ENCODE_FLAGS(buf_out, flags) \
buf_out[0] = 0x22U; buf_out[1] = (flags >> 24) & 0xFFU; buf_out[2] = (flags >> 16) & 0xFFU; \
buf_out[3] = (flags >> 8) & 0xFFU; buf_out[4] = flags & 0xFFU; buf_out += 5;
#define ENCODE_SEQUENCE(buf_out, seq) \
buf_out[0] = 0x24U; buf_out[1] = (seq >> 24) & 0xFFU; buf_out[2] = (seq >> 16) & 0xFFU; \
buf_out[3] = (seq >> 8) & 0xFFU; buf_out[4] = seq & 0xFFU; buf_out += 5;
#define ENCODE_FLS(buf_out, fls) \
buf_out[0] = 0x20U; buf_out[1] = 0x1AU; buf_out[2] = (fls >> 24) & 0xFFU; \
buf_out[3] = (fls >> 16) & 0xFFU; buf_out[4] = (fls >> 8) & 0xFFU; \
buf_out[5] = fls & 0xFFU; buf_out += 6;
#define ENCODE_LLS(buf_out, lls) \
buf_out[0] = 0x20U; buf_out[1] = 0x1BU; buf_out[2] = (lls >> 24) & 0xFFU; \
buf_out[3] = (lls >> 16) & 0xFFU; buf_out[4] = (lls >> 8) & 0xFFU; \
buf_out[5] = lls & 0xFFU; buf_out += 6;
#define ENCODE_DROPS(buf_out, drops, amt_type) \
buf_out[0] = 0x60U + amt_type; buf_out[1] = 0x40U + ((drops >> 56) & 0x3FU); \
buf_out[2] = (drops >> 48) & 0xFFU; buf_out[3] = (drops >> 40) & 0xFFU; \
buf_out[4] = (drops >> 32) & 0xFFU; buf_out[5] = (drops >> 24) & 0xFFU; \
buf_out[6] = (drops >> 16) & 0xFFU; buf_out[7] = (drops >> 8) & 0xFFU; \
buf_out[8] = drops & 0xFFU; buf_out += 9;
#define ENCODE_SIGNING_PUBKEY_EMPTY(buf_out) \
buf_out[0] = 0x73U; buf_out[1] = 0x00U; buf_out += 2;
#define ENCODE_ACCOUNT(buf_out, acc, acc_type) \
buf_out[0] = 0x80U + acc_type; buf_out[1] = 0x14U; \
for (int i = 0; i < 20; ++i) buf_out[2+i] = acc[i]; buf_out += 22;
#define PREPARE_PAYMENT_SIMPLE_SIZE 270U
int64_t hook(uint32_t reserved) {
_g(1, 1);
if (otxn_type() != ttPAYMENT)
return accept(0, 0, 0);
ASSERT(xport_reserve(1) == 1);
uint8_t dst[20];
int64_t dst_len = otxn_param(SBUF(dst), "DST", 3);
ASSERT(dst_len == 20);
uint8_t acc[20];
ASSERT(hook_account(SBUF(acc)) == 20);
uint32_t cls = (uint32_t)ledger_seq();
uint8_t tx[PREPARE_PAYMENT_SIMPLE_SIZE];
uint8_t* buf = tx;
ENCODE_TT(buf, ttPAYMENT);
ENCODE_FLAGS(buf, tfCANONICAL);
ENCODE_SEQUENCE(buf, 0);
ENCODE_FLS(buf, cls + 1);
ENCODE_LLS(buf, cls + 5);
// sfTicketSequence = UINT32 field 41 = 0x20 0x29
buf[0] = 0x20U; buf[1] = 0x29U;
buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 1;
buf += 6;
uint64_t drops = 1000000;
ENCODE_DROPS(buf, drops, amAMOUNT);
ENCODE_DROPS(buf, 10, amFEE);
ENCODE_SIGNING_PUBKEY_EMPTY(buf);
ENCODE_ACCOUNT(buf, acc, atACCOUNT);
ENCODE_ACCOUNT(buf, dst, atDESTINATION);
uint8_t hash[32];
int64_t xport_result = xport(SBUF(hash), (uint32_t)tx, buf - tx);
ASSERT(xport_result == 32);
return accept(0, 0, 0);
}
"""
async def scenario(ctx, log):
# Wait for network to start and amendments to activate
await require_export(ctx, log)
# --- Setup ---
await ctx.fund_accounts({"alice": 10000, "bob": 10000, "carol": 1000})
log("Accounts funded")
alice = ctx.account("alice")
carol = ctx.account("carol")
# Compile and install xport hook on alice
wasm = ctx.compile_hook(XPORT_HOOK_C, label="xport")
await ctx.submit_and_wait(
{
"TransactionType": "SetHook",
"Hooks": [
{
"Hook": {
"CreateCode": wasm.hex().upper(),
"HookOn": "0" * 64,
"HookNamespace": "0" * 64,
"HookApiVersion": 0,
"Flags": 1, # hsfOVERRIDE
}
}
],
"Fee": "100000000",
},
alice.wallet,
)
log(
f"Hook installed on alice ({alice.address[:12]}...) "
f"ledger {ctx.validated_ledger_index(0)}"
)
# --- Trigger ---
# bob pays alice → hook calls xport() → emits ttEXPORT
trigger_result = await ctx.submit_and_wait(
{
"TransactionType": "Payment",
"Destination": alice.address,
"Amount": "100000000",
"Fee": "1000000",
"HookParameters": [dst_param(carol.address)],
},
ctx.account("bob").wallet,
)
trigger_seq = ctx.validated_ledger_index(0)
log(f"Export triggered at ledger {trigger_seq}")
# Assert hook fired with ACCEPT and emitted 1 tx
trigger_meta = trigger_result.get("meta", {})
assert_hook_accepted(trigger_meta, log, expected_emits=1)
# --- Verify: check each ledger close for the Export transaction ---
max_ledgers = 10
for i in range(max_ledgers):
await ctx.wait_for_ledgers(1, node_id=0, timeout=30)
seq = ctx.validated_ledger_index(0)
exports = find_export_txns(ctx, seq)
if exports:
export_tx = exports[0]
meta = export_tx.get("meta", export_tx.get("metaData", {}))
result = meta.get("TransactionResult", "")
log(f"Ledger {seq}: Export txn found, result={result}")
if result != "tesSUCCESS":
raise AssertionError(f"Export did not succeed: {result}")
# Assert ExportResult is well-formed with signers and inner tx
assert_export_result(meta, log, require_signers=True)
# Assert shadow ticket was created
assert_shadow_ticket(ctx, alice.address, log, expect_exists=True)
log("PASS")
return
log(f"Ledger {seq}: no Export txn yet")
raise AssertionError(
f"No Export transaction found after {max_ledgers} ledger closes"
)

View File

@@ -1,91 +0,0 @@
"""Shared helpers for ConsensusEntropy scenario tests."""
from __future__ import annotations
from xahaud_scripts.testnet.config import feature_name_to_hash
ZERO_DIGEST = "0" * 64
CONSENSUS_ENTROPY_FEATURE = feature_name_to_hash("ConsensusEntropy")
def feature_hash(name: str) -> str:
"""Return the amendment hash accepted by feature RPC."""
return feature_name_to_hash(name)
def feature_status(ctx, name: str, node_id=0):
"""Query a feature by amendment hash; feature RPC names are ambiguous."""
return ctx.feature_check(feature_hash(name), node_id=node_id)
def consensus_entropy_feature(ctx, node_id=0):
"""Query ConsensusEntropy by amendment hash."""
return feature_status(ctx, "ConsensusEntropy", node_id=node_id)
async def require_entropy(ctx, log):
"""Wait for first ledger and assert ConsensusEntropy is enabled."""
await ctx.wait_for_ledger_close(timeout=120)
feature = consensus_entropy_feature(ctx, node_id=0)
if not feature or not feature.get("enabled", False):
raise AssertionError(f"ConsensusEntropy not enabled: {feature}")
log("ConsensusEntropy enabled")
def get_entropy_tx(ctx, seq):
"""Fetch ledger and return (ce_tx, user_txns) or raise."""
result = ctx.ledger(seq, transactions=True)
if not result:
raise AssertionError(f"Ledger {seq}: fetch failed")
ledger = result.get("ledger")
if not isinstance(ledger, dict):
raise AssertionError(f"Ledger {seq}: fetch returned no ledger: {result}")
txns = ledger.get("transactions", [])
ce = [tx for tx in txns if tx.get("TransactionType") == "ConsensusEntropy"]
user = [tx for tx in txns if tx.get("TransactionType") != "ConsensusEntropy"]
if len(ce) != 1:
raise AssertionError(
f"Ledger {seq}: expected 1 ConsensusEntropy txn, got {len(ce)}"
)
return ce[0], user
def entropy_fields(ce_tx):
"""Return (digest, entropy_count, is_fallback) from a ConsensusEntropy tx.
Tier 3: fallback rounds carry a deterministic non-zero consensus-bound
digest with EntropyCount=0 and EntropyTier=1 (consensus_fallback).
Validator entropy has EntropyTier=3 (validator_quorum).
"""
digest = ce_tx.get("Digest", "")
entropy_count = ce_tx.get("EntropyCount", -1)
tier = ce_tx.get("EntropyTier", None)
if tier is not None:
is_fallback = tier != 3
else:
is_fallback = entropy_count == 0
return digest, entropy_count, is_fallback
def assert_valid_entropy(ce_tx, seq, seen_digests=None):
"""Assert quorum-met validator entropy. Optionally check uniqueness."""
digest, entropy_count, is_fallback = entropy_fields(ce_tx)
if is_fallback or not digest or digest == ZERO_DIGEST:
raise AssertionError(f"Ledger {seq}: fallback/empty Digest")
if entropy_count < 4:
raise AssertionError(
f"Ledger {seq}: EntropyCount={entropy_count} < 4 (sub-quorum)"
)
if seen_digests is not None:
if digest in seen_digests:
raise AssertionError(f"Ledger {seq}: duplicate Digest {digest[:16]}...")
seen_digests.add(digest)
return digest, entropy_count

View File

@@ -1,45 +0,0 @@
defaults:
network:
node_count: 5
launcher: tmux
find_ports: true
slave_delay: 0.2
features:
- ConsensusEntropy
track_features:
- ConsensusEntropy
log_levels:
TxQ: info
Protocol: debug
Peer: debug
LedgerConsensus: debug
ConsensusExtensions: debug
NetworkOPs: info
env:
XAHAU_RESOURCE_PER_PORT: "1"
XAHAU_RNG_POLL_MS: "333"
tests:
- name: steady_state_entropy
script: .testnet/scenarios/entropy/steady_state_entropy.py
- name: steady_state_entropy_fast_start
script: .testnet/scenarios/entropy/steady_state_entropy.py
network:
env:
XAHAUD_BOOTSTRAP_FAST_START: "1"
- name: entropy_with_transactions
script: .testnet/scenarios/entropy/entropy_with_transactions.py
- name: quorum_recovery_smoke
script: .testnet/scenarios/entropy/quorum_recovery_smoke.py
- name: quorum_degradation_smoke
script: .testnet/scenarios/entropy/quorum_degradation_smoke.py
network:
log_levels:
LedgerConsensus: trace
ConsensusExtensions: trace
# Export scenarios: see export-suite.yml

View File

@@ -12,7 +12,6 @@ libxrpl.server > xrpl.basics
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.server
test.app > test.shamap
test.app > test.toplevel
test.app > test.unit_test
test.app > xrpl.basics
@@ -44,7 +43,6 @@ test.consensus > xrpld.app
test.consensus > xrpld.consensus
test.consensus > xrpld.core
test.consensus > xrpld.ledger
test.consensus > xrpl.json
test.consensus > xrpl.protocol
test.core > test.jtx
test.core > test.toplevel
@@ -86,7 +84,6 @@ test.nodestore > xrpl.basics
test.nodestore > xrpld.core
test.nodestore > xrpld.nodestore
test.nodestore > xrpld.unity
test.nodestore > xrpl.protocol
test.overlay > test.jtx
test.overlay > test.toplevel
test.overlay > test.unit_test
@@ -121,7 +118,6 @@ test.rpc > xrpld.core
test.rpc > xrpld.net
test.rpc > xrpld.overlay
test.rpc > xrpld.rpc
test.rpc > xrpld.shamap
test.rpc > xrpl.hook
test.rpc > xrpl.json
test.rpc > xrpl.protocol
@@ -154,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

View File

@@ -145,6 +145,8 @@ target_link_libraries(ripple_libs INTERFACE
SQLite::SQLite3
)
include(deps/quickjs)
if(coverage)
include(RippledCov)
endif()

View File

@@ -12,16 +12,17 @@ echo "-- GITHUB_REPOSITORY: $1"
echo "-- GITHUB_SHA: $2"
echo "-- GITHUB_RUN_NUMBER: $4"
umask 0000
umask 0000;
####
cd /io
mkdir -p src/certs
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o src/certs/certbundle.h
if [ "$(grep certbundle.h src/xrpld/net/detail/RegisterSSLCerts.cpp | wc -l)" -eq "0" ]; then
cp src/xrpld/net/detail/RegisterSSLCerts.cpp src/xrpld/net/detail/RegisterSSLCerts.cpp.old
perl -i -pe "s/^{/{
cd /io;
mkdir -p src/certs;
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o src/certs/certbundle.h;
if [ "`grep certbundle.h src/xrpld/net/detail/RegisterSSLCerts.cpp | wc -l`" -eq "0" ]
then
cp src/xrpld/net/detail/RegisterSSLCerts.cpp src/xrpld/net/detail/RegisterSSLCerts.cpp.old
perl -i -pe "s/^{/{
#ifdef EMBEDDED_CA_BUNDLE
BIO *cbio = BIO_new_mem_buf(ca_bundle.data(), ca_bundle.size());
X509_STORE *cts = SSL_CTX_get_cert_store(ctx.native_handle());
@@ -67,14 +68,15 @@ fi
source /opt/rh/gcc-toolset-11/enable
export PATH=/usr/local/bin:$PATH
export CC='/usr/lib64/ccache/gcc' &&
export CXX='/usr/lib64/ccache/g++' &&
echo "-- Build Rippled --" &&
pwd &&
echo "MOVING TO [ build-core.sh ]"
export CXX='/usr/lib64/ccache/g++' &&
echo "-- Build Rippled --" &&
pwd &&
printenv >.env.temp
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g | sed s/\$/\\\"/g >.env
rm .env.temp
echo "MOVING TO [ build-core.sh ]";
printenv > .env.temp;
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g|sed s/\$/\\\"/g > .env;
rm .env.temp;
echo "Persisting ENV:"
cat .env

View File

@@ -62,7 +62,8 @@
"3C43D9A973AA4443EF3FC38E42DD306160FBFFDAB901CD8BAA15D09F2597EB87",
"0285B7E5E08E1A8E4C15636F0591D87F73CB6A7B6452A932AD72BBC8E5D1CBE3",
"6E739F4F8B07BED29FC9FF440DA3C301CD14A180DF45819F658FEC2F7DE31427",
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6"
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6",
"DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536"
],
"Flags": 0,
"LedgerEntryType": "Amendments",

View File

@@ -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

View File

@@ -95,9 +95,6 @@
# - replace both functions setup_target_for_coverage_gcovr_* with a single setup_target_for_coverage_gcovr
# - add support for all gcovr output formats
#
# 2024-04-03, Bronek Kozicki
# - add support for output formats: jacoco, clover, lcov
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
@@ -259,10 +256,10 @@ endif()
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# FORMAT "cobertura" # Output format, one of:
# # xml cobertura sonarqube jacoco clover
# # json-summary json-details coveralls csv
# # txt html-single html-nested html-details
# # lcov (xml is an alias to cobertura;
# # xml cobertura sonarqube json-summary
# # json-details coveralls csv txt
# # html-single html-nested html-details
# # (xml is an alias to cobertura;
# # if no format is set, defaults to xml)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
@@ -311,8 +308,6 @@ function(setup_target_for_coverage_gcovr)
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif(Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
elseif(Coverage_FORMAT STREQUAL "lcov")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
else()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif()
@@ -325,14 +320,6 @@ function(setup_target_for_coverage_gcovr)
set(Coverage_FORMAT cobertura) # overwrite xml
elseif(Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "jacoco")
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty )
elseif(Coverage_FORMAT STREQUAL "clover")
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty )
elseif(Coverage_FORMAT STREQUAL "lcov")
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)

View File

@@ -58,6 +58,7 @@ target_link_libraries(xrpl.imports.main
OpenSSL::Crypto
Ripple::boost
wasmedge::wasmedge
NIH::quickjs
Ripple::opts
Ripple::syslibs
absl::random_random

View File

@@ -6,6 +6,7 @@ include(create_symbolic_link)
install (
TARGETS
quickjs
common
opts
ripple_syslibs

View File

@@ -22,9 +22,6 @@ target_compile_definitions (opts
$<$<BOOL:${beast_no_unit_test_inline}>:BEAST_NO_UNIT_TEST_INLINE=1>
$<$<BOOL:${beast_disable_autolink}>:BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1>
$<$<BOOL:${single_io_service_thread}>:RIPPLE_SINGLE_IO_SERVICE_THREAD=1>
# Enhanced logging is enabled for Debug builds, or explicitly via
# -DBEAST_ENHANCED_LOGGING=ON for other build types.
$<$<OR:$<CONFIG:Debug>,$<BOOL:${BEAST_ENHANCED_LOGGING}>>:BEAST_ENHANCED_LOGGING=1>
$<$<BOOL:${voidstar}>:ENABLE_VOIDSTAR>)
target_compile_options (opts
INTERFACE

52
cmake/deps/quickjs.cmake Normal file
View 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
)

View File

@@ -47,8 +47,5 @@
#define MEM_OVERLAP -43
#define TOO_MANY_STATE_MODIFICATIONS -44
#define TOO_MANY_NAMESPACES -45
#define EXPORT_FAILURE -46
#define TOO_MANY_EXPORTED_TXN -47
#define TOO_LITTLE_ENTROPY -48
#define HOOK_ERROR_CODES
#endif //HOOK_ERROR_CODES

View File

@@ -2,9 +2,6 @@
// Generated using generate_extern.sh
#include <stdint.h>
#ifndef HOOK_EXTERN
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t __attribute__((noduplicate))
_g(uint32_t guard_id, uint32_t maxiter);
@@ -339,31 +336,5 @@ prepare(
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
xport_reserve(uint32_t count);
extern int64_t
xport(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
xport_cancel(uint32_t ticket_seq);
extern int64_t
dice(uint32_t sides, uint32_t min_tier, uint32_t min_count);
extern int64_t
random(
uint32_t write_ptr,
uint32_t write_len,
uint32_t min_tier,
uint32_t min_count);
#ifdef __cplusplus
}
#endif
#define HOOK_EXTERN
#endif // HOOK_EXTERN

View File

@@ -9,7 +9,7 @@ ENUM_FILE="$SCRIPT_DIR/../include/xrpl/hook/Enum.h"
echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/'
echo '// Generated using generate_error.sh'
echo '#ifndef HOOK_ERROR_CODES'
sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
sed -n '/enum hook_return_code/,/};/p' "$ENUM_FILE" |
awk '
function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s }
@@ -31,7 +31,7 @@ sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
{
line = $0
if (line ~ /enum[[:space:]]+class[[:space:]]+hook_return_code/)
if (line ~ /enum[[:space:]]+hook_return_code/)
next
if (line ~ /^[[:space:]]*\{/)
next

View File

@@ -11,9 +11,6 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
echo '// Generated using generate_extern.sh'
echo '#include <stdint.h>'
echo '#ifndef HOOK_EXTERN'
echo '#ifdef __cplusplus'
echo 'extern "C" {'
echo '#endif'
echo
awk '
function trim(s) {
@@ -30,8 +27,8 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
next;
}
# Look for comment lines that start with // and contain function signature
if (line ~ /^[[:space:]]*\/\/[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) {
# Look for comment lines that start with // int64_t or // int32_t
if (line ~ /^[[:space:]]*\/\/[[:space:]]*(int64_t|int32_t)[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) {
# Remove leading // and trim
sub(/^[[:space:]]*\/\/[[:space:]]*/, "", line);
line = trim(line);
@@ -49,9 +46,6 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
}
' "$APPLY_HOOK"
echo '#ifdef __cplusplus'
echo '}'
echo '#endif'
echo '#define HOOK_EXTERN'
echo '#endif // HOOK_EXTERN'
} | (

View File

@@ -630,7 +630,7 @@ int out_len = 0;\
_08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \
int64_t edlen = etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_SIZE); /* emitdet | size 1?? */ \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_SIZE); \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_SIZE); \
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \
}
@@ -661,8 +661,11 @@ int out_len = 0;\
_08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \
etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); /* emitdet | size 1?? */ \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); \
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \
}
#endif

View File

@@ -9,8 +9,6 @@
#define sfUNLModifyDisabling ((16U << 16U) + 17U)
#define sfHookResult ((16U << 16U) + 18U)
#define sfWasLockingChainSend ((16U << 16U) + 19U)
#define sfSidecarType ((16U << 16U) + 20U)
#define sfEntropyTier ((16U << 16U) + 21U)
#define sfLedgerEntryType ((1U << 16U) + 1U)
#define sfTransactionType ((1U << 16U) + 2U)
#define sfSignerWeight ((1U << 16U) + 3U)
@@ -24,8 +22,6 @@
#define sfHookApiVersion ((1U << 16U) + 20U)
#define sfHookStateScale ((1U << 16U) + 21U)
#define sfLedgerFixType ((1U << 16U) + 22U)
#define sfHookExportCount ((1U << 16U) + 98U)
#define sfEntropyCount ((1U << 16U) + 99U)
#define sfNetworkID ((2U << 16U) + 1U)
#define sfFlags ((2U << 16U) + 2U)
#define sfSourceTag ((2U << 16U) + 3U)
@@ -84,7 +80,6 @@
#define sfRewardTime ((2U << 16U) + 98U)
#define sfRewardLgrFirst ((2U << 16U) + 99U)
#define sfRewardLgrLast ((2U << 16U) + 100U)
#define sfCancelTicketSequence ((2U << 16U) + 101U)
#define sfIndexNext ((3U << 16U) + 1U)
#define sfIndexPrevious ((3U << 16U) + 2U)
#define sfBookNode ((3U << 16U) + 3U)
@@ -164,7 +159,6 @@
#define sfEmittedTxnID ((5U << 16U) + 97U)
#define sfGovernanceMarks ((5U << 16U) + 98U)
#define sfGovernanceFlags ((5U << 16U) + 99U)
#define sfEntropyDigest ((5U << 16U) + 100U)
#define sfNumber ((9U << 16U) + 1U)
#define sfAmount ((6U << 16U) + 1U)
#define sfBalance ((6U << 16U) + 2U)
@@ -195,7 +189,6 @@
#define sfSignatureReward ((6U << 16U) + 29U)
#define sfMinAccountCreateAmount ((6U << 16U) + 30U)
#define sfLPTokenBalance ((6U << 16U) + 31U)
#define sfTrustLineRewardAccumulator ((6U << 16U) + 99U)
#define sfPublicKey ((7U << 16U) + 1U)
#define sfMessageKey ((7U << 16U) + 2U)
#define sfSigningPubKey ((7U << 16U) + 3U)
@@ -227,7 +220,6 @@
#define sfProvider ((7U << 16U) + 30U)
#define sfMPTokenMetadata ((7U << 16U) + 31U)
#define sfCredentialType ((7U << 16U) + 32U)
#define sfHookName ((7U << 16U) + 97U)
#define sfRemarkValue ((7U << 16U) + 98U)
#define sfRemarkName ((7U << 16U) + 99U)
#define sfAccount ((8U << 16U) + 1U)
@@ -263,7 +255,6 @@
#define sfIssuingChainIssue ((24U << 16U) + 2U)
#define sfAsset ((24U << 16U) + 3U)
#define sfAsset2 ((24U << 16U) + 4U)
#define sfClaimCurrency ((24U << 16U) + 5U)
#define sfXChainBridge ((25U << 16U) + 1U)
#define sfTransactionMetaData ((14U << 16U) + 2U)
#define sfCreatedNode ((14U << 16U) + 3U)
@@ -294,7 +285,6 @@
#define sfXChainCreateAccountAttestationCollectionElement ((14U << 16U) + 31U)
#define sfPriceData ((14U << 16U) + 32U)
#define sfCredential ((14U << 16U) + 33U)
#define sfExportedTxn ((14U << 16U) + 90U)
#define sfAmountEntry ((14U << 16U) + 91U)
#define sfMintURIToken ((14U << 16U) + 92U)
#define sfHookEmission ((14U << 16U) + 93U)
@@ -302,9 +292,6 @@
#define sfActiveValidator ((14U << 16U) + 95U)
#define sfGenesisMint ((14U << 16U) + 96U)
#define sfRemark ((14U << 16U) + 97U)
#define sfHighReward ((14U << 16U) + 98U)
#define sfLowReward ((14U << 16U) + 99U)
#define sfExportResult ((14U << 16U) + 100U)
#define sfSigners ((15U << 16U) + 3U)
#define sfSignerEntries ((15U << 16U) + 4U)
#define sfTemplate ((15U << 16U) + 5U)

View File

@@ -61,7 +61,6 @@
#define ttNFTOKEN_MODIFY 70
#define ttPERMISSIONED_DOMAIN_SET 71
#define ttPERMISSIONED_DOMAIN_DELETE 72
#define ttEXPORT 91
#define ttCRON 92
#define ttCRON_SET 93
#define ttREMARKS_SET 94
@@ -75,4 +74,3 @@
#define ttUNL_MODIFY 102
#define ttEMIT_FAILURE 103
#define ttUNL_REPORT 104
#define ttCONSENSUS_ENTROPY 105

View File

@@ -115,8 +115,3 @@ enum AMMClawbackFlags : uint32_t {
enum BridgeModifyFlags : uint32_t {
tfClearAccountCreateAmount = 0x00010000,
};
enum ConsensusEntropyFlags : uint32_t {
tfEntropyCommit = 0x00000001, // entry is a commitment in commitSet
tfEntropyReveal = 0x00000002, // entry is a reveal in entropySet
};

View File

@@ -15,10 +15,7 @@
#define uint256 std::string
#define featureHooksUpdate1 "1"
#define featureHooksUpdate2 "1"
#define featureExport "1"
#define featureConsensusEntropy "1"
#define fix20250131 "1"
#define fixGuardDepth32 "1"
namespace hook_api {
struct Rules
{
@@ -267,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?
};
@@ -322,7 +322,7 @@ namespace compare_mode {
enum compare_mode : uint32_t { EQUAL = 1, LESS = 2, GREATER = 4 };
}
enum class hook_return_code : int64_t {
enum hook_return_code : int64_t {
SUCCESS =
0, // return codes > 0 are reserved for hook apis to return "success"
OUT_OF_BOUNDS =
@@ -386,24 +386,29 @@ enum class hook_return_code : int64_t {
MEM_OVERLAP = -43, // one or more specified buffers are the same memory
TOO_MANY_STATE_MODIFICATIONS = -44, // more than 5000 modified state
// entires in the combined hook chains
TOO_MANY_NAMESPACES = -45,
EXPORT_FAILURE = -46,
TOO_MANY_EXPORTED_TXN = -47,
TOO_LITTLE_ENTROPY = -48,
TOO_MANY_NAMESPACES = -45
};
enum class ExitType : uint8_t {
enum ExitType : uint8_t {
UNSET = 0,
WASM_ERROR = 1,
ROLLBACK = 2,
ACCEPT = 3,
JSVM_ERROR = 4,
LEDGER_ERROR =
5, // if the ledger contained for example a nonsense hookapi number
INSTRUCTION_LIMIT_REACHED = 6,
};
enum CodeType : uint8_t {
WASM = 0,
JS = 1,
};
const uint16_t max_state_modifications = 256;
const uint8_t max_slots = 255;
const uint8_t max_nonce = 255;
const uint8_t max_emit = 255;
const uint8_t max_export = 2;
const uint8_t max_params = 16;
const double fee_base_multiplier = 1.1f;
@@ -431,6 +436,10 @@ getImportWhitelist(Rules const& rules)
if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \
whitelist[#FUNCTION_NAME] = { \
RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE};
#define JSHOOK_API_DEFINITION( \
RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \
{ \
}
#include "hook_api.macro"
@@ -444,9 +453,12 @@ getImportWhitelist(Rules const& rules)
return whitelist;
}
#undef HOOK_API_DEFINITION
#undef I32
#undef I64
enum GuardRulesVersion : uint64_t {
GuardRuleFix20250131 = 0x00000001,
GuardRuleDepth32 = 0x00000002,
};
inline uint64_t
@@ -455,8 +467,6 @@ getGuardRulesVersion(Rules const& rules)
uint64_t version = 0;
if (rules.enabled(fix20250131))
version |= GuardRuleFix20250131;
if (rules.enabled(fixGuardDepth32))
version |= GuardRuleDepth32;
return version;
}

View File

@@ -204,13 +204,9 @@ struct WasmBlkInf
}
// compute worst case execution time
inline uint64_t
compute_wce(
const WasmBlkInf* blk,
int level,
int max_level,
bool* recursion_limit_reached)
compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached)
{
if (level > max_level)
if (level > 16)
{
*recursion_limit_reached = true;
return 0;
@@ -237,8 +233,8 @@ compute_wce(
if (blk->children.size() > 0)
for (auto const& child : blk->children)
worst_case_execution += compute_wce(
child, level + 1, max_level, recursion_limit_reached);
worst_case_execution +=
compute_wce(child, level + 1, recursion_limit_reached);
if (parent == 0 ||
parent->iteration_bound ==
@@ -792,17 +788,12 @@ check_guard(
}
bool recursion_limit_reached = false;
int max_level = 16;
if (rulesVersion & hook_api::GuardRuleDepth32)
max_level = 32;
uint64_t wce =
compute_wce(&(*root), 0, max_level, &recursion_limit_reached);
uint64_t wce = compute_wce(&(*root), 0, &recursion_limit_reached);
if (recursion_limit_reached)
{
GUARDLOG(hook::log::NESTING_LIMIT)
<< "GuardCheck "
<< "Maximum allowable depth of blocks reached (" << max_level
<< " levels). Flatten "
<< "Maximum allowable depth of blocks reached (16 levels). Flatten "
"your loops and conditions!.\n";
return {};
}

View File

@@ -67,6 +67,7 @@
#define SEP_int32_t LPAREN int32_t COMMA
#define SEP_uint64_t LPAREN uint64_t COMMA
#define SEP_int64_t LPAREN int64_t COMMA
#define SEP_JSValue LPAREN JSValue COMMA
#define VAL_uint32_t WasmEdge_ValueGetI32(in[_stack++])
#define VAL_int32_t WasmEdge_ValueGetI32(in[_stack++])
@@ -89,69 +90,174 @@
#define WASM_VAL_TYPE(T, b) CAT2(TYP_, T)
#define UNSIGNED_TYPE(T) std::make_unsigned_t<T>
#define HALF_COUNT(...) \
HALF_COUNT_IMPL( \
__VA_ARGS__, \
16, \
16, \
15, \
15, \
14, \
14, \
13, \
13, \
12, \
12, \
11, \
11, \
10, \
10, \
9, \
9, \
8, \
8, \
7, \
7, \
6, \
6, \
5, \
5, \
4, \
4, \
3, \
3, \
2, \
2, \
1, \
1, \
0, \
0)
#define DECLARE_HOOK_FUNCTION(R, F, ...) \
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__)); \
extern WasmEdge_Result WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out); \
extern WasmEdge_ValType WasmFunctionParams##F[]; \
extern WasmEdge_ValType WasmFunctionResult##F[]; \
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
#define HALF_COUNT_IMPL( \
_1, \
_2, \
_3, \
_4, \
_5, \
_6, \
_7, \
_8, \
_9, \
_10, \
_11, \
_12, \
_13, \
_14, \
_15, \
_16, \
_17, \
_18, \
_19, \
_20, \
_21, \
_22, \
_23, \
_24, \
_25, \
_26, \
_27, \
_28, \
_29, \
_30, \
_31, \
_32, \
N, \
...) \
N
#define DECLARE_WASM_FUNCTION(R, F, ...) \
R F(hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__)); \
extern WasmEdge_Result WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out); \
extern WasmEdge_ValType WasmFunctionParams##F[]; \
extern WasmEdge_ValType WasmFunctionResult##F[]; \
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
extern WasmEdge_String WasmFunctionName##F;
#define DEFINE_HOOK_FUNCTION(R, F, ...) \
WasmEdge_Result hook_api::WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out) \
{ \
__VA_OPT__(int _stack = 0;) \
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
hook::HookContext* hookCtx = \
reinterpret_cast<hook::HookContext*>(data_ptr); \
auto const& return_code = hook_api::F( \
*hookCtx, \
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
if (std::holds_alternative<hook_api::hook_return_code>(return_code) && \
(std::get<hook_api::hook_return_code>(return_code) == \
RC_ROLLBACK || \
std::get<hook_api::hook_return_code>(return_code) == RC_ACCEPT)) \
return WasmEdge_Result_Terminate; \
out[0] = RET_ASSIGN( \
R, \
std::holds_alternative<UNSIGNED_TYPE(R)>(return_code) \
? std::get<UNSIGNED_TYPE(R)>(return_code) \
: R(std::get<hook_api::hook_return_code>(return_code))); \
return WasmEdge_Result_Success; \
}; \
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
WASM_VAL_TYPE(R, dummy)}; \
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
WasmEdge_FunctionTypeCreate( \
WasmFunctionParams##F, \
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
WasmFunctionResult##F, \
1); \
WasmEdge_String hook_api::WasmFunctionName##F = \
WasmEdge_StringCreateByCString(#F); \
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> hook_api::F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
#define DECLARE_JS_FUNCTION(R, F, ...) \
extern JSValue JSFunction##F( \
JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); \
const int JSFunctionParamCount##F = __VA_OPT__(HALF_COUNT(__VA_ARGS__) +) 0;
#define DEFINE_WASM_FUNCTION(R, F, ...) \
WasmEdge_Result hook_api::WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out) \
{ \
__VA_OPT__(int _stack = 0;) \
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
hook::HookContext* hookCtx = \
reinterpret_cast<hook::HookContext*>(data_ptr); \
R return_code = hook_api::F( \
*hookCtx, \
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \
return WasmEdge_Result_Terminate; \
out[0] = RET_ASSIGN(R, return_code); \
return WasmEdge_Result_Success; \
}; \
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
WASM_VAL_TYPE(R, dummy)}; \
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
WasmEdge_FunctionTypeCreate( \
WasmFunctionParams##F, \
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
WasmFunctionResult##F, \
1); \
WasmEdge_String hook_api::WasmFunctionName##F = \
WasmEdge_StringCreateByCString(#F); \
R hook_api::F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__))
#define HOOK_SETUP() \
using enum hook_api::hook_return_code; \
#define VAR_JSASSIGN(T, V) \
if (_stack >= argc) \
returnJS(INVALID_ARGUMENT); \
T& V = argv[_stack++]
#define FORWARD_JS_FUNCTION_CALL(F, ac, av) \
hook_api::JSFunction##F(ctx, this_val, ac, av)
#define DEFINE_JS_FUNCTION(R, F, ...) \
JSValue hook_api::JSFunction##F( \
JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) \
{ \
__VA_OPT__(int _stack = 0;) \
__VA_OPT__(FOR_VARS(VAR_JSASSIGN, 2, __VA_ARGS__);)
#define JS_HOOK_SETUP() \
JSRuntime* rt = JS_GetRuntime(ctx); \
hook::HookContext& hookCtx = \
*reinterpret_cast<hook::HookContext*>(JS_GetRuntimeOpaque(rt)); \
[[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx; \
[[maybe_unused]] auto& view = applyCtx.view(); \
[[maybe_unused]] auto j = applyCtx.app.journal("View"); \
[[maybe_unused]] auto& api = hookCtx.api(); \
try \
{
#define JS_HOOK_TEARDOWN() \
} \
catch (const std::exception& e) \
{ \
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
<< "HookError[" << HC_ACC() << "]: (JS) " << __func__ \
<< " threw uncaught exception, what=" << e.what(); \
return JS_NewInt64(ctx, INTERNAL_ERROR); \
} \
}
#define WASM_HOOK_SETUP() \
try \
{ \
[[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx; \
@@ -168,14 +274,14 @@
if (!memoryCtx || !memory || !memory_length) \
return INTERNAL_ERROR;
#define HOOK_TEARDOWN() \
} \
catch (const std::exception& e) \
{ \
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
<< "HookError[" << HC_ACC() << "]: " << __func__ \
<< " threw uncaught exception, what=" << e.what(); \
return INTERNAL_ERROR; \
#define WASM_HOOK_TEARDOWN() \
} \
catch (const std::exception& e) \
{ \
JLOG(hookCtx.applyCtx.app.journal("View").error()) \
<< "HookError[" << HC_ACC() << "]: (WASM) " << __func__ \
<< " threw uncaught exception, what=" << e.what(); \
return INTERNAL_ERROR; \
}
#define WRITE_WASM_MEMORY( \
@@ -214,7 +320,7 @@
host_memory_ptr, \
guest_memory_length) \
{ \
uint64_t bytes_written = 0; \
int64_t bytes_written = 0; \
WRITE_WASM_MEMORY( \
bytes_written, \
guest_dst_ptr, \
@@ -269,6 +375,28 @@
: RC_ROLLBACK); \
}
#define HOOK_EXIT_JS(error_msg, error_code, exit_type) \
{ \
int64_t val = 0; \
if (JS_IsNumber(error_code)) \
JS_ToInt64(ctx, &val, error_code); \
hookCtx.result.exitCode = val; \
hookCtx.result.exitType = exit_type; \
if (JS_IsString(error_msg)) \
{ \
size_t len; \
const char* cstr = JS_ToCStringLen(ctx, &len, error_msg); \
if (len > 256) \
len = 256; \
hookCtx.result.exitReason = std::string(cstr, len); \
JS_FreeCString(ctx, cstr); \
} \
return JS_Exit( \
ctx, \
exit_type == hook_api::ExitType::ACCEPT ? "HookExit Accept" \
: "HookExit Rollback"); \
}
#define WRITE_WASM_MEMORY_OR_RETURN_AS_INT64( \
write_ptr_in, write_len_in, data_ptr_in, data_len_in, is_account_in) \
{ \
@@ -283,7 +411,7 @@
data_ptr < (data_ptr_in)) \
return INTERNAL_ERROR; \
if (data_len == 0) \
return 0ULL; \
return 0; \
if ((write_ptr_in) == 0) \
return data_as_int64(data_ptr, data_len); \
if (data_len > (write_len_in)) \

View File

@@ -7,311 +7,559 @@ HOOK_API_DEFINITION(
HOOK_API_DEFINITION(
int64_t, accept, (uint32_t, uint32_t, int64_t),
uint256{})
// function accept(error_msg: string, error_code: number): number
JSHOOK_API_DEFINITION(
JSValue, accept, (JSValue, JSValue),
uint256{})
// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
HOOK_API_DEFINITION(
int64_t, rollback, (uint32_t, uint32_t, int64_t),
uint256{})
// function rollback(error_msg: string, error_code: number): number
JSHOOK_API_DEFINITION(
JSValue, rollback, (JSValue, JSValue),
uint256{})
// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function util_raddr(acc_id:string): string
JSHOOK_API_DEFINITION(
JSValue, util_raddr, (JSValue),
uint256{})
// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function util_accid(acc_id:string): string
JSHOOK_API_DEFINITION(
JSValue, util_accid, (JSValue),
uint256{})
// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function util_verify(data:string, sig: string, pubkey: string): number
JSHOOK_API_DEFINITION(
JSValue, util_verify, (JSValue, JSValue, JSValue),
uint256{})
// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function util_sha512h(data: string): number
JSHOOK_API_DEFINITION(
JSValue, util_sha512h, (JSValue),
uint256{})
// int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
HOOK_API_DEFINITION(
int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function util_keylet(keylet_type: number, keylet_data: string): number
JSHOOK_API_DEFINITION(
JSValue, util_keylet, (JSValue, JSValue),
uint256{})
// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len);
HOOK_API_DEFINITION(
int64_t, sto_validate, (uint32_t, uint32_t),
uint256{})
// function sto_validate(sto: string): number
JSHOOK_API_DEFINITION(
JSValue, sto_validate, (JSValue),
uint256{})
// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t),
uint256{})
// function sto_subfield(sto: string, field_id: number): number
JSHOOK_API_DEFINITION(
JSValue, sto_subfield, (JSValue, JSValue),
uint256{})
// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id);
HOOK_API_DEFINITION(
int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t),
uint256{})
// function sto_subarray(sto: string, array_id: number): number
JSHOOK_API_DEFINITION(
JSValue, sto_subarray, (JSValue, JSValue),
uint256{})
// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function sto_emplace(sto: string, field_bytes: number, field_id: number): number
JSHOOK_API_DEFINITION(
JSValue, sto_emplace, (JSValue, JSValue, JSValue),
uint256{})
// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function sto_erase(sto: string, field_id: number): number
JSHOOK_API_DEFINITION(
JSValue, sto_erase, (JSValue, JSValue),
uint256{})
// int64_t etxn_burden();
HOOK_API_DEFINITION(
int64_t, etxn_burden, (),
uint256{})
// function etxn_burden(): number
JSHOOK_API_DEFINITION(
JSValue, etxn_burden, (),
uint256{})
// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, etxn_details, (uint32_t, uint32_t),
uint256{})
// function etxn_details(): number
JSHOOK_API_DEFINITION(
JSValue, etxn_details, (),
uint256{})
// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, etxn_fee_base, (uint32_t, uint32_t),
uint256{})
// function etxn_fee_base(txblob: string): number
JSHOOK_API_DEFINITION(
JSValue, etxn_fee_base, (JSValue),
uint256{})
// int64_t etxn_reserve(uint32_t count);
HOOK_API_DEFINITION(
int64_t, etxn_reserve, (uint32_t),
uint256{})
// function etxn_reserve(count: number): number
JSHOOK_API_DEFINITION(
JSValue, etxn_reserve, (JSValue),
uint256{})
// int64_t etxn_generation();
HOOK_API_DEFINITION(
int64_t, etxn_generation, (),
uint256{})
// function etxn_generation(): number
JSHOOK_API_DEFINITION(
JSValue, etxn_generation, (),
uint256{})
// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, etxn_nonce, (uint32_t, uint32_t),
uint256{})
// function etxn_nonce(): number
JSHOOK_API_DEFINITION(
JSValue, etxn_nonce, (),
uint256{})
// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function emit(txn: string): number
JSHOOK_API_DEFINITION(
JSValue, emit, (JSValue),
uint256{})
// int64_t float_set(int32_t exponent, int64_t mantissa);
HOOK_API_DEFINITION(
int64_t, float_set, (int32_t, int64_t),
uint256{})
// function float_set(e: number, m: number): number
JSHOOK_API_DEFINITION(
JSValue, float_set, (JSValue, JSValue),
uint256{})
// int64_t float_multiply(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_multiply, (int64_t, int64_t),
uint256{})
// function float_multiply(f1: number, f2: number): number
JSHOOK_API_DEFINITION(
JSValue, float_multiply, (JSValue, JSValue),
uint256{})
// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator);
HOOK_API_DEFINITION(
int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function float_mulratio(f1: number, round_up: number, numerator: number, denominator: number): number
JSHOOK_API_DEFINITION(
JSValue, float_mulratio, (JSValue, JSValue, JSValue, JSValue),
uint256{})
// int64_t float_negate(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_negate, (int64_t),
uint256{})
// function float_negate(f1: number): number
JSHOOK_API_DEFINITION(
JSValue, float_negate, (JSValue),
uint256{})
// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode);
HOOK_API_DEFINITION(
int64_t, float_compare, (int64_t, int64_t, uint32_t),
uint256{})
// function float_compare(f1: number, f2: number, mode: number): number
JSHOOK_API_DEFINITION(
JSValue, float_compare, (JSValue, JSValue, JSValue),
uint256{})
// int64_t float_sum(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_sum, (int64_t, int64_t),
uint256{})
// function float_sum(f1: number, f2: number): number
JSHOOK_API_DEFINITION(
JSValue, float_sum, (JSValue, JSValue),
uint256{})
// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code);
HOOK_API_DEFINITION(
int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t),
uint256{})
// function float_sto(cur: string, isu: string, float1: number, field_code: number): number
JSHOOK_API_DEFINITION(
JSValue, float_sto, (JSValue, JSValue, JSValue, JSValue),
uint256{})
// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, float_sto_set, (uint32_t, uint32_t),
uint256{})
// function float_sto_set(buf: string): number
JSHOOK_API_DEFINITION(
JSValue, float_sto_set, (JSValue),
uint256{})
// int64_t float_invert(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_invert, (int64_t),
uint256{})
// function float_invert(f1: number): number
JSHOOK_API_DEFINITION(
JSValue, float_invert, (JSValue),
uint256{})
// int64_t float_divide(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_divide, (int64_t, int64_t),
uint256{})
// function float_divide(f1: number, f2: number): number
JSHOOK_API_DEFINITION(
JSValue, float_divide, (JSValue, JSValue),
uint256{})
// int64_t float_one();
HOOK_API_DEFINITION(
int64_t, float_one, (),
uint256{})
// function float_one(): number
JSHOOK_API_DEFINITION(
JSValue, float_one, (),
uint256{})
// int64_t float_mantissa(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_mantissa, (int64_t),
uint256{})
// function float_mantissa(f1: number): number
JSHOOK_API_DEFINITION(
JSValue, float_mantissa, (JSValue),
uint256{})
// int64_t float_sign(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_sign, (int64_t),
uint256{})
// function float_sign(f1: number): number
JSHOOK_API_DEFINITION(
JSValue, float_sign, (JSValue),
uint256{})
// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs);
HOOK_API_DEFINITION(
int64_t, float_int, (int64_t, uint32_t, uint32_t),
uint256{})
// function float_int(f1: number, decimal_places: number, abs: number): number
JSHOOK_API_DEFINITION(
JSValue, float_int, (JSValue, JSValue, JSValue),
uint256{})
// int64_t float_log(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_log, (int64_t),
uint256{})
// function float_log(f1: number): number
JSHOOK_API_DEFINITION(
JSValue, float_log, (JSValue),
uint256{})
// int64_t float_root(int64_t float1, uint32_t n);
HOOK_API_DEFINITION(
int64_t, float_root, (int64_t, uint32_t),
uint256{})
// function float_root(f1: number, n: number): number
JSHOOK_API_DEFINITION(
JSValue, float_root, (JSValue, JSValue),
uint256{})
// int64_t fee_base();
HOOK_API_DEFINITION(
int64_t, fee_base, (),
uint256{})
// function fee_base(): number
JSHOOK_API_DEFINITION(
JSValue, fee_base, (),
uint256{})
// int64_t ledger_seq();
HOOK_API_DEFINITION(
int64_t, ledger_seq, (),
uint256{})
// function ledger_seq(): number
JSHOOK_API_DEFINITION(
JSValue, ledger_seq, (),
uint256{})
// int64_t ledger_last_time();
HOOK_API_DEFINITION(
int64_t, ledger_last_time, (),
uint256{})
// function ledger_last_time(): number
JSHOOK_API_DEFINITION(
JSValue, ledger_last_time, (),
uint256{})
// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, ledger_last_hash, (uint32_t, uint32_t),
uint256{})
// function ledger_last_hash(): number
JSHOOK_API_DEFINITION(
JSValue, ledger_last_hash, (),
uint256{})
// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, ledger_nonce, (uint32_t, uint32_t),
uint256{})
// function ledger_nonce(): number
JSHOOK_API_DEFINITION(
JSValue, ledger_nonce, (),
uint256{})
// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len);
HOOK_API_DEFINITION(
int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function ledger_keylet(low: string, high: string): number
JSHOOK_API_DEFINITION(
JSValue, ledger_keylet, (JSValue, JSValue),
uint256{})
// int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, hook_account, (uint32_t, uint32_t),
uint256{})
// function hook_account(): number
JSHOOK_API_DEFINITION(
JSValue, hook_account, (),
uint256{})
// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no);
HOOK_API_DEFINITION(
int64_t, hook_hash, (uint32_t, uint32_t, int32_t),
uint256{})
// function hook_hash(hook_no: number): number
JSHOOK_API_DEFINITION(
JSValue, hook_hash, (JSValue),
uint256{})
// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len);
HOOK_API_DEFINITION(
int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function hook_param_set(value: string, key: string, hash: string): number
JSHOOK_API_DEFINITION(
JSValue, hook_param_set, (JSValue, JSValue, JSValue),
uint256{})
// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function hook_param(key: string): number
JSHOOK_API_DEFINITION(
JSValue, hook_param, (JSValue),
uint256{})
// int64_t hook_again();
HOOK_API_DEFINITION(
int64_t, hook_again, (),
uint256{})
// function hook_again(): number
JSHOOK_API_DEFINITION(
JSValue, hook_again, (),
uint256{})
// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, hook_skip, (uint32_t, uint32_t, uint32_t),
uint256{})
// function hook_skip(hhash: string, flags: number): number
JSHOOK_API_DEFINITION(
JSValue, hook_skip, (JSValue, JSValue),
uint256{})
// int64_t hook_pos();
HOOK_API_DEFINITION(
int64_t, hook_pos, (),
uint256{})
// function hook_pos(): number
JSHOOK_API_DEFINITION(
JSValue, hook_pos, (),
uint256{})
// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot, (uint32_t, uint32_t, uint32_t),
uint256{})
// function slot(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot, (JSValue),
uint256{})
// int64_t slot_clear(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_clear, (uint32_t),
uint256{})
// function slot_clear(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_clear, (JSValue),
uint256{})
// int64_t slot_count(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_count, (uint32_t),
uint256{})
// function slot_count(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_count, (JSValue),
uint256{})
// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_set, (uint32_t, uint32_t, uint32_t),
uint256{})
// function slot_set(kl: string, slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_set, (JSValue, JSValue),
uint256{})
// int64_t slot_size(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_size, (uint32_t),
uint256{})
// function slot_size(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_size, (JSValue),
uint256{})
// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot);
HOOK_API_DEFINITION(
int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t),
uint256{})
// function slot_subarray(parent_slot_no: number, array_id: number, new_slot: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_subarray, (JSValue, JSValue, JSValue),
uint256{})
// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
HOOK_API_DEFINITION(
int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t),
uint256{})
// function slot_subfield(parent_slot_no: number, field_id: number, new_slot: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_subfield, (JSValue, JSValue, JSValue),
uint256{})
// int64_t slot_type(uint32_t slot_no, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, slot_type, (uint32_t, uint32_t),
uint256{})
// function slot_type(slot_no: number, flags: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_type, (JSValue, JSValue),
uint256{})
// int64_t slot_float(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, slot_float, (uint32_t),
uint256{})
// function slot_float(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_float, (JSValue),
uint256{})
// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function state_set(val: string, key: string): number
JSHOOK_API_DEFINITION(
JSValue, state_set, (JSValue, JSValue),
uint256{})
// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
HOOK_API_DEFINITION(
int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function state_foreign_set(val: string, key: string, ns: string, accid: string): number
JSHOOK_API_DEFINITION(
JSValue, state_foreign_set, (JSValue, JSValue, JSValue, JSValue),
uint256{})
// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function state(key: string): number
JSHOOK_API_DEFINITION(
JSValue, state, (JSValue),
uint256{})
// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
HOOK_API_DEFINITION(
int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function state_foreign(key: string, ns: string, accid: string): number
JSHOOK_API_DEFINITION(
JSValue, state_foreign, (JSValue, JSValue, JSValue),
uint256{})
// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex);
HOOK_API_DEFINITION(
int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function trace(msg: string, data: string, as_hex: number): number
JSHOOK_API_DEFINITION(
JSValue, trace, (JSValue, JSValue, JSValue),
uint256{})
// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number);
HOOK_API_DEFINITION(
@@ -327,73 +575,108 @@ HOOK_API_DEFINITION(
HOOK_API_DEFINITION(
int64_t, otxn_burden, (),
uint256{})
// function otxn_burden(): number
JSHOOK_API_DEFINITION(
JSValue, otxn_burden, (),
uint256{})
// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, otxn_field, (uint32_t, uint32_t, uint32_t),
uint256{})
// function otxn_field(field_id: number): number
JSHOOK_API_DEFINITION(
JSValue, otxn_field, (JSValue),
uint256{})
// int64_t otxn_generation();
HOOK_API_DEFINITION(
int64_t, otxn_generation, (),
uint256{})
// function otxn_generation(): number
JSHOOK_API_DEFINITION(
JSValue, otxn_generation, (),
uint256{})
// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, otxn_id, (uint32_t, uint32_t, uint32_t),
uint256{})
// function otxn_id(flags: number): number
JSHOOK_API_DEFINITION(
JSValue, otxn_id, (JSValue),
uint256{})
// int64_t otxn_type();
HOOK_API_DEFINITION(
int64_t, otxn_type, (),
uint256{})
// function otxn_type(): number
JSHOOK_API_DEFINITION(
JSValue, otxn_type, (),
uint256{})
// int64_t otxn_slot(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, otxn_slot, (uint32_t),
uint256{})
// function otxn_slot(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, otxn_slot, (JSValue),
uint256{})
// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// function otxn_param(param_key: string): number
JSHOOK_API_DEFINITION(
JSValue, otxn_param, (JSValue),
uint256{})
// int64_t meta_slot(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, meta_slot, (uint32_t),
uint256{})
// function meta_slot(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, meta_slot, (JSValue),
uint256{})
// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta);
HOOK_API_DEFINITION(
int64_t, xpop_slot, (uint32_t, uint32_t),
featureHooksUpdate1)
// function xpop_slot(slot_no_tx: number, slot_no_meta: number): number
JSHOOK_API_DEFINITION(
JSValue, xpop_slot, (JSValue, JSValue),
uint256{})
// int64_t prepare(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, prepare, (uint32_t, uint32_t, uint32_t, uint32_t),
featureHooksUpdate2)
// function prepare(tmpl: string): number
JSHOOK_API_DEFINITION(
JSValue, prepare, (JSValue),
uint256{})
// int64_t xport_reserve(uint32_t count);
HOOK_API_DEFINITION(
int64_t, xport_reserve, (uint32_t),
featureExport)
// function otxn_json(): number
JSHOOK_API_DEFINITION(
JSValue, otxn_json, (),
uint256{})
// int64_t xport(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, xport, (uint32_t, uint32_t, uint32_t, uint32_t),
featureExport)
// function slot_json(slot_no: number): number
JSHOOK_API_DEFINITION(
JSValue, slot_json, (JSValue),
uint256{})
// int64_t xport_cancel(uint32_t ticket_seq);
HOOK_API_DEFINITION(
int64_t, xport_cancel, (uint32_t),
featureExport)
// function sto_to_json(sto_in: string): number
JSHOOK_API_DEFINITION(
JSValue, sto_to_json, (JSValue),
uint256{})
// int64_t dice(uint32_t sides, uint32_t min_tier, uint32_t min_count);
HOOK_API_DEFINITION(
int64_t, dice, (uint32_t, uint32_t, uint32_t),
featureConsensusEntropy)
// int64_t random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier, uint32_t min_count);
HOOK_API_DEFINITION(
int64_t, random, (uint32_t, uint32_t, uint32_t, uint32_t),
featureConsensusEntropy)
// function sto_from_json(json_in: string): number
JSHOOK_API_DEFINITION(
JSValue, sto_from_json, (JSValue),
uint256{})

View File

@@ -1,2 +0,0 @@
---
DisableFormat: true

View File

@@ -166,14 +166,6 @@ message TMProposeSet
// Number of hops traveled
optional uint32 hops = 12 [deprecated=true];
// Export signatures for pending exports seen in the proposal set. The
// proposal's ExtendedPosition includes a digest of this repeated field, so
// these side-channel blobs are covered by the proposal signature.
// Each entry is: txnHash (32 bytes) + validator pubkey (33 bytes)
// + multisign signature (variable length). Validators attach these
// so export quorum can be reached within the same consensus round.
repeated bytes exportSignatures = 13;
}
enum TxSetStatus
@@ -392,3 +384,4 @@ message TMHaveTransactions
{
repeated bytes hashes = 1;
}

View File

@@ -1,37 +0,0 @@
#ifndef RIPPLE_PROTOCOL_ENTROPY_TIER_H_INCLUDED
#define RIPPLE_PROTOCOL_ENTROPY_TIER_H_INCLUDED
#include <cstdint>
namespace ripple {
/// Which gate the ledger's entropy passed. Stored in sfEntropyTier (UINT8)
/// on the ttCONSENSUS_ENTROPY pseudo-transaction and the ConsensusEntropy
/// ledger entry.
///
/// EntropyCount says how many validators contributed; EntropyTier says which
/// gate the result passed. Values are strength-ordered so consumers can gate
/// with a numeric comparison (tier >= required).
enum EntropyTier : std::uint8_t {
/// No usable entropy (reserved; a fresh ConsensusEntropy entry should
/// always carry one of the tiers below).
entropyTierNone = 0,
/// Consensus-bound deterministic fallback: derived from already-agreed
/// round inputs (parent ledger hash, base tx set hash, sequence) under
/// HashPrefix::entropyFallback when validator reveal quorum was not
/// available. Unpredictable in practice but user-influenceable via
/// transaction submission — never suitable for value-bearing outcomes.
entropyTierConsensusFallback = 1,
/// Reserved for a future participant-aligned sub-quorum tier.
entropyTierParticipantAligned = 2,
/// Validator commit/reveal entropy whose sidecar set passed the
/// active-validator-view quorum alignment gate.
entropyTierValidatorQuorum = 3,
};
} // namespace ripple
#endif

View File

@@ -1,33 +0,0 @@
#ifndef RIPPLE_PROTOCOL_EXPORT_LIMITS_H_INCLUDED
#define RIPPLE_PROTOCOL_EXPORT_LIMITS_H_INCLUDED
#include <cstdint>
namespace ripple {
// Export system caps.
//
// These limits bound the DoS surface of the export signature system:
// - Each pending export requires every validator to sign it every round
// (sign-once, attach once via TMProposeSet)
// - Inbound signature processing involves crypto verification per sig
// - The open-ledger cap (maxPendingExports) is the root constraint;
// signing throughput and inbound processing are transitively bounded by it
struct ExportLimits
{
// Maximum exports a single hook execution may produce
// (also enforced by hook_api::max_export in Enum.h)
static constexpr std::uint8_t maxExportsPerHook = 2;
// Maximum pending export transactions in an open/apply ledger.
// Hook-emitted export backlog drains into the open ledger at this cap.
// This transitively caps:
// - signatures per TMProposeSet message (1 per pending export)
// - inbound proposal signature processing (clamped to this)
// - validator signing work per round
static constexpr std::uint8_t maxPendingExports = 8;
};
} // namespace ripple
#endif

View File

@@ -33,39 +33,35 @@
*
* Steps required to add new features to the code:
*
* 1) Add the appropriate XRPL_FEATURE or XRPL_FIX macro definition for the
* feature to features.macro with the feature's name, `Supported::no`, and
* `VoteBehavior::DefaultNo`.
*
* 2) Use the generated variable name as the parameter to `view.rules.enabled()`
* to control flow into new code that this feature limits. (featureName or
* fixName)
*
* 3) If the feature development is COMPLETE, and the feature is ready to be
* SUPPORTED, change the macro parameter in features.macro to Supported::yes.
*
* 4) In general, any newly supported amendments (`Supported::yes`) should have
* a `VoteBehavior::DefaultNo` indefinitely so that external governance can
* make the decision on when to activate it. High priority bug fixes can be
* an exception to this rule. In such cases, ensure the fix has been
* clearly communicated to the community using appropriate channels,
* then change the macro parameter in features.macro to
* `VoteBehavior::DefaultYes`. The communication process is beyond
* the scope of these instructions.
*
* 1) In this file, increment `numFeatures` and add a uint256 declaration
* for the feature at the bottom
* 2) Add a uint256 definition for the feature to the corresponding source
* file (Feature.cpp). Use `registerFeature` to create the feature with
* the feature's name, `Supported::no`, and `VoteBehavior::DefaultNo`. This
* should be the only place the feature's name appears in code as a string.
* 3) Use the uint256 as the parameter to `view.rules.enabled()` to
* control flow into new code that this feature limits.
* 4) If the feature development is COMPLETE, and the feature is ready to be
* SUPPORTED, change the `registerFeature` parameter to Supported::yes.
* 5) When the feature is ready to be ENABLED, change the `registerFeature`
* parameter to `VoteBehavior::DefaultYes`.
* In general, any newly supported amendments (`Supported::yes`) should have
* a `VoteBehavior::DefaultNo` for at least one full release cycle. High
* priority bug fixes can be an exception to this rule of thumb.
*
* When a feature has been enabled for several years, the conditional code
* may be removed, and the feature "retired". To retire a feature:
*
* 1) MOVE the macro definition in features.macro to the "retired features"
* section at the end of the file, and change the macro to XRPL_RETIRE.
*
* 1) Remove the uint256 declaration from this file.
* 2) MOVE the uint256 definition in Feature.cpp to the "retired features"
* section at the end of the file.
* 3) CHANGE the name of the variable to start with "retired".
* 4) CHANGE the parameters of the `registerFeature` call to `Supported::yes`
* and `VoteBehavior::DefaultNo`.
* The feature must remain registered and supported indefinitely because it
* may exist in the Amendments object on ledger. There is no need to vote
* for it because there's nothing to vote for. If the feature definition is
* removed completely from the code, any instances running that code will get
* amendment blocked. Removing the feature from the ledger is beyond the scope
* of these instructions.
* still exists in the ledger, but there is no need to vote for it because
* there's nothing to vote for. If it is removed completely from the code, any
* instances running that code will get amendment blocked. Removing the
* feature from the ledger is beyond the scope of these instructions.
*
*/
@@ -80,32 +76,11 @@ allAmendments();
namespace detail {
#pragma push_macro("XRPL_FEATURE")
#undef XRPL_FEATURE
#pragma push_macro("XRPL_FIX")
#undef XRPL_FIX
#pragma push_macro("XRPL_RETIRE")
#undef XRPL_RETIRE
#define XRPL_FEATURE(name, supported, vote) +1
#define XRPL_FIX(name, supported, vote) +1
#define XRPL_RETIRE(name) +1
// This value SHOULD be equal to the number of amendments registered in
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures =
(0 +
#include <xrpl/protocol/detail/features.macro>
);
#undef XRPL_RETIRE
#pragma pop_macro("XRPL_RETIRE")
#undef XRPL_FIX
#pragma pop_macro("XRPL_FIX")
#undef XRPL_FEATURE
#pragma pop_macro("XRPL_FEATURE")
static constexpr std::size_t numFeatures = 116;
/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
@@ -345,17 +320,12 @@ foreachFeature(FeatureBitset bs, F&& f)
#undef XRPL_FEATURE
#pragma push_macro("XRPL_FIX")
#undef XRPL_FIX
#pragma push_macro("XRPL_RETIRE")
#undef XRPL_RETIRE
#define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name;
#define XRPL_FIX(name, supported, vote) extern uint256 const fix##name;
#define XRPL_RETIRE(name)
#include <xrpl/protocol/detail/features.macro>
#undef XRPL_RETIRE
#pragma pop_macro("XRPL_RETIRE")
#undef XRPL_FIX
#pragma pop_macro("XRPL_FIX")
#undef XRPL_FEATURE

View File

@@ -96,14 +96,6 @@ enum class HashPrefix : std::uint32_t {
/** Credentials signature */
credential = detail::make_hash_prefix('C', 'R', 'D'),
/** consensus extension sidecar object */
sidecar = detail::make_hash_prefix('S', 'C', 'R'),
/** consensus-bound fallback entropy digest (Tier 3: derived from
already-agreed round inputs when validator reveal quorum is not
available; never to be confused with validator entropy) */
entropyFallback = detail::make_hash_prefix('E', 'F', 'B'),
};
template <class Hasher>

View File

@@ -62,9 +62,6 @@ emittedDir() noexcept;
Keylet
emittedTxn(uint256 const& id) noexcept;
Keylet
shadowTicket(AccountID const& account, std::uint32_t ticketSeq) noexcept;
Keylet
hookDefinition(uint256 const& hash) noexcept;
@@ -121,10 +118,6 @@ negativeUNL() noexcept;
Keylet const&
UNLReport() noexcept;
/** The (fixed) index of the object containing consensus-derived entropy. */
Keylet const&
consensusEntropy() noexcept;
/** The beginning of an order book */
struct book_t
{

View File

@@ -1,21 +0,0 @@
#ifndef RIPPLE_PROTOCOL_SIDECAR_TYPE_H_INCLUDED
#define RIPPLE_PROTOCOL_SIDECAR_TYPE_H_INCLUDED
#include <cstdint>
namespace ripple {
/// Discriminator for sidecar set entries (SHAMap leaves used for
/// consensus extension data: RNG commit/reveal, export signatures).
///
/// Stored in sfSidecarType (UINT8) on each STObject entry.
/// Makes sidecar sets self-describing — no content-sniffing needed.
enum SidecarType : std::uint8_t {
sidecarRngCommit = 1,
sidecarRngReveal = 2,
sidecarExportSig = 3,
};
} // namespace ripple
#endif

View File

@@ -68,7 +68,6 @@ enum TELcodes : TERUnderlyingType {
telNON_LOCAL_EMITTED_TXN,
telIMPORT_VL_KEY_NOT_RECOGNISED,
telCAN_NOT_QUEUE_IMPORT,
telSHADOW_TICKET_REQUIRED,
telENV_RPC_FAILED,
};
@@ -138,7 +137,6 @@ enum TEMcodes : TERUnderlyingType {
temXCHAIN_BRIDGE_NONDOOR_OWNER,
temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT,
temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT,
temXCHAIN_TOO_MANY_ATTESTATIONS, // RESERVED - not used
temHOOK_DATA_TOO_LARGE,
temEMPTY_DID,
@@ -235,10 +233,8 @@ enum TERcodes : TERUnderlyingType {
terQUEUED, // Transaction is being held in TxQ until fee drops
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
terNO_AMM, // AMM doesn't exist for the asset pair
terNO_HOOK, // Transaction requires a non-existent hook definition
terNO_HOOK // Transaction requires a non-existent hook definition
// (referenced by sfHookHash)
terRETRY_EXPORT // Export does not yet have enough validator signatures.
// Retained in retriable set for next ledger.
};
//------------------------------------------------------------------------------
@@ -366,7 +362,7 @@ enum TECcodes : TERUnderlyingType {
tecARRAY_TOO_LARGE = 197,
tecLOCKED = 198,
tecBAD_CREDENTIALS = 199,
tecEXPORT_EXPIRED = 200,
tecINVALID_HOOK_API_VERSION = 200,
tecLAST_POSSIBLE_ENTRY = 255,
};

View File

@@ -274,13 +274,6 @@ enum BridgeModifyFlags : uint32_t {
tfClearAccountCreateAmount = 0x00010000,
};
constexpr std::uint32_t tfBridgeModifyMask = ~(tfUniversal | tfClearAccountCreateAmount);
// ConsensusEntropy flags (used on ttCONSENSUS_ENTROPY SHAMap entries):
enum ConsensusEntropyFlags : uint32_t {
tfEntropyCommit = 0x00000001, // entry is a commitment in commitSet
tfEntropyReveal = 0x00000002, // entry is a reveal in entropySet
};
// flag=0 (no tfEntropyCommit/tfEntropyReveal) = final injected pseudo-tx
// clang-format on
} // namespace ripple

View File

@@ -140,12 +140,6 @@ public:
mHookEmissions = hookEmissions;
}
void
setExportResult(STObject const& exportResult)
{
mExportResult = exportResult;
}
bool
hasHookExecutions() const
{
@@ -158,12 +152,6 @@ public:
return static_cast<bool>(mHookEmissions);
}
bool
hasExportResult() const
{
return static_cast<bool>(mExportResult);
}
STAmount
getDeliveredAmount() const
{
@@ -188,7 +176,6 @@ private:
std::optional<STAmount> mDelivered;
std::optional<STArray> mHookExecutions;
std::optional<STArray> mHookEmissions;
std::optional<STObject> mExportResult;
STArray mNodes;
};

View File

@@ -23,9 +23,6 @@
#if !defined(XRPL_FIX)
#error "undefined macro: XRPL_FIX"
#endif
#if !defined(XRPL_RETIRE)
#error "undefined macro: XRPL_RETIRE"
#endif
// clang-format off
@@ -34,9 +31,7 @@
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(IOURewardClaim, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(JSHooks, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (IOULockedBalanceInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ImportIssuer, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
@@ -62,18 +57,16 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYe
XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Export, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ConsensusEntropy, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RewardClaimFlags, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookCanEmit, Supported::yes, VoteBehavior::DefaultNo)
@@ -157,24 +150,4 @@ XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
// The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated.
// All known amendments and amendments that may appear in a validated
// ledger must be registered either here or above with the "active" amendments
XRPL_RETIRE(MultiSign)
XRPL_RETIRE(TrustSetAuth)
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(fix1368)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(fix1373)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(fix1201)
XRPL_RETIRE(fix1512)
XRPL_RETIRE(fix1523)
XRPL_RETIRE(fix1528)
// clang-format on

View File

@@ -223,21 +223,6 @@ LEDGER_ENTRY(ltURI_TOKEN, 0x0055, URIToken, uri_token, ({
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** The ledger object which stores consensus-derived entropy.
\note This is a singleton: only one such object exists in the ledger.
\sa keylet::consensusEntropy
*/
LEDGER_ENTRY_DUPLICATE(ltCONSENSUS_ENTROPY, 0x0058, ConsensusEntropy, consensus_entropy, ({
{sfDigest, soeREQUIRED},
{sfEntropyCount, soeREQUIRED},
{sfEntropyTier, soeREQUIRED},
{sfLedgerSequence, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** A ledger object which describes an account.
\sa keylet::account
@@ -411,8 +396,6 @@ LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({
{sfHighQualityOut, soeOPTIONAL},
{sfLockedBalance, soeOPTIONAL},
{sfLockCount, soeOPTIONAL},
{sfHighReward, soeOPTIONAL},
{sfLowReward, soeOPTIONAL},
}))
/** The ledger object which lists the network's fee settings.
@@ -607,22 +590,6 @@ LEDGER_ENTRY(ltDID, 0x008D, DID, did, ({
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
//@@start shadow-ticket-ledger-entry
/** A shadow ticket for export replay protection.
Created when a transaction is exported. Consumed when
proof-of-execution is imported back. Account-owned (pays reserve).
\sa keylet::shadowTicket
*/
LEDGER_ENTRY(ltSHADOW_TICKET, 0x5374, ShadowTicket, shadow_ticket, ({
{sfAccount, soeREQUIRED},
{sfTicketSequence, soeREQUIRED},
{sfTransactionHash, soeREQUIRED},
{sfLedgerSequence, soeREQUIRED},
{sfOwnerNode, soeREQUIRED},
}))
//@@end shadow-ticket-ledger-entry
#undef EXPAND
#undef LEDGER_ENTRY_DUPLICATE

View File

@@ -42,8 +42,6 @@ TYPED_SFIELD(sfTickSize, UINT8, 16)
TYPED_SFIELD(sfUNLModifyDisabling, UINT8, 17)
TYPED_SFIELD(sfHookResult, UINT8, 18)
TYPED_SFIELD(sfWasLockingChainSend, UINT8, 19)
TYPED_SFIELD(sfSidecarType, UINT8, 20)
TYPED_SFIELD(sfEntropyTier, UINT8, 21)
// 16-bit integers (common)
TYPED_SFIELD(sfLedgerEntryType, UINT16, 1, SField::sMD_Never)
@@ -61,8 +59,6 @@ TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
TYPED_SFIELD(sfHookStateScale, UINT16, 21)
TYPED_SFIELD(sfLedgerFixType, UINT16, 22)
TYPED_SFIELD(sfHookExportCount, UINT16, 98)
TYPED_SFIELD(sfEntropyCount, UINT16, 99)
// 32-bit integers (common)
TYPED_SFIELD(sfNetworkID, UINT32, 1)
@@ -127,7 +123,6 @@ TYPED_SFIELD(sfImportSequence, UINT32, 97)
TYPED_SFIELD(sfRewardTime, UINT32, 98)
TYPED_SFIELD(sfRewardLgrFirst, UINT32, 99)
TYPED_SFIELD(sfRewardLgrLast, UINT32, 100)
TYPED_SFIELD(sfCancelTicketSequence, UINT32, 101)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -222,7 +217,6 @@ TYPED_SFIELD(sfHookCanEmit, UINT256, 96)
TYPED_SFIELD(sfEmittedTxnID, UINT256, 97)
TYPED_SFIELD(sfGovernanceMarks, UINT256, 98)
TYPED_SFIELD(sfGovernanceFlags, UINT256, 99)
TYPED_SFIELD(sfEntropyDigest, UINT256, 100)
// number (common)
TYPED_SFIELD(sfNumber, NUMBER, 1)
@@ -263,7 +257,6 @@ TYPED_SFIELD(sfPrice, AMOUNT, 28)
TYPED_SFIELD(sfSignatureReward, AMOUNT, 29)
TYPED_SFIELD(sfMinAccountCreateAmount, AMOUNT, 30)
TYPED_SFIELD(sfLPTokenBalance, AMOUNT, 31)
TYPED_SFIELD(sfTrustLineRewardAccumulator,AMOUNT, 99)
// variable length (common)
TYPED_SFIELD(sfPublicKey, VL, 1)
@@ -299,7 +292,6 @@ TYPED_SFIELD(sfAssetClass, VL, 29)
TYPED_SFIELD(sfProvider, VL, 30)
TYPED_SFIELD(sfMPTokenMetadata, VL, 31)
TYPED_SFIELD(sfCredentialType, VL, 32)
TYPED_SFIELD(sfHookName, VL, 97)
TYPED_SFIELD(sfRemarkValue, VL, 98)
TYPED_SFIELD(sfRemarkName, VL, 99)
@@ -348,7 +340,6 @@ TYPED_SFIELD(sfLockingChainIssue, ISSUE, 1)
TYPED_SFIELD(sfIssuingChainIssue, ISSUE, 2)
TYPED_SFIELD(sfAsset, ISSUE, 3)
TYPED_SFIELD(sfAsset2, ISSUE, 4)
TYPED_SFIELD(sfClaimCurrency, ISSUE, 5)
// bridge
TYPED_SFIELD(sfXChainBridge, XCHAIN_BRIDGE, 1)
@@ -388,7 +379,6 @@ UNTYPED_SFIELD(sfXChainClaimAttestationCollectionElement, OBJECT, 30)
UNTYPED_SFIELD(sfXChainCreateAccountAttestationCollectionElement, OBJECT, 31)
UNTYPED_SFIELD(sfPriceData, OBJECT, 32)
UNTYPED_SFIELD(sfCredential, OBJECT, 33)
UNTYPED_SFIELD(sfExportedTxn, OBJECT, 90)
UNTYPED_SFIELD(sfAmountEntry, OBJECT, 91)
UNTYPED_SFIELD(sfMintURIToken, OBJECT, 92)
UNTYPED_SFIELD(sfHookEmission, OBJECT, 93)
@@ -396,9 +386,6 @@ UNTYPED_SFIELD(sfImportVLKey, OBJECT, 94)
UNTYPED_SFIELD(sfActiveValidator, OBJECT, 95)
UNTYPED_SFIELD(sfGenesisMint, OBJECT, 96)
UNTYPED_SFIELD(sfRemark, OBJECT, 97)
UNTYPED_SFIELD(sfHighReward, OBJECT, 98)
UNTYPED_SFIELD(sfLowReward, OBJECT, 99)
UNTYPED_SFIELD(sfExportResult, OBJECT, 100)
// array of objects (common)
// ARRAY/1 is reserved for end of array

View File

@@ -500,17 +500,6 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 72, PermissionedDomainDelete, ({
{sfDomainID, soeREQUIRED},
}))
//@@start export-transaction-types
/* User-submittable export: creates a cross-chain transaction for
validator signing. Retries via terRETRY_EXPORT until quorum.
Also supports shadow ticket cancellation via sfCancelTicketSequence.
At least one of sfExportedTxn or sfCancelTicketSequence must be present. */
TRANSACTION(ttEXPORT, 91, Export, ({
{sfExportedTxn, soeOPTIONAL},
{sfCancelTicketSequence, soeOPTIONAL},
}))
//@@end export-transaction-types
/* A pseudo-txn alarm signal for invoking a hook, emitted by validators after alarm set conditions are met */
TRANSACTION(ttCRON, 92, Cron, ({
{sfOwner, soeREQUIRED},
@@ -561,7 +550,6 @@ TRANSACTION(ttIMPORT, 97, Import, ({
* from a specified hook */
TRANSACTION(ttCLAIM_REWARD, 98, ClaimReward, ({
{sfIssuer, soeOPTIONAL},
{sfClaimCurrency, soeOPTIONAL},
}))
/** This transaction invokes a hook, providing arbitrary data. Essentially as a 0 drop payment. **/
@@ -617,11 +605,3 @@ TRANSACTION(ttUNL_REPORT, 104, UNLReport, ({
{sfActiveValidator, soeOPTIONAL},
{sfImportVLKey, soeOPTIONAL},
}))
TRANSACTION(ttCONSENSUS_ENTROPY, 105, ConsensusEntropy, ({
{sfLedgerSequence, soeREQUIRED},
{sfDigest, soeREQUIRED},
{sfEntropyCount, soeREQUIRED},
{sfEntropyTier, soeREQUIRED},
{sfBlob, soeOPTIONAL},
}))

View File

@@ -76,7 +76,6 @@ JSS(Holder); // field.
JSS(HookApiVersion); // field
JSS(HookCanEmit); // field
JSS(HookHash); // field
JSS(HookName); // field
JSS(HookNamespace); // field
JSS(HookOn); // field
JSS(HookOnIncoming); // field

View File

@@ -109,22 +109,14 @@ public:
Consumer
newInboundEndpoint(beast::IP::Endpoint const& address)
{
//@@start rng-local-testnet-resource-bucket
// Inbound connections from the same IP normally share one
// resource bucket (port stripped) for DoS protection. For
// loopback addresses, preserve the port so local testnet nodes
// each get their own bucket instead of all sharing one.
auto const key = is_loopback(address) ? address : address.at_port(0);
//@@end rng-local-testnet-resource-bucket
Entry* entry(nullptr);
{
std::lock_guard _(lock_);
auto [resultIt, resultInserted] = table_.emplace(
std::piecewise_construct,
std::make_tuple(kindInbound, key),
std::make_tuple(m_clock.now()));
std::make_tuple(kindInbound, address.at_port(0)), // Key
std::make_tuple(m_clock.now())); // Entry
entry = &resultIt->second;
entry->key = &resultIt->first;

View File

@@ -11,11 +11,11 @@ echo "START BUILDING (HOST)"
echo "Cleaning previously built binary"
rm -f release-build/xahaud
BUILD_CORES=$(echo "scale=0 ; $(nproc) / 1.337" | bc)
BUILD_CORES=$(echo "scale=0 ; `nproc` / 1.337" | bc)
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
#Default
BUILD_CORES=${BUILD_CORES:-8}
BUILD_CORES=${BUILD_CORES:-8}
fi
# Ensure still works outside of GH Actions by setting these to /dev/null
@@ -31,19 +31,21 @@ echo "-- GITHUB_SHA: $GITHUB_SHA"
echo "-- GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER"
echo "-- CONTAINER_NAME: $CONTAINER_NAME"
which docker 2>/dev/null 2>/dev/null
if [ "$?" -eq "1" ]; then
which docker 2> /dev/null 2> /dev/null
if [ "$?" -eq "1" ]
then
echo 'Docker not found. Install it first.'
exit 1
fi
stat .git 2>/dev/null 2>/dev/null
if [ "$?" -eq "1" ]; then
stat .git 2> /dev/null 2> /dev/null
if [ "$?" -eq "1" ]
then
echo 'Run this inside the source directory. (.git dir not found).'
exit 1
fi
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME | wc -l)
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME |wc -l)
CACHE_VOLUME_NAME="xahau-release-builder-cache"
@@ -55,14 +57,13 @@ if false; then
docker stop $CONTAINER_NAME
else
echo "No static container, build on temp container"
rm -rf release-build
mkdir -p release-build
rm -rf release-build;
mkdir -p release-build;
docker volume create $CACHE_VOLUME_NAME
# Create inline Dockerfile with environment setup for build-full.sh
DOCKERFILE_CONTENT=$(
cat <<'DOCKERFILE_EOF'
DOCKERFILE_CONTENT=$(cat <<'DOCKERFILE_EOF'
FROM ghcr.io/phusion/holy-build-box:4.0.1-amd64
ARG BUILD_CORES=8
@@ -217,7 +218,7 @@ RUN /hbb_exe/activate-exec bash -c "ccache -M 100G && \
ln -s ../../bin/ccache /usr/lib64/ccache/c++"
DOCKERFILE_EOF
)
)
# Build custom Docker image
IMAGE_NAME="xahaud-builder:latest"
@@ -227,14 +228,14 @@ DOCKERFILE_EOF
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
# Non GH, local building
echo "Non-GH runner, local building, temp container"
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
else
# GH Action, runner
echo "GH Action, runner, clean & re-create create persistent container"
docker rm -f $CONTAINER_NAME
echo "echo 'Stopping container: $CONTAINER_NAME'" >>"$JOB_CLEANUP_SCRIPT"
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >>"$JOB_CLEANUP_SCRIPT"
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
echo "echo 'Stopping container: $CONTAINER_NAME'" >> "$JOB_CLEANUP_SCRIPT"
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >> "$JOB_CLEANUP_SCRIPT"
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
docker stop $CONTAINER_NAME
fi

View File

@@ -31,7 +31,6 @@
#include <cassert>
#include <cstring>
#include <ctime>
#include <exception>
#include <fstream>
#include <functional>
#include <iostream>
@@ -352,18 +351,9 @@ Logs::format(
if (useLocalTime)
{
try
{
auto now = std::chrono::system_clock::now();
auto local = date::make_zoned(date::current_zone(), now);
output = date::format(fmt, local);
}
catch (std::exception const&)
{
// Enhanced logging should not make startup fatal if tzdb lookup is
// unavailable or misconfigured. Fall back to UTC formatting.
output = date::format(fmt, std::chrono::system_clock::now());
}
auto now = std::chrono::system_clock::now();
auto local = date::make_zoned(date::current_zone(), now);
output = date::format(fmt, local);
}
else
{

View File

@@ -66,7 +66,7 @@ invalidAMMAsset(
Issue const& issue,
std::optional<std::pair<Issue, Issue>> const& pair)
{
if (isBadCurrency(issue.currency))
if (badCurrency() == issue.currency)
return temBAD_CURRENCY;
if (isXRP(issue) && issue.account.isNonZero())
return temBAD_ISSUER;

View File

@@ -250,9 +250,12 @@ FeatureCollections::registerFeature(
Feature const* i = getByName(name);
if (!i)
{
// If this check fails, and you just added a feature, increase the
// numFeatures value in Feature.h
check(
features.size() < detail::numFeatures,
"More features defined than allocated.");
"More features defined than allocated. Adjust numFeatures in "
"Feature.h.");
auto const f = sha512Half(Slice(name.data(), name.size()));
@@ -421,26 +424,45 @@ featureToName(uint256 const& f)
#undef XRPL_FEATURE
#pragma push_macro("XRPL_FIX")
#undef XRPL_FIX
#pragma push_macro("XRPL_RETIRE")
#undef XRPL_RETIRE
#define XRPL_FEATURE(name, supported, vote) \
uint256 const feature##name = registerFeature(#name, supported, vote);
#define XRPL_FIX(name, supported, vote) \
uint256 const fix##name = registerFeature("fix" #name, supported, vote);
#define XRPL_RETIRE(name) \
[[deprecated("The referenced amendment has been retired"), maybe_unused]] \
uint256 const retired##name = retireFeature(#name);
#include <xrpl/protocol/detail/features.macro>
#undef XRPL_RETIRE
#pragma pop_macro("XRPL_RETIRE")
#undef XRPL_FIX
#pragma pop_macro("XRPL_FIX")
#undef XRPL_FEATURE
#pragma pop_macro("XRPL_FEATURE")
// clang-format off
// The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated.
// All known amendments and amendments that may appear in a validated
// ledger must be registered either here or above with the "active" amendments
[[deprecated("The referenced amendment has been retired"), maybe_unused]]
uint256 const
retiredMultiSign = retireFeature("MultiSign"),
retiredTrustSetAuth = retireFeature("TrustSetAuth"),
retiredFeeEscalation = retireFeature("FeeEscalation"),
retiredPayChan = retireFeature("PayChan"),
retiredCryptoConditions = retireFeature("CryptoConditions"),
retiredTickSize = retireFeature("TickSize"),
retiredFix1368 = retireFeature("fix1368"),
retiredEscrow = retireFeature("Escrow"),
retiredFix1373 = retireFeature("fix1373"),
retiredEnforceInvariants = retireFeature("EnforceInvariants"),
retiredSortedDirectories = retireFeature("SortedDirectories"),
retiredFix1201 = retireFeature("fix1201"),
retiredFix1512 = retireFeature("fix1512"),
retiredFix1523 = retireFeature("fix1523"),
retiredFix1528 = retireFeature("fix1528");
// clang-format on
// All of the features should now be registered, since variables in a cpp file
// are initialized from top to bottom.
//

View File

@@ -74,7 +74,6 @@ enum class LedgerNameSpace : std::uint16_t {
HOOK_DEFINITION = 'D',
EMITTED_TXN = 'E',
EMITTED_DIR = 'F',
SHADOW_TICKET = 0x5374, // St
NFTOKEN_OFFER = 'q',
NFTOKEN_BUY_OFFERS = 'h',
NFTOKEN_SELL_OFFERS = 'i',
@@ -82,7 +81,6 @@ enum class LedgerNameSpace : std::uint16_t {
IMPORT_VLSEQ = 'I',
UNL_REPORT = 'R',
CRON = 'L',
CONSENSUS_ENTROPY = 'X',
AMM = 'A',
BRIDGE = LEDGER_NAMESPACE2(0x01, 'H'),
XCHAIN_CLAIM_ID = 'Q',
@@ -190,15 +188,6 @@ emittedTxn(uint256 const& id) noexcept
return {ltEMITTED_TXN, indexHash(LedgerNameSpace::EMITTED_TXN, id)};
}
Keylet
shadowTicket(AccountID const& account, std::uint32_t ticketSeq) noexcept
{
return {
ltSHADOW_TICKET,
indexHash(
LedgerNameSpace::SHADOW_TICKET, account, std::uint32_t(ticketSeq))};
}
Keylet
hook(AccountID const& id) noexcept
{
@@ -557,14 +546,6 @@ cron(uint32_t timestamp, std::optional<AccountID> const& id)
return {ltCRON, uint256::fromVoid(h)};
}
Keylet const&
consensusEntropy() noexcept
{
static Keylet const ret{
ltCONSENSUS_ENTROPY, indexHash(LedgerNameSpace::CONSENSUS_ENTROPY)};
return ret;
}
Keylet
amm(Asset const& issue1, Asset const& issue2) noexcept
{

View File

@@ -78,7 +78,6 @@ InnerObjectFormats::InnerObjectFormats()
{sfHookExecutionIndex, soeREQUIRED},
{sfHookStateChangeCount, soeREQUIRED},
{sfHookEmitCount, soeREQUIRED},
{sfHookExportCount, soeOPTIONAL},
{sfFlags, soeOPTIONAL}});
add(sfHookEmission.jsonName,
@@ -100,7 +99,7 @@ InnerObjectFormats::InnerObjectFormats()
{sfHookOnOutgoing, soeOPTIONAL},
{sfHookCanEmit, soeOPTIONAL},
{sfHookApiVersion, soeOPTIONAL},
{sfHookName, soeOPTIONAL},
{sfFee, soeOPTIONAL},
{sfFlags, soeOPTIONAL}});
add(sfHookGrant.jsonName,
@@ -255,24 +254,6 @@ InnerObjectFormats::InnerObjectFormats()
{sfIssuer, soeREQUIRED},
{sfCredentialType, soeREQUIRED},
});
add(sfHighReward.jsonName,
sfHighReward.getCode(),
{
{sfRewardLgrFirst, soeREQUIRED},
{sfRewardLgrLast, soeREQUIRED},
{sfRewardTime, soeREQUIRED},
{sfTrustLineRewardAccumulator, soeREQUIRED},
});
add(sfLowReward.jsonName,
sfLowReward.getCode(),
{
{sfRewardLgrFirst, soeREQUIRED},
{sfRewardLgrLast, soeREQUIRED},
{sfRewardTime, soeREQUIRED},
{sfTrustLineRewardAccumulator, soeREQUIRED},
});
}
InnerObjectFormats const&

View File

@@ -111,7 +111,7 @@ issueFromJson(Json::Value const& v)
}
auto const currency = to_currency(curStr.asString());
if (isBadCurrency(currency) || currency == noCurrency())
if (currency == badCurrency() || currency == noCurrency())
{
Throw<Json::error>("issueFromJson currency must be a valid currency");
}

View File

@@ -103,7 +103,7 @@ currencyFromJson(SField const& name, Json::Value const& v)
}
auto const currency = to_currency(v.asString());
if (isBadCurrency(currency) || currency == noCurrency())
if (currency == badCurrency() || currency == noCurrency())
{
Throw<std::runtime_error>(
"currencyFromJson currency must be a valid currency");

View File

@@ -684,8 +684,7 @@ isPseudoTx(STObject const& tx)
auto tt = safe_cast<TxType>(*t);
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY ||
tt == ttEMIT_FAILURE || tt == ttUNL_REPORT || tt == ttCRON ||
tt == ttCONSENSUS_ENTROPY;
tt == ttEMIT_FAILURE || tt == ttUNL_REPORT || tt == ttCRON;
}
} // namespace ripple

View File

@@ -124,7 +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(tecEXPORT_EXPIRED, "Export expired without reaching signature quorum."),
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."),
@@ -172,7 +172,6 @@ transResults()
MAKE_ERROR(telNON_LOCAL_EMITTED_TXN, "Emitted transaction cannot be applied because it was not generated locally."),
MAKE_ERROR(telIMPORT_VL_KEY_NOT_RECOGNISED, "Import vl key was not recognized."),
MAKE_ERROR(telCAN_NOT_QUEUE_IMPORT, "Import transaction was not able to be directly applied and cannot be queued."),
MAKE_ERROR(telSHADOW_TICKET_REQUIRED, "The imported transaction uses a TicketSequence but no shadow ticket exists."),
MAKE_ERROR(telENV_RPC_FAILED, "Unit test RPC failure."),
MAKE_ERROR(temMALFORMED, "Malformed transaction."),
@@ -240,7 +239,6 @@ transResults()
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
MAKE_ERROR(terNO_HOOK, "No hook with that hash exists on the ledger."),
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
MAKE_ERROR(terRETRY_EXPORT, "Export awaiting validator signatures."),
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
MAKE_ERROR(tesPARTIAL, "The transaction was applied but should be submitted again until returning tesSUCCESS."),

View File

@@ -48,7 +48,6 @@ TxFormats::TxFormats()
{sfFirstLedgerSequence, soeOPTIONAL},
{sfNetworkID, soeOPTIONAL},
{sfHookParameters, soeOPTIONAL},
{sfHookName, soeOPTIONAL},
};
#pragma push_macro("UNWRAP")

View File

@@ -49,11 +49,6 @@ TxMeta::TxMeta(
if (obj.isFieldPresent(sfHookEmissions))
setHookEmissions(obj.getFieldArray(sfHookEmissions));
if (obj.isFieldPresent(sfExportResult))
setExportResult(const_cast<STObject&>(obj)
.getField(sfExportResult)
.downcast<STObject>());
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
@@ -80,11 +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(sfExportResult))
setExportResult(const_cast<STObject&>(obj)
.getField(sfExportResult)
.downcast<STObject>());
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
@@ -255,14 +245,6 @@ TxMeta::getAsObject() const
if (hasHookEmissions())
metaData.setFieldArray(sfHookEmissions, getHookEmissions());
if (hasExportResult())
{
Serializer s;
mExportResult->add(s);
SerialIter sit(s.slice());
metaData.emplace_back(STObject(sit, sfExportResult));
}
return metaData;
}

820
src/quickjs/buffer-utils.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

535
src/quickjs/libbf.h Normal file
View 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 */

View 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

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More