Compare commits

..

74 Commits

Author SHA1 Message Date
JCW
80f649055b Address clang-tidy error 2026-07-06 15:41:06 +01:00
JCW
cffdaea8f1 Fix test errors 2026-07-06 12:00:20 +01:00
Jingchen
26de3f2561 Merge branch 'develop' into a1q123456/fix-is-valid-develop 2026-07-06 11:50:01 +01:00
Ayaz Salikhov
c92285f10d chore: Delete dead code (#7718) 2026-07-03 15:59:20 +00:00
Ayaz Salikhov
53649cc298 chore: Enable modernize-use-constraints (#7715) 2026-07-03 14:28:15 +00:00
Ayaz Salikhov
f151293e8a chore: Enable modernize-avoid-bind (#7711) 2026-07-03 11:17:03 +00:00
Ayaz Salikhov
7ba1d76d05 chore: Enable modernize-use-auto (#7707) 2026-07-02 20:02:55 +00:00
Bart
3d847f2a60 build: Add protobuf dependencies to Nix (#7706)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-02 18:46:27 +00:00
yinyiqian1
6003fd03fc feat: Enable ConfidentialTransfer and BatchV1_1 (#7698) 2026-07-02 18:37:37 +00:00
Ayaz Salikhov
41622b87ae chore: Enable modernize-unary-static-assert (#7705) 2026-07-02 18:30:59 +00:00
Ayaz Salikhov
6f0f5b8bb3 chore: Make clang-tidy happy on macOS (#7701) 2026-07-02 16:26:09 +00:00
Bart
3b9e24e0e0 chore: Improve pre-commit hooks (#7702)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-02 15:01:30 +00:00
Timothy Banks
4c619e8a85 refactor: Retire DisallowIncomingV1 fix (#7364) 2026-07-02 14:17:32 +00:00
Ayaz Salikhov
8e378c4f47 build: Add verify-headers target to cleanup headers (#7670) 2026-07-01 23:14:17 +00:00
Timothy Banks
c53aafa6bf refactor: Retire InnerObjTemplate fix (#7368) 2026-07-01 15:36:28 +00:00
Vito Tumas
0d149ba5b6 fix: Disable AMM creation with Vault shares (#7666) 2026-07-01 15:04:38 +00:00
Ayaz Salikhov
d1ff948244 test: Add tests for TMProofPathResponse and TMReplayDeltaResponse invalid hash/key sizes (#7593) 2026-07-01 13:30:03 +00:00
dependabot[bot]
ba739c94ce ci: [DEPENDABOT] bump actions/setup-python from 6.2.0 to 6.3.0 (#7657)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-01 13:29:06 +00:00
Ayaz Salikhov
6d0b758a12 build: Don't reuse binaries between different C++ versions (#7681) 2026-07-01 13:28:41 +00:00
Ayaz Salikhov
6aed3bb71d chore: Update pre-commit hooks && actions (#7686) 2026-07-01 13:28:14 +00:00
Vito Tumas
ea13be81b7 feat: Add an invariant to ensure object deletion also deletes its pseudo-account (#7445)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-07-01 13:21:23 +00:00
Denis Angell
86d8b244d6 feat: Add Batch (XLS-56) V1_1 (#6446)
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-07-01 12:47:14 +00:00
Vito Tumas
ecf7f805c9 feat: Introduce lending 1.1 amendment and add MemoData field to VaultDelete transaction (#6324) 2026-06-30 23:51:41 +00:00
Ayaz Salikhov
8abbd1ba3a chore: Use std::ranges where possible (#7634) 2026-06-30 11:03:19 +00:00
Ayaz Salikhov
95d53b4d43 ci: Use macOS 26 Tahoe with apple-clang 21 (#7601) 2026-06-30 10:43:44 +00:00
Ayaz Salikhov
62bfc4ca5b build: Mark sec256k1 and mpt-crypto as transitive headers (#7658) 2026-06-30 10:43:21 +00:00
Ayaz Salikhov
809a629075 chore: Add a script to nicely format clang-tidy output (#7650) 2026-06-29 13:21:14 +00:00
Ayaz Salikhov
74b55a59b2 chore: Enable most bugprone checks (#7643) 2026-06-29 13:20:17 +00:00
Shawn Xie
768d7603b1 feat: Confidential Transfer for MPT (#5860)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: chuanshanjida <chuanshanjida@outlook.com>
Co-authored-by: Ed Hennis <ed@ripple.com>
Co-authored-by: Jingchen <a1q123456@users.noreply.github.com>
Co-authored-by: Denis Angell <dangell@transia.co>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
Co-authored-by: yinyiqian1 <yqian@ripple.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Bronek Kozicki <brok@incorrekt.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com>
Co-authored-by: tequ <git@tequ.dev>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Peter Chen <34582813+PeterChen13579@users.noreply.github.com>
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Zhiyuan Wang <96991820+Kassaking7@users.noreply.github.com>
Co-authored-by: Alex Kremer <akremer@ripple.com>
Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gregory Tsipenyuk <gregtatcam@users.noreply.github.com>
Co-authored-by: chuanshanjida <chuanshanjida@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Peter Chen <ychen@ripple.com>
Co-authored-by: Timothy Banks <timothyaaronbanks@gmail.com>
Co-authored-by: Timothy Banks <tbanks@ripple.com>
2026-06-27 01:20:38 +00:00
yinyiqian1
fd8a915243 fix: Use trustline balance direction to validate IOU PaymentMint/PaymentBurn (#7584) 2026-06-26 22:26:53 +00:00
Vito Tumas
3e9f1d0ab8 fix: Unify freeze checks for pseudo-account deposit/withdraw (#7382)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Shawn Xie <35279399+shawnxie999@users.noreply.github.com>
2026-06-26 21:38:59 +00:00
yinyiqian1
652b5f9af1 fix: Block delegate tx from being queued (#7640) 2026-06-26 20:34:22 +00:00
Ayaz Salikhov
50fdb38ace chore: Enable groups of clang-tidy checks by default (#7637) 2026-06-26 10:46:39 +00:00
Ayaz Salikhov
bb2ab4243b ci: Better determine when we need to run full clang-tidy (#7635) 2026-06-26 10:42:24 +00:00
Timothy Banks
2ab43b6fda refactor: Retire NFTokenReserve fix (#7367) 2026-06-26 10:31:16 +00:00
Timothy Banks
12a5d9014e refactor: Retire Clawback amendment (#7353) 2026-06-26 10:24:25 +00:00
Mayukha Vadari
b9eee1d245 refactor: Rename (mostly keylet) functions to more closely match the docs (#7059)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-06-26 10:24:12 +00:00
Ayaz Salikhov
0711a7b493 build: Switch to a new conan XRPLF remote, again (#7638) 2026-06-25 22:06:04 +00:00
Ayaz Salikhov
07c64f07f0 chore: Revert "build: Switch to a new conan XRPLF remote (#7622)" (#7623) 2026-06-25 14:47:55 +00:00
Ayaz Salikhov
3097c157b6 build: Switch to a new conan XRPLF remote (#7622) 2026-06-25 08:40:06 -04:00
Michael Legleux
556d62a0de build: Align xrpld RPM packaging with DEB package (#7529) 2026-06-24 23:53:46 +00:00
Ayaz Salikhov
eef8f4a4ff chore: Use clang-tidy v22 new features (#7427) 2026-06-24 17:23:29 +00:00
Ayaz Salikhov
4fec58251b build: Patch nix binaries in CMake (#7539)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-06-24 13:56:18 +00:00
Ayaz Salikhov
8bbbc2051e chore: Check more tools to be available (#7600) 2026-06-24 12:25:03 +00:00
Mayukha Vadari
6736ab39df test: Add test for Permissioned Domain sequence fix (#7591)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-24 12:24:27 +00:00
Ayaz Salikhov
b68e1f7170 fix: Add pragma once checker (#7580) 2026-06-24 12:24:04 +00:00
Timothy Banks
bb7c4d1c9f fix: Additional RPC validation checks on ammRpcInfo account and amm_account fields. (#7324) 2026-06-24 12:23:12 +00:00
Zhiyuan Wang
69d289a388 fix: AMM Quality Leak into Domain BookStep for Permissioned DEX (#6853)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-24 12:15:45 +00:00
Jingchen
6341e75200 refactor: Refactor TaggedCache.ipp to remove const_cast in canonicalize_replace_cache (#5638)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-06-24 12:15:11 +00:00
yinyiqian1
5a2c82f699 fix: Reject delegate permission to pseudo accounts (#7597) 2026-06-23 19:55:23 +00:00
Jingchen
0b22050b5e ci: Update workflows and conan to use VS2026 and grpc 1.81.0 (#7550)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-06-23 19:25:38 +00:00
Bart
ff02269c0d refactor: Use dispatch instead of post (#7438)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-22 22:35:28 +00:00
JCW
c2b07f02b2 Merge remote-tracking branch 'private/develop' into a1q123456/fix-is-valid-develop 2026-05-19 15:01:11 +01:00
JCW
ff2ac99e45 Fix clang-tidy error 2026-05-14 11:40:37 +01:00
Ed Hennis
9a93adea7d Merge branch 'develop' into a1q123456/fix-is-valid-develop 2026-05-13 20:15:29 -04:00
JCW
ba4bf0935a Fix clang-tidy errors 2026-05-13 12:20:57 +01:00
JCW
7db79b3606 Fix an issue 2026-05-13 11:40:46 +01:00
JCW
d9f188fa94 Merge remote-tracking branch 'private/develop' into a1q123456/fix-is-valid-develop 2026-05-12 21:04:49 +01:00
JCW
821b0d6764 Fix clang-tidy errors 2026-05-12 21:04:27 +01:00
JCW
8340cd645b Address PR comments 2026-05-12 20:35:31 +01:00
JCW
9f385aa62a Merge remote-tracking branch 'private/develop' into a1q123456/fix-is-valid-develop 2026-05-12 18:31:08 +01:00
Jingchen
267737fe76 Update src/xrpld/peerfinder/detail/Logic.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-05-12 18:13:15 +01:00
Ayaz Salikhov
0317d3fad2 Merge branch 'develop' into a1q123456/fix-is-valid-develop 2026-04-16 15:23:24 +01:00
JCW
f04c12bc84 Fix formatting 2026-04-16 14:01:26 +01:00
JCW
b2760c04c4 Fix for clang-tidy 2026-04-16 12:33:57 +01:00
JCW
06937e68c0 Fix 2026-04-10 17:11:08 +01:00
JCW
3ccbee28d1 Fix 2026-04-10 17:11:08 +01:00
JCW
494af3aee8 Update comment 2026-04-10 17:11:08 +01:00
JCW
e938405a57 Address PR comments 2026-04-10 17:11:07 +01:00
JCW
068b62bcae Add logging 2026-04-10 17:11:07 +01:00
JCW
39808c8d7c Add logging 2026-04-10 17:11:07 +01:00
JCW
4146596ebc Add an option to allow disabling endpoint verification after tightening the requirements 2026-04-10 17:11:07 +01:00
JCW
98c361608a Address PR comments 2026-04-10 17:10:27 +01:00
JCW
154e0d3a27 Fix is_valid_address 2026-04-10 17:03:41 +01:00
984 changed files with 33596 additions and 6705 deletions

View File

@@ -1,159 +1,140 @@
---
Checks: "-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-bool-pointer-implicit-conversion,
bugprone-capturing-this-in-member-variable,
bugprone-casting-through-void,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
bugprone-copy-constructor-init,
bugprone-crtp-constructor-accessibility,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-empty-catch,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-inaccurate-erase,
bugprone-inc-dec-in-conditions,
bugprone-incorrect-enable-if,
bugprone-incorrect-roundings,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misleading-setter-of-reference,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multi-level-implicit-pointer-conversion,
bugprone-multiple-new-in-one-expression,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-non-zero-enum-to-bool-conversion,
bugprone-optional-value-conversion,
bugprone-parent-virtual-call,
bugprone-pointer-arithmetic-on-polymorphic-object,
bugprone-posix-return,
bugprone-redundant-branch-condition,
bugprone-reserved-identifier,
bugprone-return-const-ref-from-parameter,
bugprone-shared-ptr-array-mismatch,
bugprone-signal-handler,
bugprone-signed-char-misuse,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-standalone-empty,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-stringview-nullptr,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-realloc-usage,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-suspicious-stringview-data-usage,
bugprone-swapped-arguments,
bugprone-switch-missing-default-case,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-unchecked-optional-access,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
bugprone-unhandled-self-assignment,
bugprone-unique-ptr-array-mismatch,
bugprone-unsafe-functions,
bugprone-unused-local-non-trivial-variable,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
cppcoreguidelines-init-variables,
cppcoreguidelines-misleading-capture-default-by-value,
cppcoreguidelines-no-suspend-with-lock,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-use-default-member-init,
cppcoreguidelines-use-enum-class,
cppcoreguidelines-virtual-class-destructor,
hicpp-ignored-remove-result,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-exception-escape,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-narrowing-conversions,
-bugprone-throwing-static-initialization,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-capturing-lambda-coroutines,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-avoid-reference-coroutine-parameters,
-cppcoreguidelines-c-copy-assignment-signature,
-cppcoreguidelines-explicit-virtual-functions,
-cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-macro-to-enum,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-missing-std-forward,
-cppcoreguidelines-narrowing-conversions,
-cppcoreguidelines-no-malloc,
-cppcoreguidelines-noexcept-destructor,
-cppcoreguidelines-noexcept-move-operations,
-cppcoreguidelines-noexcept-swap,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-prefer-member-initializer,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-slicing,
-cppcoreguidelines-special-member-functions,
llvm-namespace-comment,
misc-const-correctness,
misc-definitions-in-headers,
misc-header-include-cycle,
misc-include-cleaner,
misc-misplaced-const,
misc-redundant-expression,
misc-static-assert,
misc-throw-by-value-catch-by-reference,
misc-unused-alias-decls,
misc-unused-using-decls,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-type-traits,
modernize-use-designated-initializers,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-override,
modernize-use-ranges,
modernize-use-scoped-lock,
modernize-use-starts-ends-with,
modernize-use-std-numbers,
modernize-use-using,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-trivially-destructible,
readability-ambiguous-smartptr-reset-call,
readability-avoid-nested-conditional-operator,
readability-avoid-return-with-void-value,
readability-braces-around-statements,
readability-const-return-type,
readability-container-contains,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-duplicate-include,
readability-else-after-return,
readability-enum-initial-value,
readability-identifier-naming,
readability-implicit-bool-conversion,
readability-make-member-function-const,
readability-math-missing-parentheses,
readability-misleading-indentation,
readability-non-const-parameter,
readability-redundant-casting,
readability-redundant-declaration,
readability-redundant-inline-specifier,
readability-redundant-member-init,
readability-redundant-string-init,
readability-reference-to-constructed-temporary,
readability-simplify-boolean-expr,
readability-static-definition-in-anonymous-namespace,
readability-suspicious-call-argument,
readability-use-std-min-max
misc-*,
-misc-anonymous-namespace-in-header,
-misc-confusable-identifiers,
-misc-coroutine-hostile-raii,
-misc-misleading-bidirectional,
-misc-misleading-identifier,
-misc-multiple-inheritance,
-misc-new-delete-overloads,
-misc-no-recursion,
-misc-non-copyable-objects,
-misc-non-private-member-variables-in-classes,
-misc-override-with-different-visibility,
-misc-predictable-rand,
-misc-unconventional-assign-operator,
-misc-uniqueptr-reset-release,
-misc-unused-parameters,
-misc-use-anonymous-namespace,
-misc-use-internal-linkage,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-avoid-c-style-cast,
-modernize-avoid-setjmp-longjmp,
-modernize-avoid-variadic-functions,
-modernize-deprecated-ios-base-aliases,
-modernize-loop-convert,
-modernize-macro-to-enum,
-modernize-min-max-use-initializer-list,
-modernize-raw-string-literal,
-modernize-redundant-void-arg,
-modernize-replace-auto-ptr,
-modernize-replace-disallow-copy-and-assign-macro,
-modernize-replace-random-shuffle,
-modernize-return-braced-init-list,
-modernize-shrink-to-fit,
-modernize-use-bool-literals,
-modernize-use-default-member-init,
-modernize-use-integer-sign-comparison,
-modernize-use-noexcept,
-modernize-use-nullptr,
-modernize-use-std-format,
-modernize-use-std-print,
-modernize-use-trailing-return-type,
-modernize-use-transparent-functors,
-modernize-use-uncaught-exceptions,
performance-*,
-performance-avoid-endl,
-performance-enum-size,
-performance-inefficient-algorithm,
-performance-inefficient-string-concatenation,
-performance-no-int-to-ptr,
-performance-noexcept-destructor,
-performance-noexcept-move-constructor,
-performance-noexcept-swap,
-performance-type-promotion-in-math-fn,
-performance-unnecessary-copy-initialization,
-performance-unnecessary-value-param,
readability-*,
-readability-avoid-const-params-in-decls,
-readability-avoid-unconditional-preprocessor-if,
-readability-container-data-pointer,
-readability-delete-null-pointer,
-readability-function-cognitive-complexity,
-readability-function-size,
-readability-identifier-length,
-readability-inconsistent-declaration-parameter-name,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-misplaced-array-index,
-readability-named-parameter,
-readability-operators-representation,
-readability-qualified-auto,
-readability-redundant-access-specifiers,
-readability-redundant-control-flow,
-readability-redundant-function-ptr-dereference,
-readability-redundant-preprocessor,
-readability-redundant-smartptr-get,
-readability-redundant-string-cstr,
-readability-simplify-subscript-expr,
-readability-static-accessed-through-instance,
-readability-string-compare,
-readability-uniqueptr-delete-release,
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
-readability-use-concise-preprocessor-directives
"
# ---
# bugprone-narrowing-conversions, # this will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs
# bugprone-narrowing-conversions, # This will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs
# misc-override-with-different-visibility, # Will be addressed in a future PR, but for now it generates too many warnings
# readability-inconsistent-declaration-parameter-name, # In this codebase this check will break a lot of arg names
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
# ---
@@ -162,7 +143,7 @@ CheckOptions:
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/uuid/uuid_hash.hpp;boost/beast/core/flat_buffer\\.hpp;boost/beast/http/field\\.hpp;boost/beast/http/dynamic_body\\.hpp;boost/beast/http/message\\.hpp;boost/beast/http/read\\.hpp;boost/beast/http/write\\.hpp;openssl/obj_mac\\.h"
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/.*;openssl/obj_mac\\.h"
readability-braces-around-statements.ShortStatementLines: 2
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE

View File

@@ -36,9 +36,7 @@ overrides:
- /'[^']*'/g # single-quoted strings
- /`[^`]*`/g # backtick strings
suggestWords:
- xprl->xrpl
- xprld->xrpld # cspell: disable-line not sure what this problem is....
- unsynched->unsynced # cspell: disable-line not sure what this problem is....
- unsynched->unsynced
- synched->synced
- synch->sync
words:
@@ -60,6 +58,7 @@ words:
- autobridging
- bimap
- bindir
- blindings
- bookdir
- Bougalis
- Britto
@@ -95,6 +94,7 @@ words:
- daria
- dcmake
- dearmor
- decryptor
- dedented
- deleteme
- demultiplexer
@@ -106,6 +106,7 @@ words:
- distro
- doxyfile
- dxrpl
- elgamal
- enabled
- enablerepo
- endmacro
@@ -119,6 +120,7 @@ words:
- fmtdur
- fsanitize
- funclets
- Gamal
- gcov
- gcovr
- ghead
@@ -216,6 +218,7 @@ words:
- partitioner
- paychan
- paychans
- Pedersen
- permdex
- perminute
- permissioned
@@ -239,6 +242,10 @@ words:
- Raphson
- rcflags
- replayer
- rerandomize
- rerandomization
- rerandomized
- rerandomizes
- rerere
- retriable
- RIPD
@@ -255,6 +262,7 @@ words:
- sahyadri
- Satoshi
- scons
- Schnorr
- secp
- sendq
- seqit
@@ -285,6 +293,7 @@ words:
- stvar
- stvector
- stxchainattestations
- summands
- superpeer
- superpeers
- takergets
@@ -301,6 +310,7 @@ words:
- txs
- ubsan
- UBSAN
- ufdio
- umant
- unacquired
- unambiguity

View File

@@ -48,6 +48,12 @@ endfunction()
function(add_module parent name)
endfunction()
function(verify_target_headers target headers_dir)
endfunction()
function(_verify_add_headers target dir)
endfunction()
function(setup_protocol_autogen)
endfunction()
@@ -96,3 +102,6 @@ function(verbose_find_path variable name)
${ARGN}
)
endfunction()
function(patch_nix_binary target)
endfunction()

View File

@@ -9,7 +9,7 @@ inputs:
remote_url:
description: "The URL of the Conan endpoint to use."
required: false
default: https://conan.ripplex.io
default: https://conan.xrplf.org/repository/conan/
runs:
using: composite

View File

@@ -1,9 +1,3 @@
Loop: test.jtx test.toplevel
test.toplevel > test.jtx
Loop: test.jtx test.unit_test
test.unit_test ~= test.jtx
Loop: xrpld.app xrpld.overlay
xrpld.app > xrpld.overlay

View File

@@ -83,7 +83,6 @@ test.conditions > xrpl.basics
test.conditions > xrpl.conditions
test.consensus > test.csf
test.consensus > test.jtx
test.consensus > test.toplevel
test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app
@@ -106,9 +105,9 @@ test.csf > xrpl.basics
test.csf > xrpld.consensus
test.csf > xrpl.json
test.csf > xrpl.ledger
test.csf > xrpl.protocol
test.json > test.jtx
test.json > xrpl.json
test.jtx > test.unit_test
test.jtx > xrpl.basics
test.jtx > xrpl.config
test.jtx > xrpl.core
@@ -195,8 +194,6 @@ test.shamap > xrpl.config
test.shamap > xrpl.nodestore
test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
test.toplevel > test.csf
test.toplevel > xrpl.json
test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
@@ -219,11 +216,14 @@ xrpl.core > xrpl.json
xrpl.core > xrpl.protocol
xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.json
xrpl.ledger > xrpl.nodestore
xrpl.ledger > xrpl.protocol
xrpl.ledger > xrpl.shamap
xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.config
xrpl.nodestore > xrpl.json
xrpl.nodestore > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
@@ -241,7 +241,6 @@ xrpl.server > xrpl.json
xrpl.server > xrpl.protocol
xrpl.server > xrpl.rdb
xrpl.server > xrpl.resource
xrpl.server > xrpl.shamap
xrpl.shamap > xrpl.basics
xrpl.shamap > xrpl.nodestore
xrpl.shamap > xrpl.protocol
@@ -296,8 +295,10 @@ xrpld.peerfinder > xrpl.rdb
xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.config
xrpld.perflog > xrpl.core
xrpld.perflog > xrpld.app
xrpld.perflog > xrpld.rpc
xrpld.perflog > xrpl.json
xrpld.perflog > xrpl.nodestore
xrpld.perflog > xrpl.protocol
xrpld.rpc > xrpl.basics
xrpld.rpc > xrpl.config
@@ -315,5 +316,6 @@ xrpld.rpc > xrpl.shamap
xrpld.rpc > xrpl.tx
xrpld.shamap > xrpl.basics
xrpld.shamap > xrpld.core
xrpld.shamap > xrpl.nodestore
xrpld.shamap > xrpl.protocol
xrpld.shamap > xrpl.shamap

View File

@@ -1,5 +1,5 @@
{
"image_tag": "sha-fe4c8ae",
"image_tag": "sha-e29b523",
"configs": {
"ubuntu": [
{

View File

@@ -1,6 +1,6 @@
{
"platform": "macos/arm64",
"runner": ["self-hosted", "macOS", "ARM64", "mac-runner-m1"],
"runner": ["self-hosted", "macOS", "ARM64", "macos-26-apple-clang-21"],
"configs": [
{
"build_type": "Release",

View File

@@ -1,6 +1,6 @@
{
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "devbox"],
"runner": ["self-hosted", "Windows", "dev-box-windows-2026"],
"configs": [
{ "build_type": "Release" },
{

View File

@@ -70,6 +70,7 @@ jobs:
.github/workflows/reusable-upload-recipe.yml
.clang-tidy
.codecov.yml
bin/check-tools.sh
cfg/**
cmake/**
conan/**
@@ -121,7 +122,6 @@ jobs:
issues: write
contents: read
with:
check_only_changed: true
create_issue_on_failure: false
build-test:
@@ -153,8 +153,8 @@ jobs:
if: ${{ github.repository == 'XRPLF/rippled' && needs.should-run.outputs.go == 'true' && github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release') }}
uses: ./.github/workflows/reusable-upload-recipe.yml
secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
notify-clio:
needs: upload-recipe

View File

@@ -20,8 +20,8 @@ jobs:
if: ${{ github.repository == 'XRPLF/rippled' }}
uses: ./.github/workflows/reusable-upload-recipe.yml
secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
build-test:
if: ${{ github.repository == 'XRPLF/rippled' }}

View File

@@ -27,6 +27,7 @@ on:
- ".github/workflows/reusable-upload-recipe.yml"
- ".clang-tidy"
- ".codecov.yml"
- "bin/check-tools.sh"
- "cfg/**"
- "cmake/**"
- "conan/**"
@@ -71,7 +72,6 @@ jobs:
issues: write
contents: read
with:
check_only_changed: false
create_issue_on_failure: ${{ github.event_name == 'schedule' }}
build-test:
@@ -97,8 +97,8 @@ jobs:
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
uses: ./.github/workflows/reusable-upload-recipe.yml
secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
package:
needs: build-test

View File

@@ -14,7 +14,7 @@ on:
jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@e06d4138c9ec8dceeb7c818645faa38087ea9e3d
uses: XRPLF/actions/.github/workflows/pre-commit.yml@1bde119a1ab71305ba5d3716e7a82cea1c7bdede
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

@@ -41,13 +41,13 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: false

View File

@@ -82,7 +82,7 @@ jobs:
name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 180 }}
env:
# Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -113,7 +113,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: ${{ inputs.ccache_enabled }}
@@ -163,7 +163,7 @@ jobs:
CMAKE_ARGS: ${{ inputs.cmake_args }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-G '${{ runner.os == 'Windows' && 'Visual Studio 18 2026' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
@@ -229,21 +229,6 @@ jobs:
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
# This step is needed to allow running in non-Nix environments
- name: Patch binary to use default loader and remove rpath (Linux)
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
run: |
loader="$(/tmp/loader-path.sh)"
patchelf --set-interpreter "${loader}" --remove-rpath "${{ env.BUILD_DIR }}/xrpld"
# We're only running aarch64 Linux builds in Ubuntu-based images, so this is kept simple
- name: Install libatomic (Linux aarch64)
if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }}
run: |
apt update --yes
apt install -y --no-install-recommends \
libatomic1
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
run: |

View File

@@ -3,10 +3,6 @@ name: Run clang-tidy on files
on:
workflow_call:
inputs:
check_only_changed:
description: "Check only changed files in PR. If false, checks all files in the repository."
type: boolean
default: false
create_issue_on_failure:
description: "Whether to create an issue if the check failed"
type: boolean
@@ -29,17 +25,16 @@ env:
jobs:
determine-files:
if: ${{ inputs.check_only_changed }}
permissions:
contents: read
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@c7045074aafe9fb92fa537aa4446f81fbfc17e8b
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@d041ac9f1fa9f07a4ba335eb4c1c82233fb3fef6
run-clang-tidy:
name: Run clang tidy
needs: [determine-files]
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fe4c8ae"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-e29b523"
permissions:
contents: read
issues: write
@@ -48,7 +43,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: false
@@ -84,6 +79,7 @@ jobs:
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
-Dverify_headers=ON \
..
# clang-tidy needs headers generated from proto files
@@ -96,15 +92,15 @@ jobs:
id: run_clang_tidy
continue-on-error: true
env:
TARGETS: ${{ (needs.determine-files.outputs.clang_tidy_config_changed != 'true' && inputs.check_only_changed) && needs.determine-files.outputs.cpp_changed_files || 'src tests' }}
TARGETS: ${{ needs.determine-files.outputs.need_full_run != 'true' && needs.determine-files.outputs.cpp_changed_files || 'include src tests' }}
run: |
set -o pipefail
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
- name: Print errors
- name: Print filtered clang-tidy errors
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
sed '/error\||/!d' "${OUTPUT_FILE}"
bin/filter-clang-tidy.py "${OUTPUT_FILE}"
- name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
@@ -148,12 +144,12 @@ jobs:
\`\`\`
EOF
- name: Append clang-tidy output to issue body (filter for errors and warnings)
- name: Append filtered clang-tidy output to issue body
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >"${FILTERED_OUTPUT_FILE}" || true
# Filter to the unique errors with their source context.
bin/filter-clang-tidy.py "${OUTPUT_FILE}" >"${FILTERED_OUTPUT_FILE}" || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s "${FILTERED_OUTPUT_FILE}" ]; then

View File

@@ -30,7 +30,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"
@@ -39,23 +39,8 @@ jobs:
working-directory: .github/scripts/strategy-matrix
run: ./generate.py --packaging >>"${GITHUB_OUTPUT}"
generate-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
sparse-checkout: |
.github/actions/generate-version
src/libxrpl/protocol/BuildInfo.cpp
- name: Generate version
id: version
uses: ./.github/actions/generate-version
package:
needs: [generate-matrix, generate-version]
needs: [generate-matrix]
if: ${{ github.event.repository.visibility == 'public' }}
strategy:
fail-fast: false
@@ -82,14 +67,13 @@ jobs:
- name: Build package
env:
PKG_VERSION: ${{ needs.generate-version.outputs.version }}
PKG_RELEASE: ${{ inputs.pkg_release }}
run: ./package/build_pkg.sh
- name: Upload package artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.artifact_name }}-pkg-${{ needs.generate-version.outputs.version }}
name: ${{ matrix.artifact_name }}-pkg
path: |
${{ env.BUILD_DIR }}/debbuild/*.deb
${{ env.BUILD_DIR }}/debbuild/*.ddeb

View File

@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"

View File

@@ -14,7 +14,7 @@ on:
description: "The URL of the Conan endpoint to use."
required: false
type: string
default: https://conan.ripplex.io
default: https://conan.xrplf.org/repository/conan/
secrets:
remote_username:
@@ -40,7 +40,11 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
env:
REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -56,15 +60,9 @@ jobs:
remote_url: ${{ inputs.remote_url }}
- name: Log into Conan remote
env:
REMOTE_NAME: ${{ inputs.remote_name }}
REMOTE_USERNAME: ${{ secrets.remote_username }}
REMOTE_PASSWORD: ${{ secrets.remote_password }}
run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}"
run: conan remote login "${REMOTE_NAME}" "${CONAN_LOGIN_USERNAME_XRPLF}" --password "${CONAN_PASSWORD_XRPLF}"
- name: Upload Conan recipe (version)
env:
REMOTE_NAME: ${{ inputs.remote_name }}
run: |
conan export . --version=${{ steps.version.outputs.version }}
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
@@ -73,8 +71,6 @@ jobs:
# 'develop' branch, see on-trigger.yml.
- name: Upload Conan recipe (develop)
if: ${{ github.event_name == 'push' }}
env:
REMOTE_NAME: ${{ inputs.remote_name }}
run: |
conan export . --version=develop
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
@@ -83,8 +79,6 @@ jobs:
# one of the 'release' branches, see on-pr.yml.
- name: Upload Conan recipe (rc)
if: ${{ github.event_name == 'pull_request' }}
env:
REMOTE_NAME: ${{ inputs.remote_name }}
run: |
conan export . --version=rc
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
@@ -93,8 +87,6 @@ jobs:
# release, see on-tag.yml.
- name: Upload Conan recipe (release)
if: ${{ startsWith(github.ref, 'refs/tags/') }}
env:
REMOTE_NAME: ${{ inputs.remote_name }}
run: |
conan export . --version=release
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release

View File

@@ -34,7 +34,7 @@ on:
env:
CONAN_REMOTE_NAME: xrplf
CONAN_REMOTE_URL: https://conan.ripplex.io
CONAN_REMOTE_URL: https://conan.xrplf.org/repository/conan/
NPROC_SUBTRACT: 2
concurrency:
@@ -68,7 +68,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: false
@@ -108,10 +108,12 @@ jobs:
- name: Log into Conan remote
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.NEXUS_REMOTE_USERNAME }}" --password "${{ secrets.NEXUS_REMOTE_PASSWORD }}"
- name: Upload Conan packages
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
env:
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.NEXUS_REMOTE_USERNAME }}
CONAN_PASSWORD_XRPLF: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}

View File

@@ -15,6 +15,7 @@ repos:
hooks:
- id: check-added-large-files
args: [--maxkb=400, --enforce-all]
- id: check-executables-have-shebangs
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
@@ -27,30 +28,37 @@ repos:
entry: ./bin/pre-commit/clang_tidy_check.py
language: python
types_or: [c++, c]
exclude: ^include/xrpl/protocol_autogen
pass_filenames: false # script determines the staged files itself
# .ipp fragments are included by their owning header rather than compiled
# as standalone translation units, so they have no compile_commands.json
# entry to lint (verify_headers checks them transitively).
exclude: '^include/xrpl/protocol_autogen|\.ipp$'
- id: fix-include-style
name: fix include style
entry: ./bin/pre-commit/fix_include_style.py
language: python
types_or: [c++, c]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- id: fix-pragma-once
name: fix missing '#pragma once' declarations in header files
language: python
entry: ./bin/pre-commit/fix_pragma_once.py
files: \.(h|hpp)$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
hooks:
- id: clang-format
args: [--style=file]
"types_or": [c++, c, proto]
types_or: [c++, c, proto]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: faadd6a9d852369ca94f4d15b2404c967ba8cb01 # frozen: 0.27.6
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7
hooks:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
rev: 39e2973981e6d2f9b6c543b0086a2d2393abdc89 # frozen: v3.9.4
hooks:
- id: prettier
args: [--end-of-line=auto]
@@ -80,22 +88,21 @@ repos:
files: \.md$
- repo: https://github.com/streetsidesoftware/cspell-cli
rev: 4643f154907327ee0a2c7038f0296e0dd77d9776 # frozen: v10.0.0
rev: ea11f9efc0bec520073405bc30552da887ba71bc # frozen: v10.0.1
hooks:
- id: cspell # Spell check changed files
- id: cspell
name: check changed files spelling
exclude: |
(?x)^(
.config/cspell.config.yaml|
\.cspell\.config\.yaml|
include/xrpl/protocol_autogen/(transactions|ledger_entries)/.*
)$
- id: cspell # Spell check the commit message
- id: cspell
name: check commit message spelling
args:
- --no-must-find-files
- --no-progress
- --no-summary
- --files
- .git/COMMIT_EDITMSG
stages: [commit-msg]
- repo: local

View File

@@ -25,7 +25,7 @@ You can verify that the required tools are installed and runnable with:
| ----------- | --------------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| Apple Clang | 21 |
| MSVC | 19.44[^windows] |
## Operating Systems
@@ -101,7 +101,7 @@ More information on customizing Conan can be found in the [Advanced Conan config
Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
```bash
conan remote add --index 0 --force xrplf https://conan.ripplex.io
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
```
### Set Up Ccache
@@ -317,21 +317,41 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
## Options
| Option | Default Value | Description |
| ---------- | ------------- | -------------------------------------------------------------- |
| `assert` | OFF | Force enabling assertions. |
| `coverage` | OFF | Prepare the coverage report. |
| `tests` | OFF | Build tests. |
| `unity` | OFF | Configure a unity build. |
| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. |
| `werr` | OFF | Treat compilation warnings as errors |
| `wextra` | OFF | Enable additional compilation warnings |
| Option | Default Value | Description |
| ---------------- | ------------- | ----------------------------------------------------------------------------- |
| `assert` | OFF | Force enabling assertions. |
| `coverage` | OFF | Prepare the coverage report. |
| `tests` | OFF | Build tests. |
| `unity` | OFF | Configure a unity build. |
| `verify_headers` | ON | Make the `verify-headers` target available to compile each header on its own. |
| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. |
| `werr` | OFF | Treat compilation warnings as errors |
| `wextra` | OFF | Enable additional compilation warnings |
[Unity builds][unity-build] may be faster for the first build (at the cost of much more
memory) since they concatenate sources into fewer translation units. Non-unity
builds may be faster for incremental builds, and can be helpful for detecting
`#include` omissions.
### Verifying headers
The regular build only compiles `.cpp` files, so a header is only ever checked
through whatever translation unit happens to include it. A header that forgets
an `#include` is not caught as long as every `.cpp` that uses it includes its
missing dependency first. The `verify_headers` option (ON by default) adds a
`verify-headers` target that compiles every header on its own, which fails if a
header is not self-contained:
```bash
cmake --build . --target verify-headers
```
The per-header objects are excluded from the `all` target, so a normal build
never compiles them; they are built only through `verify-headers`. The generated
translation units do appear in `compile_commands.json`, so clang-tidy (and
clangd and IDEs) can lint each header on its own. Pass `-Dverify_headers=OFF` to
omit them entirely.
## Troubleshooting
### Conan

View File

@@ -57,6 +57,8 @@ if(target)
)
endif()
include(PatchNixBinary)
include(XrplSanity)
include(XrplVersion)
include(XrplSettings)
@@ -88,6 +90,7 @@ find_package(ed25519 REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
find_package(mpt-crypto REQUIRED)
find_package(nudb REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
@@ -100,6 +103,7 @@ target_link_libraries(
INTERFACE
ed25519::ed25519
lz4::lz4
mpt-crypto::mpt-crypto
OpenSSL::Crypto
OpenSSL::SSL
secp256k1::secp256k1

View File

@@ -90,16 +90,19 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check perl
check pkg-config
check vim
check zip
# These tools are present in our Linux CI images and in local development
# setups, but not in the macOS CI environment. So check them everywhere
# except when running in CI on macOS.
if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then
check clang-format
check dot
check doxygen
check gcovr
check gh
check git-cliff
check git-lfs
check gpg
# pre-commit, or its alternative implementation prek
check pre-commit sh -c 'pre-commit --version || prek --version'

102
bin/filter-clang-tidy.py Executable file
View File

@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""
Reduce run-clang-tidy output to its unique errors.
It does two things:
1. Filters the raw output down to diagnostics and their source-context lines
(the indented " 103 | ..." / " | ^" lines clang-tidy prints),
matching the "path:line:col: error:" diagnostic shape.
2. Deduplicates. The same diagnostic in a header is reported once per
translation unit that includes it, so identical error blocks are collapsed
to their first occurrence.
An "error block" is an "error:" line together with the indented context lines
and any "note:" lines that follow it (up to the next "error:" line). Blocks are
compared as a whole, so an error stays attached to its own context, and
first-occurrence order is preserved.
The deduplicated output goes to stdout; a summary of unique error counts per
check is printed to stderr.
Usage:
bin/filter-clang-tidy.py [INPUT_FILE] # read from file, or
run-clang-tidy ... | bin/filter-clang-tidy.py # read from stdin
"""
import re
import sys
from collections import Counter
# A clang-tidy diagnostic line looks like "path:line:col: error: msg [check]".
# Matching on that shape (rather than a loose "error" substring) avoids treating
# progress lines whose paths contain "error" as diagnostics, e.g.
# [284/850][0.7s] /nix/.../clang-tidy ... src/.../error.cpp
DIAG_RE = re.compile(r":\d+:\d+: (?:error|warning|note):")
ERROR_RE = re.compile(r":\d+:\d+: error:")
CHECK_RE = re.compile(r" error: .*\[([^\],]+)")
def filter_and_dedup(lines: list[str]) -> list[str]:
"""Keep diagnostics with their context, then drop duplicate error blocks."""
blocks: list[str] = []
seen: set[str] = set()
current: list[str] = []
def flush() -> None:
if not current:
return
block = "".join(current)
if block not in seen:
seen.add(block)
blocks.append(block)
for line in lines:
# Keep only diagnostics and their indented source-context lines; drop
# progress/status output and blank lines.
if not (DIAG_RE.search(line) or line[:1] in (" ", "\t")):
continue
# An "error:" line starts a new block; its context and any following
# "note:" lines (and their context) belong to it.
if ERROR_RE.search(line):
flush()
current = []
current.append(line)
flush()
return blocks
def summarize(blocks: list[str]) -> Counter[str]:
"""Count unique errors per check name (e.g. "bugprone-branch-clone")."""
counts: Counter[str] = Counter()
for block in blocks:
# The error line is the first line of the block.
match = CHECK_RE.search(block.splitlines()[0])
if match:
counts[match.group(1)] += 1
return counts
def main() -> int:
if len(sys.argv) > 1 and sys.argv[1] != "-":
with open(sys.argv[1], encoding="utf-8") as f:
lines = f.readlines()
else:
lines = sys.stdin.readlines()
blocks = filter_and_dedup(lines)
# Blank line between blocks so distinct errors are easy to tell apart.
sys.stdout.write("\n".join(blocks))
print("\nUnique errors per check:", file=sys.stderr)
for check, count in summarize(blocks).most_common():
print(f"{count:>4} {check}", file=sys.stderr)
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,24 +1,27 @@
#!/usr/bin/env python3
"""Pre-commit hook that runs clang-tidy on changed files using run-clang-tidy."""
"""Pre-commit hook that runs clang-tidy on changed files using run-clang-tidy.
The set of files is chosen by pre-commit (see .pre-commit-config.yaml), which
filters to C/C++ sources and excludes `.ipp` fragments. Headers are linted
directly: the `verify_headers` build option (ON by default) compiles every
`.h`/`.hpp` on its own, so each header is the main file of its own
compile_commands.json entry and run-clang-tidy can analyse it just like a
`.cpp`.
"""
from __future__ import annotations
import json
import os
import re
import shutil
import subprocess
import sys
from collections import defaultdict
from pathlib import Path
HEADER_EXTENSIONS = {".h", ".hpp", ".ipp"}
SOURCE_EXTENSIONS = {".cpp"}
INCLUDE_RE = re.compile(r"^\s*#\s*include\s*[<\"]([^>\"]+)[>\"]")
CLANG_TIDY_VERSION = 22
def find_run_clang_tidy() -> str | None:
for candidate in ("run-clang-tidy-21", "run-clang-tidy"):
for candidate in (f"run-clang-tidy-{CLANG_TIDY_VERSION}", "run-clang-tidy"):
if path := shutil.which(candidate):
return path
return None
@@ -32,142 +35,23 @@ def find_build_dir(repo_root: Path) -> Path | None:
return None
def build_include_graph(build_dir: Path, repo_root: Path) -> tuple[dict, set]:
"""
Scan all files reachable from compile_commands.json and build an inverted include graph.
Returns:
inverted: header_path -> set of files that include it
source_files: set of all TU paths from compile_commands.json
"""
with open(build_dir / "compile_commands.json") as f:
db = json.load(f)
source_files = {Path(e["file"]).resolve() for e in db}
include_roots = [repo_root / "include", repo_root / "src"]
inverted: dict[Path, set[Path]] = defaultdict(set)
to_scan: set[Path] = set(source_files)
scanned: set[Path] = set()
while to_scan:
file = to_scan.pop()
if file in scanned or not file.exists():
continue
scanned.add(file)
content = file.read_text()
for line in content.splitlines():
m = INCLUDE_RE.match(line)
if not m:
continue
for root in include_roots:
candidate = (root / m.group(1)).resolve()
if candidate.exists():
inverted[candidate].add(file)
if candidate not in scanned:
to_scan.add(candidate)
break
return inverted, source_files
def find_tus_for_headers(
headers: list[Path],
inverted: dict[Path, set[Path]],
source_files: set[Path],
) -> set[Path]:
"""
For each header, pick one TU that transitively includes it.
Prefers a TU whose stem matches the header's stem, otherwise picks the first found.
"""
result: set[Path] = set()
for header in headers:
preferred: Path | None = None
visited: set[Path] = {header}
stack: list[Path] = [header]
while stack:
h = stack.pop()
for inc in inverted.get(h, ()):
if inc in source_files:
if inc.stem == header.stem:
preferred = inc
break
if preferred is None:
preferred = inc
if inc not in visited:
visited.add(inc)
stack.append(inc)
if preferred is not None and preferred.stem == header.stem:
break
if preferred is not None:
result.add(preferred)
return result
def resolve_files(
input_files: list[str], build_dir: Path, repo_root: Path
) -> list[str]:
"""
Split input into source files and headers. Source files are passed through;
headers are resolved to the TUs that transitively include them.
"""
sources: list[Path] = []
headers: list[Path] = []
for f in input_files:
p = Path(f).resolve()
if p.suffix in SOURCE_EXTENSIONS:
sources.append(p)
elif p.suffix in HEADER_EXTENSIONS:
headers.append(p)
if not headers:
return [str(p) for p in sources]
print(
f"Resolving {len(headers)} header(s) to compilation units...", file=sys.stderr
)
inverted, source_files = build_include_graph(build_dir, repo_root)
tus = find_tus_for_headers(headers, inverted, source_files)
if not tus:
print(
"Warning: no compilation units found that include the modified headers; "
"skipping clang-tidy for headers.",
file=sys.stderr,
)
return sorted({str(p) for p in (*sources, *tus)})
def staged_files(repo_root: Path) -> list[str]:
result = subprocess.run(
["git", "diff", "--staged", "--name-only", "--diff-filter=d"],
capture_output=True,
text=True,
cwd=repo_root,
)
if result.returncode != 0:
print(
"clang-tidy check failed: 'git diff --staged' command failed.",
file=sys.stderr,
)
if result.stderr:
print(result.stderr, file=sys.stderr)
sys.exit(result.returncode or 1)
return [str(repo_root / p) for p in result.stdout.splitlines() if p]
def main():
if not os.environ.get("TIDY"):
return 0
files = sys.argv[1:]
if not files:
return 0
run_clang_tidy = find_run_clang_tidy()
if not run_clang_tidy:
print(
f"clang-tidy check failed: TIDY is enabled but neither "
f"'run-clang-tidy-{CLANG_TIDY_VERSION}' nor 'run-clang-tidy' was found in PATH.",
file=sys.stderr,
)
return 1
repo_root = Path(
subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
@@ -175,19 +59,6 @@ def main():
text=True,
).strip()
)
files = staged_files(repo_root)
if not files:
return 0
run_clang_tidy = find_run_clang_tidy()
if not run_clang_tidy:
print(
"clang-tidy check failed: TIDY is enabled but neither "
"'run-clang-tidy-21' nor 'run-clang-tidy' was found in PATH.",
file=sys.stderr,
)
return 1
build_dir = find_build_dir(repo_root)
if not build_dir:
print(
@@ -197,13 +68,9 @@ def main():
)
return 1
tidy_files = resolve_files(files, build_dir, repo_root)
if not tidy_files:
return 0
result = subprocess.run(
[run_clang_tidy, "-quiet", "-p", str(build_dir), "-fix", "-allow-no-checks"]
+ tidy_files
+ files
)
return result.returncode

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env python3
"""
Adds "#pragma once" to the top of header files that don't already have it.
Usage: ./bin/pre-commit/fix_pragma_once.py <file1> <file2> ...
"""
import sys
from pathlib import Path
PRAGMA_ONCE = "#pragma once\n\n"
def fix_pragma_once(path: Path) -> bool:
original = path.read_text(encoding="utf-8")
if PRAGMA_ONCE not in original:
path.write_text(PRAGMA_ONCE + original, encoding="utf-8")
return False
return True
def main() -> int:
files = [Path(f) for f in sys.argv[1:]]
success = True
for path in files:
success &= fix_pragma_once(path)
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())

View File

@@ -56,3 +56,16 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
else()
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
# --------------------------------------------------------------------
# Sanitizers
# --------------------------------------------------------------------
# SANITIZERS is injected by the Conan toolchain when a sanitizer build is
# requested (see conan/profiles/sanitizers). The flags are applied to the
# 'common' target in XrplSanitizers; this flag lets other modules know a
# sanitizer build is active without depending on that module.
if(DEFINED SANITIZERS)
set(SANITIZERS_ENABLED TRUE)
else()
set(SANITIZERS_ENABLED FALSE)
endif()

View File

@@ -0,0 +1,53 @@
#[===================================================================[
Patch executables to run in non-Nix environments.
The Nix-based CI image links binaries against an ELF interpreter (loader)
that lives in the Nix store, so the resulting binaries don't run elsewhere
(including once installed from the .deb package). `patch_nix_binary` adds a
POST_BUILD step that resets the interpreter to the system default loader and
drops the rpath.
This is only active inside the Nix-based image, detected by the presence of
/tmp/loader-path.sh (shipped by that image, resolves the default loader). It
is skipped for sanitizer builds, whose runtime libraries are resolved through
the rpath. Everywhere else `patch_nix_binary` is a no-op.
#]===================================================================]
include_guard(GLOBAL)
include(CompilationEnv)
# Provided by the Nix-based CI image; prints the system default ELF loader path.
set(_loader_path_script "/tmp/loader-path.sh")
if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}")
execute_process(
COMMAND "${_loader_path_script}"
OUTPUT_VARIABLE DEFAULT_LOADER_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
find_program(PATCHELF_COMMAND patchelf REQUIRED)
set(PATCH_NIX_BINARIES TRUE)
message(
STATUS
"Binaries will be patched to use loader '${DEFAULT_LOADER_PATH}'"
)
else()
set(PATCH_NIX_BINARIES FALSE)
endif()
function(patch_nix_binary target)
if(NOT PATCH_NIX_BINARIES)
return()
endif()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${PATCHELF_COMMAND}" --set-interpreter "${DEFAULT_LOADER_PATH}"
--remove-rpath "$<TARGET_FILE:${target}>"
COMMENT "Patching ${target}: set default loader, remove rpath"
VERBATIM
)
endfunction()

View File

@@ -154,6 +154,15 @@ else()
>
)
# On aarch64, libatomic is required for atomic operations. It is not needed on x86_64.
# Linking it statically on Linux
if(is_arm64 AND is_linux)
target_link_options(
common
INTERFACE -Wl,--push-state -Wl,-Bstatic -latomic -Wl,--pop-state
)
endif()
# Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking.
#
# Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in

View File

@@ -247,6 +247,7 @@ target_link_modules(
if(xrpld)
add_executable(xrpld)
patch_nix_binary(xrpld)
if(tests)
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
target_compile_definitions(
@@ -292,4 +293,13 @@ if(xrpld)
PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk
)
endif()
# The xrpld headers are not built with add_module, so verify them against
# the executable's own compile environment.
if(verify_headers)
verify_target_headers(xrpld "${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld")
if(tests)
verify_target_headers(xrpld "${CMAKE_CURRENT_SOURCE_DIR}/src/test")
endif()
endif()
endif()

View File

@@ -28,7 +28,6 @@ endif()
set(package_env
SRC_DIR=${CMAKE_SOURCE_DIR}
BUILD_DIR=${CMAKE_BINARY_DIR}
PKG_VERSION=${xrpld_version}
PKG_RELEASE=${pkg_release}
)

View File

@@ -14,11 +14,9 @@
include_guard(GLOBAL)
include(CompilationEnv)
if(NOT DEFINED SANITIZERS)
set(SANITIZERS_ENABLED FALSE)
if(NOT SANITIZERS_ENABLED)
return()
endif()
set(SANITIZERS_ENABLED TRUE)
message(STATUS "=== Configuring Sanitizers ===")
message(STATUS " SANITIZERS: ${SANITIZERS}")

View File

@@ -30,6 +30,23 @@ if(tests)
endif()
endif()
# Enabled by default so every header is compiled on its own as the main file of
# its own compile_commands.json entry - this is what lets clang-tidy (and clangd
# and IDEs) analyse a header's own includes directly. The per-header objects are
# EXCLUDE_FROM_ALL (see cmake/verify_headers.cmake) and the aggregate target
# below is not part of `all`, so a normal `cmake --build` never compiles them.
option(
verify_headers
"Compile every header on its own to verify it is self-contained."
ON
)
if(verify_headers)
# Aggregate target that builds every per-module header-verification library
# created by add_module (see cmake/verify_headers.cmake). Build it with:
# cmake --build . --target verify-headers
add_custom_target(verify-headers)
endif()
option(unity "Creates a build using UNITY support in cmake." OFF)
if(unity)
if(NOT is_ci)

View File

@@ -1,4 +1,5 @@
include(isolate_headers)
include(verify_headers)
# Create an OBJECT library target named
#
@@ -37,4 +38,20 @@ function(add_module parent name)
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
PRIVATE
)
# protocol_autogen contains generated headers that are deliberately exempt
# from clang-tidy (see ExcludeHeaderFilterRegex in .clang-tidy), so we do not
# verify them either.
if(
verify_headers
AND NOT "${parent}/${name}" STREQUAL "xrpl/protocol_autogen"
)
verify_target_headers(
${target}
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}"
)
verify_target_headers(
${target}
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
)
endif()
endfunction()

View File

@@ -0,0 +1,84 @@
# Our normal build only ever compiles `.cpp` files, so a header is only ever
# checked through whatever translation unit happens to include it. A header that
# is missing an `#include` is never caught as long as every `.cpp` that uses it
# includes its missing dependency first. To check a header on its own we compile
# it directly as a translation unit.
#
# Compiling the header itself - rather than a `.cpp` wrapper that includes it -
# gives two checks at once:
# * the compiler fails if the header is not self-contained, i.e. it uses a
# declaration that is not available (directly or transitively); and
# * the header is the *main file* of its `compile_commands.json` entry, so
# clang-tidy's misc-include-cleaner analyses (and can --fix) the header's own
# includes - flagging a dependency that is only available transitively, which
# a plain compile cannot catch. A wrapper would be the main file instead, and
# include-cleaner never looks inside the headers a main file includes.
#
# The objects are never linked anywhere; we build them only for these checks.
# Verify that the headers under headers_dir compile on their own, using the
# compile environment of an existing target so each header is compiled exactly as
# that target compiles it. This works for both add_module libraries and the xrpld
# and test binaries: a library's isolated public and private include directories
# and a binary's `-I src` both live in its INCLUDE_DIRECTORIES, and the modules or
# libraries it links live in its LINK_LIBRARIES. We copy those usage requirements
# through generator expressions (rather than linking ${target}, which is
# impossible for an executable), evaluated at generation time so they capture
# requirements the caller adds after this runs. The verify library is created
# once; call this repeatedly to add more header directories.
#
# verify_target_headers(target headers_dir)
function(verify_target_headers target headers_dir)
set(verify ${target}.verify)
if(NOT TARGET ${verify})
add_library(${verify} OBJECT EXCLUDE_FROM_ALL)
# A unity build would concatenate the headers into a single translation
# unit, where a header missing an include could be satisfied by one that
# precedes it in the blob - exactly the bug we want to catch.
set_target_properties(${verify} PROPERTIES UNITY_BUILD OFF)
target_include_directories(
${verify}
PRIVATE $<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>
)
target_compile_definitions(
${verify}
PRIVATE $<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>
)
target_compile_options(
${verify}
PRIVATE $<TARGET_PROPERTY:${target},COMPILE_OPTIONS>
)
target_link_libraries(
${verify}
PRIVATE $<TARGET_PROPERTY:${target},LINK_LIBRARIES>
)
add_dependencies(verify-headers ${verify})
endif()
_verify_add_headers(${verify} "${headers_dir}")
endfunction()
# Add every .h/.hpp under dir to target as a directly-compiled C++ translation
# unit. .ipp files are inline-implementation fragments included by their owning
# header (often after a class declaration), so they are not self-contained on
# their own and are verified transitively when that header is verified.
function(_verify_add_headers target dir)
file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${dir}/*.h" "${dir}/*.hpp")
if(NOT headers)
return()
endif()
# `-xc++` forces the header to be compiled as a C++ translation unit; a lone
# `.h` is otherwise treated as a header to precompile. `#pragma once` is
# harmless (and warns) when the header is the main file, so silence it.
# Compiled on its own, a header legitimately defines constants and static or
# template functions that nothing in this single translation unit uses (they
# exist for the files that include it), so the resulting unused-entity
# warnings are expected and must not fail the build under -Werror.
set_source_files_properties(
${headers}
PROPERTIES
LANGUAGE CXX
COMPILE_OPTIONS
"-xc++;-Wno-pragma-once-outside-header;-Wno-unused-const-variable;-Wno-unused-function"
)
target_sources(${target} PRIVATE ${headers})
endfunction()

View File

@@ -1,43 +1,44 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
"secp256k1/0.7.1#b1f450b7f78a36fff75bb6934a356f3a%1782338841.3729",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1782392413.075713",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1782392402.431897",
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.3#1163d4ddc603907084d08a6a0c6e580f%1782307150.583886",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1782392402.297166",
"mpt-crypto/0.4.0-rc2#a580f2f9ad0e795de696aa62d54fb9af%1782425834.488828",
"lz4/1.10.0#982d9b673900f665a1da109e09c17cab%1782392402.164188",
"libiconv/1.17#9923bc6dc6f106646d6967e0039a5ada%1782392792.775744",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1782392402.420732",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.81.1#5217e6ef0544c42b46f4af35d5e7f649%1782307148.845616",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1782392402.296732",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1782392419.475605",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
],
"build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1782395692.540639",
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#4523e4347b55cd26ae918bd5770cab9a%1778062762.471",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
],
"python_requires": [],
"overrides": {
@@ -57,7 +58,7 @@
"boost/1.91.0"
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
"lz4/1.10.0#982d9b673900f665a1da109e09c17cab"
]
},
"config_requires": []

View File

@@ -14,7 +14,7 @@ export CONAN_HOME="$TEMP_DIR"
# Ensure that the xrplf remote is the first to be consulted, so any recipes we
# patched are used. We also add it there to not created huge diff when the
# official Conan Center Index is updated.
conan remote add --force --index 0 xrplf https://conan.ripplex.io
conan remote add --force --index 0 xrplf https://conan.xrplf.org/repository/conan/
# Delete any existing lockfile.
rm -f conan.lock

View File

@@ -10,16 +10,18 @@
os={{ os }}
arch={{ arch }}
build_type=Debug
compiler={{compiler}}
compiler={{ compiler }}
compiler.version={{ compiler_version }}
compiler.cppstd=23
{% if os == "Windows" %}
compiler.runtime=static
{% else %}
compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
{% endif %}
[conf]
{% if compiler == "gcc" and compiler_version < 13 %}
tools.build:cxxflags+=['-Wno-restrict']
{% endif %}
{# By default, Conan tries to reuse binaries built with different cppstd versions. #}
{# We want to avoid that to improve reproduceability, so we add the cppstd version to the package ID. #}
{# More info: https://docs.conan.io/2/reference/extensions/binary_compatibility.html #}
user.package:cppstd_version=23
tools.info.package_id:confs+=["user.package:cppstd_version"]

View File

@@ -87,15 +87,15 @@ include(default)
{% endif %}
[conf]
tools.build:defines+={{defines}}
tools.build:cxxflags+={{sanitizer_compiler_flags}}
tools.build:sharedlinkflags+={{sanitizer_linker_flags}}
tools.build:exelinkflags+={{sanitizer_linker_flags}}
tools.build:defines+={{ defines }}
tools.build:cxxflags+={{ sanitizer_compiler_flags }}
tools.build:sharedlinkflags+={{ sanitizer_linker_flags }}
tools.build:exelinkflags+={{ sanitizer_linker_flags }}
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
# &: means "apply only to the consumer/root package"
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{sanitizers}}", "SANITIZERS_COMPILER_FLAGS": "{{sanitizer_compiler_flags | join(' ')}}", "SANITIZERS_LINKER_FLAGS": "{{sanitizer_linker_flags | join(' ')}}"}
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{ sanitizers }}", "SANITIZERS_COMPILER_FLAGS": "{{ sanitizer_compiler_flags | join(' ') }}", "SANITIZERS_LINKER_FLAGS": "{{ sanitizer_linker_flags | join(' ') }}"}
[options]
{% if enable_asan %}

View File

@@ -28,11 +28,10 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"grpc/1.78.1",
"grpc/1.81.1",
"libarchive/3.8.7",
"nudb/2.0.9",
"openssl/3.6.2",
"secp256k1/0.7.1",
"openssl/3.6.3",
"soci/4.0.3",
"zlib/1.3.2",
]
@@ -132,13 +131,15 @@ class Xrpl(ConanFile):
def requirements(self):
self.requires("boost/1.91.0", force=True, transitive_headers=True)
self.requires("date/3.0.4", transitive_headers=True)
self.requires("lz4/1.10.0", force=True)
self.requires("protobuf/6.33.5", force=True)
self.requires("sqlite3/3.53.0", force=True)
if self.options.jemalloc:
self.requires("jemalloc/5.3.1")
self.requires("lz4/1.10.0", force=True)
self.requires("mpt-crypto/0.4.0-rc2", transitive_headers=True)
self.requires("protobuf/6.33.5", force=True)
if self.options.rocksdb:
self.requires("rocksdb/10.5.1")
self.requires("secp256k1/0.7.1", transitive_headers=True)
self.requires("sqlite3/3.53.0", force=True)
self.requires("xxhash/0.8.3", transitive_headers=True)
exports_sources = (
@@ -208,6 +209,7 @@ class Xrpl(ConanFile):
"grpc::grpc++",
"libarchive::libarchive",
"lz4::lz4",
"mpt-crypto::mpt-crypto",
"nudb::nudb",
"openssl::crypto",
"protobuf::libprotobuf",

View File

@@ -288,7 +288,7 @@ components with non-trivial changes are colored green.
validated.
![Sequence diagram](./negativeUNL_highLevel_sequence.png?raw=true "Negative UNL
Changes")
Changes")
## Roads Not Taken

View File

@@ -34,7 +34,7 @@ higher index than the default Conan Center remote, so it is consulted first. You
can do this by running:
```bash
conan remote add --index 0 --force xrplf https://conan.ripplex.io
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
```
Alternatively, you can pull our recipes from the repository and export them locally:

View File

@@ -6,6 +6,7 @@
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>
namespace xrpl {

View File

@@ -1,134 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2024 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_BASICS_CANPROCESS_H_INCLUDED
#define RIPPLE_BASICS_CANPROCESS_H_INCLUDED
#include <functional>
#include <mutex>
#include <set>
/** RAII class to check if an Item is already being processed on another thread,
* as indicated by it's presence in a Collection.
*
* If the Item is not in the Collection, it will be added under lock in the
* ctor, and removed under lock in the dtor. The object will be considered
* "usable" and evaluate to `true`.
*
* If the Item is in the Collection, no changes will be made to the collection,
* and the CanProcess object will be considered "unusable".
*
* It's up to the caller to decide what "usable" and "unusable" mean. (e.g.
* Process or skip a block of code, or set a flag.)
*
* The current use is to avoid lock contention that would be involved in
* processing something associated with the Item.
*
* Examples:
*
* void IncomingLedgers::acquireAsync(LedgerHash const& hash, ...)
* {
* if (CanProcess check{acquiresMutex_, pendingAcquires_, hash})
* {
* acquire(hash, ...);
* }
* }
*
* bool
* NetworkOPsImp::recvValidation(
* std::shared_ptr<STValidation> const& val,
* std::string const& source)
* {
* CanProcess check(
* validationsMutex_, pendingValidations_, val->getLedgerHash());
* BypassAccept bypassAccept =
* check ? BypassAccept::no : BypassAccept::yes;
* handleNewValidation(app_, val, source, bypassAccept, m_journal);
* }
*
*/
class CanProcess
{
public:
template <class Mutex, class Collection, class Item>
CanProcess(Mutex& mtx, Collection& collection, Item const& item)
: cleanup_(insert(mtx, collection, item))
{
}
~CanProcess()
{
if (cleanup_)
cleanup_();
}
explicit
operator bool() const
{
return static_cast<bool>(cleanup_);
}
private:
template <bool useIterator, class Mutex, class Collection, class Item>
std::function<void()>
doInsert(Mutex& mtx, Collection& collection, Item const& item)
{
std::unique_lock<Mutex> lock(mtx);
// TODO: Use structured binding once LLVM 16 is the minimum supported
// version. See also: https://github.com/llvm/llvm-project/issues/48582
// https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
auto const insertResult = collection.insert(item);
auto const it = insertResult.first;
if (!insertResult.second)
return {};
if constexpr (useIterator)
return [&, it]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(it);
};
else
return [&]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(item);
};
}
// Generic insert() function doesn't use iterators because they may get
// invalidated
template <class Mutex, class Collection, class Item>
std::function<void()>
insert(Mutex& mtx, Collection& collection, Item const& item)
{
return doInsert<false>(mtx, collection, item);
}
// Specialize insert() for std::set, which does not invalidate iterators for
// insert and erase
template <class Mutex, class Item>
std::function<void()>
insert(Mutex& mtx, std::set<Item>& collection, Item const& item)
{
return doInsert<true>(mtx, collection, item);
}
// If set, then the item is "usable"
std::function<void()> cleanup_;
};
#endif

View File

@@ -5,6 +5,7 @@
#include <lz4.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <vector>

View File

@@ -2,6 +2,7 @@
#include <chrono>
#include <cmath>
#include <cstddef>
namespace xrpl {
@@ -12,8 +13,8 @@ template <int Window, typename Clock>
class DecayingSample
{
public:
using value_type = typename Clock::duration::rep;
using time_point = typename Clock::time_point;
using value_type = Clock::duration::rep;
using time_point = Clock::time_point;
DecayingSample() = delete;
@@ -93,7 +94,7 @@ template <int HalfLife, class Clock>
class DecayWindow
{
public:
using time_point = typename Clock::time_point;
using time_point = Clock::time_point;
explicit DecayWindow(time_point now) : when_(now)
{

View File

@@ -3,7 +3,9 @@
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <cstddef>
#include <optional>
#include <string>
namespace xrpl {

View File

@@ -1,6 +1,7 @@
#pragma once
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <atomic>
#include <cstddef>
#include <cstdint>
namespace xrpl {

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/beast/utility/Journal.h>
#include <boost/beast/core/string.hpp>
@@ -11,7 +10,9 @@
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
#include <vector>
namespace xrpl {
@@ -206,8 +207,7 @@ private:
#ifndef JLOG
#define JLOG(x) \
if (!(x)) \
{ \
} \
; \
else \
x
#endif

View File

@@ -2,7 +2,9 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
@@ -11,7 +13,9 @@
#include <set>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
namespace xrpl {

View File

@@ -6,6 +6,7 @@
#include <boost/icl/closed_interval.hpp>
#include <boost/icl/interval_set.hpp>
#include <functional>
#include <optional>
#include <string>
#include <vector>

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/net/IPEndpoint.h>
#include <functional>
#include <string>
#include <vector>
namespace xrpl {

View File

@@ -5,6 +5,8 @@
#include <boost/asio/io_context.hpp>
#include <memory>
namespace xrpl {
class ResolverAsio : public Resolver

View File

@@ -3,7 +3,9 @@
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/partitioned_unordered_map.h>
#include <cstddef>
#include <ostream>
#include <string>
namespace xrpl {

View File

@@ -1,5 +1,7 @@
#pragma once
#include <concepts>
#include <cstddef>
#include <memory>
#include <variant>

View File

@@ -15,6 +15,7 @@
#include <cstdint>
#include <cstring>
#include <mutex>
#include <stdexcept>
#include <vector>
#if BOOST_OS_LINUX

View File

@@ -211,15 +211,17 @@ operator<<(Stream& s, Slice const& v)
}
template <class T, std::size_t N>
std::enable_if_t<std::is_same_v<T, char> || std::is_same_v<T, unsigned char>, Slice>
Slice
makeSlice(std::array<T, N> const& a)
requires(std::is_same_v<T, char> || std::is_same_v<T, unsigned char>)
{
return Slice(a.data(), a.size());
}
template <class T, class Alloc>
std::enable_if_t<std::is_same_v<T, char> || std::is_same_v<T, unsigned char>, Slice>
Slice
makeSlice(std::vector<T, Alloc> const& v)
requires(std::is_same_v<T, char> || std::is_same_v<T, unsigned char>)
{
return Slice(v.data(), v.size());
}

View File

@@ -1,18 +1,19 @@
#pragma once
#include <xrpl/basics/Blob.h>
#include <xrpl/basics/strHex.h>
#include <boost/format.hpp>
#include <boost/utility/string_view.hpp>
#include <array>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
namespace xrpl {

View File

@@ -1,22 +1,46 @@
#pragma once
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/SharedWeakCachePointer.ipp>
#include <xrpl/basics/SharedWeakCachePointer.h>
#include <xrpl/basics/SharedWeakCachePointer.ipp> // IWYU pragma: keep
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/hardened_hash.h>
#include <xrpl/beast/clock/abstract_clock.h>
#include <xrpl/beast/insight/Insight.h>
#include <xrpl/beast/insight/Collector.h>
#include <xrpl/beast/insight/Gauge.h>
#include <xrpl/beast/insight/Hook.h>
#include <xrpl/beast/insight/NullCollector.h>
#include <xrpl/beast/utility/Journal.h>
#include <atomic>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <type_traits>
#include <vector>
namespace xrpl {
namespace detail {
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
// collision when the key already exists (defined in TaggedCache.ipp):
// - ReplaceCached: always replace the cached value with `data`. `data` is
// never written back and may be const.
// - ReplaceClient: keep the cached value and write it back into `data` (the
// client's pointer), which must therefore be writable.
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
// is written back when the cached value is kept, so it must be writable.
struct ReplaceCached;
struct ReplaceClient;
struct ReplaceDynamically;
} // namespace detail
/** Map/cache combination.
This class implements a cache and a map. The cache keeps objects alive
in the map. The map allows multiple code paths that reference objects
@@ -96,6 +120,32 @@ public:
bool
del(key_type const& key, bool valid);
private:
// Selects the `data` parameter type of canonicalizeImpl from the replace
// policy: const for detail::ReplaceCached (never written back), otherwise
// writable.
template <typename Policy>
using CanonicalizeClientPointerType = std::conditional_t<
std::is_same_v<detail::ReplaceCached, Policy>,
SharedPointerType const&,
SharedPointerType&>;
/** Shared implementation of the canonicalize family.
`policy` selects how a collision is resolved when `key` already exists:
detail::ReplaceCached, detail::ReplaceClient or
detail::ReplaceDynamically. For ReplaceDynamically `replaceCallback` is
invoked with the existing strong pointer and returns whether to replace
the cached value with `data`; for the tag policies it is unused.
*/
template <class Policy, class Callback = std::nullptr_t>
bool
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback = nullptr);
public:
/** Replace aliased objects with originals.
@@ -104,19 +154,52 @@ public:
This routine eliminates the duplicate and performs a replacement
on the callers shared pointer if needed.
`replaceCallback` is a callable taking the existing strong pointer and
returning whether to replace the cached value with `data` (true) or to
keep the cached value and write it back into `data` (false). Because the
write-back case mutates `data`, `data` must be writable.
@param key The key corresponding to the object
@param data A shared pointer to the data corresponding to the object.
@param replace Function that decides if cache should be replaced
@param replaceCallback A callable (existing strong pointer -> bool).
@return `true` If the key already existed.
*/
template <class R>
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
template <class Callback>
bool
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback);
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback);
/** Insert/update the canonical entry for `key`, always replacing the
cached value with `data`.
If an entry already exists for `key`, the cached value is unconditionally
replaced with `data`; otherwise `data` is inserted. `data` is never
written back, so it may be const.
@param key The key corresponding to the object.
@param data A shared pointer to the data corresponding to the object.
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
bool
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data);
/** Insert the canonical entry for `key`, keeping any existing cached value.
If an entry already exists for `key`, the cached value is kept and
written back into `data` so the caller ends up with the canonical
object; otherwise `data` is inserted. Because `data` may be overwritten
it must be writable.
@param key The key corresponding to the object.
@param data A shared pointer to the data corresponding to the object;
updated to the canonical value when one already exists.
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
bool
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data);
@@ -129,11 +212,13 @@ public:
*/
template <class ReturnType = bool>
auto
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>;
insert(key_type const& key, T const& value) -> ReturnType
requires(!IsKeyCache);
template <class ReturnType = bool>
auto
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>;
insert(key_type const& key) -> ReturnType
requires IsKeyCache;
// VFALCO NOTE It looks like this returns a copy of the data in
// the output parameter 'data'. This could be expensive.
@@ -262,7 +347,7 @@ private:
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
typename KeyValueCacheType::map_type& partition,
KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);
@@ -271,7 +356,7 @@ private:
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
typename KeyOnlyCacheType::map_type& partition,
KeyOnlyCacheType::map_type& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);

View File

@@ -1,10 +1,35 @@
#pragma once
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Log.h> // IWYU pragma: keep
#include <xrpl/basics/TaggedCache.h>
namespace xrpl {
namespace detail {
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
// collision when the key already exists:
// - ReplaceCached: always replace the cached value with `data`. `data` is
// never written back and may be const.
// - ReplaceClient: keep the cached value and write it back into `data` (the
// client's pointer), which must therefore be writable.
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
// is written back when the cached value is kept, so it must be writable.
struct ReplaceCached
{
};
struct ReplaceClient
{
};
struct ReplaceDynamically
{
};
} // namespace detail
template <
class Key,
class T,
@@ -32,7 +57,10 @@ inline TaggedCache<
beast::insight::Collector::ptr const& collector)
: journal_(journal)
, clock_(clock)
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
, stats_(
name,
[this] { collectMetrics(); },
collector)
, name_(name)
, targetSize_(size)
, targetAge_(expiration)
@@ -300,13 +328,29 @@ template <
class Hash,
class KeyEqual,
class Mutex>
template <class R>
template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback)
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
[[maybe_unused]] Policy policy,
[[maybe_unused]] Callback&& replaceCallback)
{
// Return canonical value, store if needed, refresh in cache
// Return values: true=we had the data already
// `Policy` is one of:
// - detail::ReplaceCached: always replace the cached value with `data`;
// `data` is never written back and may be const.
// - detail::ReplaceClient: keep the cached value and write it back into
// `data` (the client's pointer), which must therefore be writable.
// - detail::ReplaceDynamically: call `replaceCallback` to decide at run
// time; `data` must be writable.
// For the latter two the write-back below requires a mutable `data`, so
// passing a const argument is a compile error.
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key);
@@ -324,13 +368,14 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
Entry& entry = cit->second;
entry.touch(clock_.now());
auto shouldReplace = [&] {
if constexpr (std::is_invocable_r_v<bool, R>)
auto shouldReplaceCached = [&] {
if constexpr (replaceCached)
{
// The reason for this extra complexity is for intrusive
// strong/weak combo getting a strong is relatively expensive
// and not needed for many cases.
return replaceCallback();
return true;
}
else if constexpr (std::is_same_v<Policy, detail::ReplaceClient>)
{
return false;
}
else
{
@@ -340,11 +385,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
if (shouldReplace())
if (shouldReplaceCached())
{
entry.ptr = data;
}
else
else if constexpr (!replaceCached)
{
data = entry.ptr.getStrong();
}
@@ -356,11 +401,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (cachedData)
{
if (shouldReplace())
if (shouldReplaceCached())
{
entry.ptr = data;
}
else
else if constexpr (!replaceCached)
{
entry.ptr.convertToStrong();
data = cachedData;
@@ -376,6 +421,24 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return false;
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback)
{
return canonicalizeImpl(
key, data, detail::ReplaceDynamically{}, std::forward<Callback>(replaceCallback));
}
template <
class Key,
class T,
@@ -389,7 +452,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data)
{
return canonicalize(key, const_cast<SharedPointerType&>(data), []() { return true; });
return canonicalizeImpl(key, data, detail::ReplaceCached{});
}
template <
@@ -405,7 +468,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data)
{
return canonicalize(key, data, []() { return false; });
return canonicalizeImpl(key, data, detail::ReplaceClient{});
}
template <
@@ -440,7 +503,8 @@ template <
template <class ReturnType>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>
insert(key_type const& key, T const& value) -> ReturnType
requires(!IsKeyCache)
{
static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
@@ -470,7 +534,8 @@ template <
template <class ReturnType>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>
insert(key_type const& key) -> ReturnType
requires IsKeyCache
{
std::scoped_lock const lock(mutex_);
clock_type::time_point const now(clock_.now());
@@ -676,7 +741,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
typename KeyValueCacheType::map_type& partition,
KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)
@@ -756,7 +821,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
typename KeyOnlyCacheType::map_type& partition,
KeyOnlyCacheType::map_type& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)

View File

@@ -12,8 +12,9 @@ namespace xrpl {
*/
template <class T>
std::enable_if_t<std::is_arithmetic_v<T>, std::string>
std::string
to_string(T t) // NOLINT(readability-identifier-naming)
requires(std::is_arithmetic_v<T>)
{
return std::to_string(t);
}

View File

@@ -2,12 +2,14 @@
#include <xrpl/basics/hardened_hash.h>
#include <xrpl/basics/partitioned_unordered_map.h>
#include <xrpl/beast/hash/hash_append.h>
#include <xrpl/beast/hash/uhash.h>
#include <xrpl/beast/hash/xxhasher.h>
#include <functional>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <utility>
/**
* Use hash_* containers for keys that do not need a cryptographically secure

View File

@@ -34,6 +34,7 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>

View File

@@ -10,6 +10,7 @@
#include <xrpl/basics/hardened_hash.h>
#include <xrpl/basics/partitioned_unordered_map.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/hash/hash_append.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
@@ -18,8 +19,17 @@
#include <algorithm>
#include <array>
#include <compare>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <expected>
#include <iterator>
#include <optional>
#include <ostream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
namespace xrpl {
@@ -87,7 +97,7 @@ public:
//
static constexpr std::size_t kBytes = Bits / 8;
static_assert(sizeof(data_) == kBytes, "");
static_assert(sizeof(data_) == kBytes);
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
@@ -270,12 +280,11 @@ public:
{
}
template <
class Container,
class = std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>>>
template <class Container>
explicit BaseUInt(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
// Use AlwaysFalseT so the static_assert condition is dependent
// and only triggers when this constructor template is instantiated.
@@ -285,13 +294,12 @@ public:
"Use base_uint::fromRaw instead.");
}
template <
class Container,
class = std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>>>
template <class Container>
static BaseUInt
fromRaw(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
BaseUInt result;
XRPL_ASSERT(
@@ -302,11 +310,11 @@ public:
}
template <class Container>
std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>,
BaseUInt&>
BaseUInt&
operator=(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
XRPL_ASSERT(
c.size() * sizeof(typename Container::value_type) == size(),

View File

@@ -10,6 +10,7 @@
#include <cstdint>
#include <ratio>
#include <string>
#include <type_traits>
namespace xrpl {

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/beast/hash/hash_append.h>
#include <xrpl/beast/hash/xxhasher.h>
#include <cstdint>
@@ -75,7 +74,7 @@ private:
detail::seed_pair seeds_{detail::makeSeedPair<>()};
public:
using result_type = typename HashAlgorithm::result_type;
using result_type = HashAlgorithm::result_type;
HardenedHash() = default;

View File

@@ -1,7 +1,9 @@
#pragma once
#include <cstddef>
#include <string>
#include <string_view>
#include <utility>
namespace xrpl {

View File

@@ -2,6 +2,7 @@
#include <boost/asio/ssl/context.hpp>
#include <memory>
#include <string>
namespace xrpl {

View File

@@ -3,7 +3,10 @@
#include <xrpl/beast/hash/uhash.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <cstddef>
#include <functional>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <thread>
@@ -57,8 +60,8 @@ public:
{
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
typename partition_map_type::iterator ait{};
typename map_type::iterator mit;
partition_map_type::iterator ait{};
map_type::iterator mit;
Iterator() = default;
@@ -126,8 +129,8 @@ public:
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
typename partition_map_type::iterator ait{};
typename map_type::iterator mit;
partition_map_type::iterator ait{};
map_type::iterator mit;
ConstIterator() = default;

View File

@@ -3,7 +3,6 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/beast/xor_shift_engine.h>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <mutex>
@@ -29,6 +28,7 @@ static_assert(
namespace detail {
// Determines if a type can be called like an Engine
// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC
template <class Engine, class Result = typename Engine::result_type>
using is_engine = std::is_invocable_r<Result, Engine>;
} // namespace detail
@@ -91,8 +91,9 @@ defaultPrng()
*/
/** @{ */
template <class Engine, class Integral>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine, Integral min, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
XRPL_ASSERT(max > min, "xrpl::randInt : max over min inputs");
@@ -103,36 +104,41 @@ randInt(Engine& engine, Integral min, Integral max)
}
template <class Integral>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt(Integral min, Integral max)
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), min, max);
}
template <class Engine, class Integral>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
return randInt(engine, Integral(0), max);
}
template <class Integral>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt(Integral max)
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), max);
}
template <class Integral, class Engine>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
return randInt(engine, std::numeric_limits<Integral>::max());
}
template <class Integral = int>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt()
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), std::numeric_limits<Integral>::max());
}
@@ -141,19 +147,20 @@ randInt()
/** Return a random byte */
/** @{ */
template <class Byte, class Engine>
std::enable_if_t<
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
detail::is_engine<Engine>::value,
Byte>
Byte
randByte(Engine& engine)
requires(
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
detail::is_engine<Engine>::value)
{
return static_cast<Byte>(randInt<Engine, std::uint32_t>(
engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
}
template <class Byte = std::uint8_t>
std::enable_if_t<(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>), Byte>
Byte
randByte()
requires(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>)
{
return randByte<Byte>(defaultPrng());
}

View File

@@ -1,7 +1,5 @@
#pragma once
#include <xrpl/beast/utility/instrumentation.h>
#include <type_traits>
namespace xrpl {
@@ -17,8 +15,9 @@ concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
: sizeof(Dest) >= sizeof(Src));
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr Dest
safeCast(Src s) noexcept
requires(std::is_integral_v<Dest> && std::is_integral_v<Src>)
{
static_assert(
std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
@@ -30,15 +29,17 @@ safeCast(Src s) noexcept
}
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr Dest
safeCast(Src s) noexcept
requires(std::is_enum_v<Dest> && std::is_integral_v<Src>)
{
return static_cast<Dest>(safeCast<std::underlying_type_t<Dest>>(s));
}
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
constexpr Dest
safeCast(Src s) noexcept
requires(std::is_integral_v<Dest> && std::is_enum_v<Src>)
{
return safeCast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
}
@@ -48,8 +49,9 @@ safeCast(Src s) noexcept
// underlying types become safe, it can be converted to a safe_cast.
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr Dest
unsafeCast(Src s) noexcept
requires(std::is_integral_v<Dest> && std::is_integral_v<Src>)
{
static_assert(
!SafeToCast<Src, Dest>,
@@ -59,15 +61,17 @@ unsafeCast(Src s) noexcept
}
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr Dest
unsafeCast(Src s) noexcept
requires(std::is_enum_v<Dest> && std::is_integral_v<Src>)
{
return static_cast<Dest>(unsafeCast<std::underlying_type_t<Dest>>(s));
}
template <class Dest, class Src>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
constexpr Dest
unsafeCast(Src s) noexcept
requires(std::is_integral_v<Dest> && std::is_enum_v<Src>)
{
return unsafeCast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
}

View File

@@ -46,11 +46,9 @@ public:
operator=(ScopeExit&&) = delete;
template <class EFP>
explicit ScopeExit(
EFP&& f,
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
explicit ScopeExit(EFP&& f) noexcept
requires(
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> && std::is_constructible_v<EF, EFP>)
: exitFunction_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
@@ -93,11 +91,9 @@ public:
operator=(ScopeFail&&) = delete;
template <class EFP>
explicit ScopeFail(
EFP&& f,
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
explicit ScopeFail(EFP&& f) noexcept
requires(
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> && std::is_constructible_v<EF, EFP>)
: exitFunction_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
@@ -140,12 +136,11 @@ public:
operator=(ScopeSuccess&&) = delete;
template <class EFP>
explicit ScopeSuccess(
EFP&& f,
std::enable_if_t<
explicit ScopeSuccess(EFP&& f) noexcept(
std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
requires(
!std::is_same_v<std::remove_cv_t<EFP>, ScopeSuccess> &&
std::is_constructible_v<EF, EFP>>* =
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
std::is_constructible_v<EF, EFP>)
: exitFunction_{std::forward<EFP>(f)}
{
}

View File

@@ -3,6 +3,9 @@
#include <boost/algorithm/hex.hpp>
#include <boost/endian/conversion.hpp>
#include <iterator>
#include <string>
namespace xrpl {
template <class FwdIt>

View File

@@ -7,6 +7,7 @@
#include <boost/operators.hpp>
#include <iostream>
#include <string>
#include <type_traits>
namespace xrpl {
@@ -42,10 +43,10 @@ public:
TaggedInteger() = default;
template <
class OtherInt,
class = std::enable_if_t<std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int)>>
explicit constexpr TaggedInteger(OtherInt value) noexcept : value_(value)
template <class OtherInt>
explicit constexpr TaggedInteger(OtherInt value) noexcept
requires(std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int))
: value_(value)
{
static_assert(sizeof(TaggedInteger) == sizeof(Int), "tagged_integer is adding padding");
}

View File

@@ -8,6 +8,7 @@
#include <chrono>
#include <condition_variable>
#include <cstddef>
#include <mutex>
#include <stdexcept>
@@ -18,8 +19,8 @@ template <class Clock>
class IOLatencyProbe
{
private:
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
using duration = Clock::duration;
using time_point = Clock::time_point;
std::recursive_mutex mutex_;
std::condition_variable_any cond_;

View File

@@ -34,10 +34,10 @@ template <class Clock>
class AbstractClock
{
public:
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
using rep = Clock::rep;
using period = Clock::period;
using duration = Clock::duration;
using time_point = Clock::time_point;
using clock_type = Clock;
static bool const is_steady = Clock::is_steady; // NOLINT(readability-identifier-naming)

View File

@@ -20,10 +20,10 @@ public:
explicit BasicSecondsClock() = default;
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
using rep = Clock::rep;
using period = Clock::period;
using duration = Clock::duration;
using time_point = Clock::time_point;
static bool const is_steady = // NOLINT(readability-identifier-naming)
Clock::is_steady;

View File

@@ -3,14 +3,15 @@
#include <xrpl/beast/container/aged_container.h>
#include <chrono>
#include <type_traits>
#include <cstddef>
namespace beast {
/** Expire aged container items past the specified age. */
template <class AgedContainer, class Rep, class Period>
std::enable_if_t<IsAgedContainer<AgedContainer>::value, std::size_t>
std::size_t
expire(AgedContainer& c, std::chrono::duration<Rep, Period> const& age)
requires(IsAgedContainer<AgedContainer>::value)
{
std::size_t n(0);
auto const expired(c.clock().now() - age);

View File

@@ -5,6 +5,7 @@
#include <chrono>
#include <functional>
#include <memory>
#include <utility>
namespace beast {

View File

@@ -5,6 +5,7 @@
#include <chrono>
#include <functional>
#include <memory>
#include <utility>
namespace beast {

View File

@@ -5,6 +5,7 @@
#include <chrono>
#include <functional>
#include <memory>
#include <utility>
namespace beast {

View File

@@ -5,6 +5,7 @@
#include <chrono>
#include <functional>
#include <memory>
#include <utility>
namespace beast {

View File

@@ -16,34 +16,33 @@ template <bool IsConst, class Iterator>
class AgedContainerIterator
{
public:
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using iterator_category = std::iterator_traits<Iterator>::iterator_category;
using value_type = std::conditional_t<
IsConst,
typename Iterator::value_type::Stashed::value_type const,
typename Iterator::value_type::Stashed::value_type>;
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
using difference_type = std::iterator_traits<Iterator>::difference_type;
using pointer = value_type*;
using reference = value_type&;
using time_point = typename Iterator::value_type::Stashed::time_point;
using time_point = Iterator::value_type::Stashed::time_point;
AgedContainerIterator() = default;
// Disable constructing a const_iterator from a non-const_iterator.
// Converting between reverse and non-reverse iterators should be explicit.
template <
bool OtherIsConst,
class OtherIterator,
class = std::enable_if_t<
(!OtherIsConst || IsConst) &&
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>)>>
template <bool OtherIsConst, class OtherIterator>
explicit AgedContainerIterator(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
requires(
(!OtherIsConst || IsConst) &&
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>))
: iter_(other.iter_)
{
}
// Disable constructing a const_iterator from a non-const_iterator.
template <bool OtherIsConst, class = std::enable_if_t<!OtherIsConst || IsConst>>
template <bool OtherIsConst>
AgedContainerIterator(AgedContainerIterator<OtherIsConst, Iterator> const& other)
requires(!OtherIsConst || IsConst)
: iter_(other.iter_)
{
}
@@ -52,7 +51,8 @@ public:
template <bool OtherIsConst, class OtherIterator>
auto
operator=(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
-> std::enable_if_t<!OtherIsConst || IsConst, AgedContainerIterator&>
-> AgedContainerIterator&
requires(!OtherIsConst || IsConst)
{
iter_ = other.iter_;
return *this;

View File

@@ -11,9 +11,14 @@
#include <boost/version.hpp>
#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <utility>
@@ -62,8 +67,8 @@ class AgedOrderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -94,8 +99,8 @@ private:
{
explicit Stashed() = default;
using value_type = typename AgedOrderedContainer::value_type;
using time_point = typename AgedOrderedContainer::time_point;
using value_type = AgedOrderedContainer::value_type;
using time_point = AgedOrderedContainer::time_point;
};
Element(time_point const& when, value_type const& value) : value(value), when(when)
@@ -106,10 +111,9 @@ private:
{
}
template <
class... Args,
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
template <class... Args>
Element(time_point const& when, Args&&... args)
requires(std::is_constructible_v<value_type, Args...>)
: value(std::forward<Args>(args)...), when(when)
{
}
@@ -192,8 +196,8 @@ private:
}
};
using list_type = typename boost::intrusive::
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using list_type =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
IsMulti,
@@ -206,8 +210,7 @@ private:
boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<KeyValueCompare>>::type>;
using ElementAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
@@ -373,8 +376,8 @@ public:
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = std::allocator_traits<Allocator>::pointer;
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
@@ -604,35 +607,25 @@ public:
//
//--------------------------------------------------------------------------
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
at(K const& k);
at(K const& k)
requires(MaybeMap && !MaybeMulti);
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
typename std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional<IsMap, T, void*>::type const&
at(K const& k) const
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key const& key);
operator[](Key const& key)
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key&& key);
operator[](Key&& key)
requires(MaybeMap && !MaybeMulti);
//--------------------------------------------------------------------------
//
@@ -766,35 +759,40 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insert(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insert(value_type const& value) -> iterator
requires MaybeMulti;
// set
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
insert(value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap);
// multiset
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
insert(value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap);
//---
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(const_iterator hint, value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>;
insert(const_iterator hint, value_type const& value) -> iterator
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert(value);
@@ -803,12 +801,14 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(const_iterator hint, value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>;
insert(const_iterator hint, value_type&& value) -> iterator
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert(std::move(value));
@@ -816,20 +816,18 @@ public:
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplace(std::forward<P>(value));
}
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -851,46 +849,45 @@ public:
// map, set
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplace(Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
emplace(Args&&... args) -> iterator
requires MaybeMulti;
// map, set
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplaceHint(const_iterator hint, Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplaceHint(const_iterator hint, Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
std::enable_if_t<MaybeMulti, iterator>
iterator
emplaceHint(const_iterator /*hint*/, Args&&... args)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return emplace<MaybeMulti>(std::forward<Args>(args)...);
}
// enable_if prevents erase (reverse_iterator pos) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents erase (reverse_iterator pos) from compiling
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos);
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value);
// enable_if prevents erase (reverse_iterator first, reverse_iterator last)
// The constraint prevents erase (reverse_iterator first, reverse_iterator last)
// from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
beast::detail::AgedContainerIterator<IsConst, Iterator> last);
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
requires(!IsBoostReverseIterator<Iterator>::value);
template <class K>
auto
@@ -901,13 +898,11 @@ public:
//--------------------------------------------------------------------------
// enable_if prevents touch (reverse_iterator pos) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents touch (reverse_iterator pos) from compiling
template <bool IsConst, class Iterator>
void
touch(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value)
{
touch(pos, clock().now());
}
@@ -1138,25 +1133,25 @@ public:
}
private:
// enable_if prevents erase (reverse_iterator pos, now) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents erase (reverse_iterator pos, now) from compiling
template <bool IsConst, class Iterator>
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
typename clock_type::time_point const& now);
clock_type::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value);
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<MaybePropagate>
swapData(AgedOrderedContainer& other) noexcept;
void
swapData(AgedOrderedContainer& other) noexcept
requires MaybePropagate;
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<!MaybePropagate>
swapData(AgedOrderedContainer& other) noexcept;
void
swapData(AgedOrderedContainer& other) noexcept
requires(!MaybePropagate);
private:
ConfigT config_;
@@ -1248,12 +1243,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
AgedOrderedContainer const& other)
: config_(other.config_)
#if BOOST_VERSION >= 108000
, cont_(other.cont_.get_comp())
#else
, cont_(other.cont_.comp())
#endif
: config_(other.config_), cont_(other.cont_.get_comp())
{
insert(other.cbegin(), other.cend());
}
@@ -1262,12 +1252,7 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
AgedOrderedContainer const& other,
Allocator const& alloc)
: config_(other.config_, alloc)
#if BOOST_VERSION >= 108000
, cont_(other.cont_.get_comp())
#else
, cont_(other.cont_.comp())
#endif
: config_(other.config_, alloc), cont_(other.cont_.get_comp())
{
insert(other.cbegin(), other.cend());
}
@@ -1284,13 +1269,7 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
AgedOrderedContainer&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
Allocator const& alloc)
: config_(std::move(other.config_), alloc)
#if BOOST_VERSION >= 108000
, cont_(std::move(other.cont_.get_comp()))
#else
, cont_(std::move(other.cont_.comp()))
#endif
: config_(std::move(other.config_), alloc), cont_(std::move(other.cont_.get_comp()))
{
insert(other.cbegin(), other.cend());
other.clear();
@@ -1381,9 +1360,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k)
requires(MaybeMap && !MaybeMulti)
{
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
if (iter == cont_.end())
@@ -1392,9 +1372,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
typename std::conditional<IsMap, T, void*>::type const&
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional<IsMap, T, void*>::type const&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k) const
requires(MaybeMap && !MaybeMulti)
{
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
if (iter == cont_.end())
@@ -1403,9 +1384,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key const& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
@@ -1421,9 +1403,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key&& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
@@ -1457,7 +1440,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
@@ -1476,7 +1460,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
Element* const p(newElement(value));
@@ -1490,7 +1475,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, bool MaybeMap>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
-> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
@@ -1509,7 +1495,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, bool MaybeMap>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
-> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
-> iterator
requires(MaybeMulti && !MaybeMap)
{
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
Element* const p(newElement(std::move(value)));
@@ -1526,7 +1513,8 @@ template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
const_iterator hint,
value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>
value_type const& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(
@@ -1547,7 +1535,8 @@ template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
const_iterator hint,
value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>
value_type&& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(
@@ -1567,7 +1556,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
-> std::pair<iterator, bool>
requires(!MaybeMulti)
{
// VFALCO NOTE Its unfortunate that we need to
// construct element here
@@ -1589,7 +1579,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
-> std::enable_if_t<MaybeMulti, iterator>
-> iterator
requires MaybeMulti
{
Element* const p(newElement(std::forward<Args>(args)...));
auto const before(cont_.upper_bound(extract(p->value), std::cref(config_.keyCompare())));
@@ -1604,7 +1595,8 @@ template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplaceHint(
const_iterator hint,
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
// VFALCO NOTE Its unfortunate that we need to
// construct element here
@@ -1623,21 +1615,23 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value)
{
unlinkAndDeleteElement(&*((pos++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator());
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
requires(!IsBoostReverseIterator<Iterator>::value)
{
for (; first != last;)
unlinkAndDeleteElement(&*((first++).iterator()));
@@ -1732,7 +1726,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
cend(),
other.cbegin(),
other.cend(),
[&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) {
[&eq, &other](value_type const& lhs, Other::value_type const& rhs) {
return eq(extract(lhs), other.extract(rhs));
});
}
@@ -1740,11 +1734,12 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
typename clock_type::time_point const& now)
clock_type::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value)
{
auto& e(*pos.iterator());
e.when = now;
@@ -1754,9 +1749,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybePropagate>
std::enable_if_t<MaybePropagate>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
AgedOrderedContainer& other) noexcept
requires MaybePropagate
{
std::swap(config_.keyCompare(), other.config_.keyCompare());
std::swap(config_.alloc(), other.config_.alloc());
@@ -1765,9 +1761,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapDat
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybePropagate>
std::enable_if_t<!MaybePropagate>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
AgedOrderedContainer& other) noexcept
requires(!MaybePropagate)
{
std::swap(config_.keyCompare(), other.config_.keyCompare());
std::swap(config_.clock, other.config_.clock);

View File

@@ -10,13 +10,19 @@
#include <boost/intrusive/unordered_set.hpp>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
/*
@@ -67,8 +73,8 @@ class AgedUnorderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -99,8 +105,8 @@ private:
{
explicit Stashed() = default;
using value_type = typename AgedUnorderedContainer::value_type;
using time_point = typename AgedUnorderedContainer::time_point;
using value_type = AgedUnorderedContainer::value_type;
using time_point = AgedUnorderedContainer::time_point;
};
Element(time_point const& when, value_type const& value) : value(value), when(when)
@@ -111,10 +117,9 @@ private:
{
}
template <
class... Args,
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
template <class... Args>
Element(time_point const& when, Args&&... args)
requires(std::is_constructible_v<value_type, Args...>)
: value(std::forward<Args>(args)...), when(when)
{
}
@@ -201,8 +206,8 @@ private:
}
};
using list_type = typename boost::intrusive::
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using list_type =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
IsMulti,
@@ -219,16 +224,14 @@ private:
boost::intrusive::equal<KeyValueEqual>,
boost::intrusive::cache_begin<true>>::type>;
using bucket_type = typename cont_type::bucket_type;
using bucket_traits = typename cont_type::bucket_traits;
using bucket_type = cont_type::bucket_type;
using bucket_traits = cont_type::bucket_traits;
using ElementAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
using BucketAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using BucketAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using BucketAllocatorTraits = std::allocator_traits<BucketAllocator>;
@@ -542,8 +545,8 @@ public:
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = std::allocator_traits<Allocator>::pointer;
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
@@ -837,35 +840,25 @@ public:
//
//--------------------------------------------------------------------------
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
at(K const& k);
at(K const& k)
requires(MaybeMap && !MaybeMulti);
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
typename std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional<IsMap, T, void*>::type const&
at(K const& k) const
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key const& key);
operator[](Key const& key)
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key&& key);
operator[](Key&& key)
requires(MaybeMap && !MaybeMulti);
//--------------------------------------------------------------------------
//
@@ -963,28 +956,32 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insert(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insert(value_type const& value) -> iterator
requires MaybeMulti;
// map, set
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
insert(value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap);
// multimap, multiset
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
insert(value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap);
// map, set
template <bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires(!MaybeMulti)
{
// Hint is ignored but we provide the interface so
// callers may use ordered and unordered interchangeably.
@@ -993,8 +990,9 @@ public:
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires MaybeMulti
{
// VFALCO TODO The hint could be used to let
// the client order equal ranges
@@ -1003,8 +1001,9 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires(!MaybeMulti)
{
// Hint is ignored but we provide the interface so
// callers may use ordered and unordered interchangeably.
@@ -1013,8 +1012,9 @@ public:
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires MaybeMulti
{
// VFALCO TODO The hint could be used to let
// the client order equal ranges
@@ -1023,20 +1023,18 @@ public:
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplace(std::forward<P>(value));
}
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -1057,23 +1055,26 @@ public:
// set, map
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplace(Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
emplace(Args&&... args) -> iterator
requires MaybeMulti;
// set, map
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplaceHint(const_iterator /*hint*/, Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplaceHint(const_iterator /*hint*/, Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
std::enable_if_t<MaybeMulti, iterator>
iterator
emplaceHint(const_iterator /*hint*/, Args&&... args)
requires MaybeMulti
{
// VFALCO TODO The hint could be used for multi, to let
// the client order equal ranges
@@ -1304,7 +1305,7 @@ public:
class OtherHash,
class OtherAllocator,
bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, bool>
bool
operator==(AgedUnorderedContainer<
false,
OtherIsMap,
@@ -1313,7 +1314,8 @@ public:
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const;
OtherAllocator> const& other) const
requires(!MaybeMulti);
template <
bool OtherIsMap,
@@ -1323,7 +1325,7 @@ public:
class OtherHash,
class OtherAllocator,
bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, bool>
bool
operator==(AgedUnorderedContainer<
true,
OtherIsMap,
@@ -1332,7 +1334,8 @@ public:
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const;
OtherAllocator> const& other) const
requires MaybeMulti;
template <
bool OtherIsMulti,
@@ -1377,13 +1380,14 @@ private:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insertUnchecked(value_type const& value)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insertUnchecked(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insertUnchecked(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insertUnchecked(value_type const& value) -> iterator
requires MaybeMulti;
template <class InputIt>
void
@@ -1414,7 +1418,7 @@ private:
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
typename clock_type::time_point const& now)
clock_type::time_point const& now)
{
auto& e(*pos.iterator());
e.when = now;
@@ -1424,8 +1428,9 @@ private:
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<MaybePropagate>
void
swapData(AgedUnorderedContainer& other) noexcept
requires MaybePropagate
{
std::swap(config_.hashFunction(), other.config_.hashFunction());
std::swap(config_.keyEq(), other.config_.keyEq());
@@ -1435,8 +1440,9 @@ private:
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<!MaybePropagate>
void
swapData(AgedUnorderedContainer& other) noexcept
requires(!MaybePropagate)
{
std::swap(config_.hashFunction(), other.config_.hashFunction());
std::swap(config_.keyEq(), other.config_.keyEq());
@@ -2090,9 +2096,10 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(K const& k)
requires(MaybeMap && !MaybeMulti)
{
auto const iter(
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
@@ -2110,10 +2117,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
typename std::conditional<IsMap, T, void*>::type const&
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional<IsMap, T, void*>::type const&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(
K const& k) const
requires(MaybeMap && !MaybeMulti)
{
auto const iter(
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
@@ -2131,10 +2139,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
Key const& key)
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2160,10 +2169,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
Key&& key)
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2216,7 +2226,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2245,7 +2256,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
maybeRehash(1);
Element* const p(newElement(value));
@@ -2267,7 +2279,8 @@ template <
template <bool MaybeMulti, bool MaybeMap>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type&& value) -> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2296,7 +2309,8 @@ template <
template <bool MaybeMulti, bool MaybeMap>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap)
{
maybeRehash(1);
Element* const p(newElement(std::move(value)));
@@ -2305,7 +2319,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
return iterator(iter);
}
#if 1 // Use insert() instead of insert_check() insert_commit()
// set, map
template <
bool IsMulti,
@@ -2319,7 +2332,8 @@ template <
template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
// VFALCO NOTE Its unfortunate that we need to
@@ -2334,42 +2348,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
deleteElement(p);
return std::make_pair(iterator(result.first), false);
}
#else // As original, use insert_check() / insert_commit () pair.
// set, map
template <
bool IsMulti,
bool IsMap,
class Key,
class T,
class Clock,
class Hash,
class KeyEqual,
class Allocator>
template <bool maybe_multi, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
{
maybe_rehash(1);
// VFALCO NOTE Its unfortunate that we need to
// construct element here
element* const p(new_element(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(
extract(p->value),
std::cref(m_config.hashFunction()),
std::cref(m_config.keyValueEqual()),
d));
if (result.second)
{
auto const iter(m_cont.insert_commit(*p, d));
chronological.list.push_back(*p);
return std::make_pair(iterator(iter), true);
}
delete_element(p);
return std::make_pair(iterator(result.first), false);
}
#endif // 0
// multiset, multimap
template <
@@ -2384,7 +2362,8 @@ template <
template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>
Args&&... args) -> iterator
requires MaybeMulti
{
maybeRehash(1);
Element* const p(newElement(std::forward<Args>(args)...));
@@ -2407,7 +2386,8 @@ template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplaceHint(
const_iterator /*hint*/,
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
// VFALCO NOTE Its unfortunate that we need to
@@ -2558,7 +2538,7 @@ template <
class OtherHash,
class OtherAllocator,
bool MaybeMulti>
std::enable_if_t<!MaybeMulti, bool>
bool
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
AgedUnorderedContainer<
false,
@@ -2569,6 +2549,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
requires(!MaybeMulti)
{
if (size() != other.size())
return false;
@@ -2598,7 +2579,7 @@ template <
class OtherHash,
class OtherAllocator,
bool MaybeMulti>
std::enable_if_t<MaybeMulti, bool>
bool
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
AgedUnorderedContainer<
true,
@@ -2609,6 +2590,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
requires MaybeMulti
{
if (size() != other.size())
return false;
@@ -2645,7 +2627,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(
@@ -2673,7 +2656,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
Element* const p(newElement(value));
chronological.list_.push_back(*p);

View File

@@ -6,6 +6,7 @@
#include <boost/predef.h>
#include <cstddef>
#include <string>
#include <string_view>

View File

@@ -5,11 +5,12 @@
#include <boost/core/detail/string_view.hpp>
#include <algorithm>
#include <cerrno>
#include <cctype>
#include <charconv>
#include <cstdlib>
#include <iterator>
#include <string>
#include <string_view>
#include <system_error>
#include <type_traits>
#include <typeinfo>
@@ -28,16 +29,18 @@ struct LexicalCast<std::string, In>
explicit LexicalCast() = default;
template <class Arithmetic = In>
std::enable_if_t<std::is_arithmetic_v<Arithmetic>, bool>
bool
operator()(std::string& out, Arithmetic in)
requires(std::is_arithmetic_v<Arithmetic>)
{
out = std::to_string(in);
return true;
}
template <class Enumeration = In>
std::enable_if_t<std::is_enum_v<Enumeration>, bool>
bool
operator()(std::string& out, Enumeration in)
requires(std::is_enum_v<Enumeration>)
{
out = std::to_string(static_cast<std::underlying_type_t<Enumeration>>(in));
return true;
@@ -55,8 +58,9 @@ struct LexicalCast<Out, std::string_view>
"beast::LexicalCast can only be used with integral types");
template <class Integral = Out>
std::enable_if_t<std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>, bool>
bool
operator()(Integral& out, std::string_view in) const
requires(std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>)
{
auto first = in.data();
auto last = in.data() + in.size();

View File

@@ -1,6 +1,8 @@
#pragma once
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace beast {
@@ -24,7 +26,7 @@ struct CopyConst<T const, U>
{
explicit CopyConst() = default;
using type = typename std::remove_const<U>::type const;
using type = std::remove_const<U>::type const;
};
/** @} */
@@ -56,7 +58,7 @@ class ListIterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = typename beast::detail::CopyConst<N, typename N::value_type>::type;
using value_type = beast::detail::CopyConst<N, typename N::value_type>::type;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
@@ -259,7 +261,7 @@ template <typename T, typename Tag = void>
class List
{
public:
using Node = typename detail::ListNode<T, Tag>;
using Node = detail::ListNode<T, Tag>;
using value_type = T;
using pointer = value_type*;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <atomic>
#include <cstddef>
#include <iterator>
#include <type_traits>
@@ -12,13 +13,13 @@ template <class Container, bool IsConst>
class LockFreeStackIterator
{
protected:
using Node = typename Container::Node;
using Node = Container::Node;
using NodePtr = std::conditional_t<IsConst, Node const*, Node*>;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = typename Container::value_type;
using difference_type = typename Container::difference_type;
using value_type = Container::value_type;
using difference_type = Container::difference_type;
using pointer =
std::conditional_t<IsConst, typename Container::const_pointer, typename Container::pointer>;
using reference = std::
@@ -58,7 +59,7 @@ public:
return result;
}
NodePtr
[[nodiscard]] NodePtr
node() const
{
return node_;

View File

@@ -5,8 +5,8 @@
#include <array>
#include <chrono>
#include <cstddef>
#include <cstring>
#include <functional>
#include <memory>
#include <string>
#include <system_error>
@@ -26,7 +26,7 @@ template <class T>
inline void
reverseBytes(T& t)
{
unsigned char* bytes =
auto* bytes =
static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
for (unsigned i = 0; i < sizeof(T) / 2; ++i)
std::swap(bytes[i], bytes[sizeof(T) - 1 - i]);
@@ -44,7 +44,7 @@ template <class T>
inline void
maybeReverseBytes(T& t, std::true_type)
{
reverseBytes(t);
reverse_bytes(t);
}
template <class T, class Hasher>
@@ -200,26 +200,29 @@ struct IsContiguouslyHashable<T[N], HashAlgorithm>
// scalars
template <class Hasher, class T>
inline std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
inline void
hash_append(Hasher& h, T const& t) noexcept
requires(IsContiguouslyHashable<T, Hasher>::value)
{
// NOLINTNEXTLINE(bugprone-sizeof-expression)
h(static_cast<void const*>(std::addressof(t)), sizeof(t));
}
template <class Hasher, class T>
inline std::enable_if_t<
!IsContiguouslyHashable<T, Hasher>::value &&
(std::is_integral_v<T> || std::is_pointer_v<T> || std::is_enum_v<T>)>
inline void
hash_append(Hasher& h, T t) noexcept
requires(
!IsContiguouslyHashable<T, Hasher>::value &&
(std::is_integral_v<T> || std::is_pointer_v<T> || std::is_enum_v<T>))
{
detail::reverseBytes(t);
h(std::addressof(t), sizeof(t));
}
template <class Hasher, class T>
inline std::enable_if_t<std::is_floating_point_v<T>>
inline void
hash_append(Hasher& h, T t) noexcept
requires(std::is_floating_point_v<T>)
{
if (t == 0)
t = 0;
@@ -239,36 +242,44 @@ hash_append(Hasher& h, std::nullptr_t) noexcept
// Forward declarations for ADL purposes
template <class Hasher, class T, std::size_t N>
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
hash_append(Hasher& h, T (&a)[N]) noexcept;
void
hash_append(Hasher& h, T (&a)[N]) noexcept
requires(!IsContiguouslyHashable<T, Hasher>::value);
template <class Hasher, class CharT, class Traits, class Alloc>
std::enable_if_t<!IsContiguouslyHashable<CharT, Hasher>::value>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
void
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
requires(!IsContiguouslyHashable<CharT, Hasher>::value);
template <class Hasher, class CharT, class Traits, class Alloc>
std::enable_if_t<IsContiguouslyHashable<CharT, Hasher>::value>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
void
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
requires(IsContiguouslyHashable<CharT, Hasher>::value);
template <class Hasher, class T, class U>
std::enable_if_t<!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value>
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept;
void
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
requires(!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value);
template <class Hasher, class T, class Alloc>
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
void
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
requires(!IsContiguouslyHashable<T, Hasher>::value);
template <class Hasher, class T, class Alloc>
std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
void
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
requires(IsContiguouslyHashable<T, Hasher>::value);
template <class Hasher, class T, std::size_t N>
std::enable_if_t<!IsContiguouslyHashable<std::array<T, N>, Hasher>::value>
hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
void
hash_append(Hasher& h, std::array<T, N> const& a) noexcept
requires(!IsContiguouslyHashable<std::array<T, N>, Hasher>::value);
template <class Hasher, class... T>
std::enable_if_t<!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value>
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
void
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
requires(!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value);
template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
void
@@ -279,11 +290,13 @@ void
hash_append(Hasher& h, std::unordered_set<Key, Hash, Pred, Alloc> const& s);
template <class Hasher, class Key, class Compare, class Alloc>
std::enable_if_t<!IsContiguouslyHashable<Key, Hasher>::value>
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
void
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
requires(!IsContiguouslyHashable<Key, Hasher>::value);
template <class Hasher, class Key, class Compare, class Alloc>
std::enable_if_t<IsContiguouslyHashable<Key, Hasher>::value>
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
void
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
requires(IsContiguouslyHashable<Key, Hasher>::value);
template <class Hasher, class T0, class T1, class... T>
void
hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
@@ -291,8 +304,9 @@ hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
// c-array
template <class Hasher, class T, std::size_t N>
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
void
hash_append(Hasher& h, T (&a)[N]) noexcept
requires(!IsContiguouslyHashable<T, Hasher>::value)
{
for (auto const& t : a)
hash_append(h, t);
@@ -301,8 +315,9 @@ hash_append(Hasher& h, T (&a)[N]) noexcept
// basic_string
template <class Hasher, class CharT, class Traits, class Alloc>
inline std::enable_if_t<!IsContiguouslyHashable<CharT, Hasher>::value>
inline void
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
requires(!IsContiguouslyHashable<CharT, Hasher>::value)
{
for (auto c : s)
hash_append(h, c);
@@ -310,8 +325,9 @@ hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcep
}
template <class Hasher, class CharT, class Traits, class Alloc>
inline std::enable_if_t<IsContiguouslyHashable<CharT, Hasher>::value>
inline void
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
requires(IsContiguouslyHashable<CharT, Hasher>::value)
{
h(s.data(), s.size() * sizeof(CharT));
hash_append(h, s.size());
@@ -320,8 +336,9 @@ hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcep
// pair
template <class Hasher, class T, class U>
inline std::enable_if_t<!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value>
inline void
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
requires(!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value)
{
hash_append(h, p.first, p.second);
}
@@ -329,8 +346,9 @@ hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
// vector
template <class Hasher, class T, class Alloc>
inline std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
inline void
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
requires(!IsContiguouslyHashable<T, Hasher>::value)
{
for (auto const& t : v)
hash_append(h, t);
@@ -338,8 +356,9 @@ hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
}
template <class Hasher, class T, class Alloc>
inline std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
inline void
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
requires(IsContiguouslyHashable<T, Hasher>::value)
{
h(v.data(), v.size() * sizeof(T));
hash_append(h, v.size());
@@ -348,23 +367,26 @@ hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
// array
template <class Hasher, class T, std::size_t N>
std::enable_if_t<!IsContiguouslyHashable<std::array<T, N>, Hasher>::value>
void
hash_append(Hasher& h, std::array<T, N> const& a) noexcept
requires(!IsContiguouslyHashable<std::array<T, N>, Hasher>::value)
{
for (auto const& t : a)
hash_append(h, t);
}
template <class Hasher, class Key, class Compare, class Alloc>
std::enable_if_t<!IsContiguouslyHashable<Key, Hasher>::value>
void
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
requires(!IsContiguouslyHashable<Key, Hasher>::value)
{
for (auto const& t : v)
hash_append(h, t);
}
template <class Hasher, class Key, class Compare, class Alloc>
std::enable_if_t<IsContiguouslyHashable<Key, Hasher>::value>
void
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
requires(IsContiguouslyHashable<Key, Hasher>::value)
{
h(&(v.begin()), v.size() * sizeof(Key));
}
@@ -395,8 +417,9 @@ tuple_hash(Hasher& h, std::tuple<T...> const& t, std::index_sequence<I...>) noex
} // namespace detail
template <class Hasher, class... T>
inline std::enable_if_t<!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value>
inline void
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
requires(!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value)
{
detail::tuple_hash(h, t, std::index_sequence_for<T...>{});
}

View File

@@ -11,7 +11,7 @@ struct Uhash
{
Uhash() = default;
using result_type = typename Hasher::result_type;
using result_type = Hasher::result_type;
template <class T>
result_type

View File

@@ -124,14 +124,18 @@ public:
}
}
template <class Seed, std::enable_if_t<std::is_unsigned_v<Seed>>* = nullptr>
explicit Xxhasher(Seed seed) : seed_(seed)
template <class Seed>
explicit Xxhasher(Seed seed)
requires(std::is_unsigned_v<Seed>)
: seed_(seed)
{
resetBuffers();
}
template <class Seed, std::enable_if_t<std::is_unsigned_v<Seed>>* = nullptr>
Xxhasher(Seed seed, Seed) : seed_(seed)
template <class Seed>
Xxhasher(Seed seed, Seed)
requires(std::is_unsigned_v<Seed>)
: seed_(seed)
{
resetBuffers();
}

View File

@@ -4,8 +4,10 @@
#include <xrpl/beast/insight/Event.h>
#include <xrpl/beast/insight/Gauge.h>
#include <xrpl/beast/insight/Hook.h>
#include <xrpl/beast/insight/HookImpl.h>
#include <xrpl/beast/insight/Meter.h>
#include <memory>
#include <string>
namespace beast::insight {

View File

@@ -1,15 +0,0 @@
#pragma once
#include <xrpl/beast/insight/Collector.h>
#include <xrpl/beast/insight/Counter.h>
#include <xrpl/beast/insight/CounterImpl.h>
#include <xrpl/beast/insight/Event.h>
#include <xrpl/beast/insight/EventImpl.h>
#include <xrpl/beast/insight/Gauge.h>
#include <xrpl/beast/insight/GaugeImpl.h>
#include <xrpl/beast/insight/Group.h>
#include <xrpl/beast/insight/Groups.h>
#include <xrpl/beast/insight/Hook.h>
#include <xrpl/beast/insight/HookImpl.h>
#include <xrpl/beast/insight/NullCollector.h>
#include <xrpl/beast/insight/StatsDCollector.h>

View File

@@ -2,6 +2,8 @@
#include <xrpl/beast/insight/Collector.h>
#include <memory>
namespace beast::insight {
/** A Collector which does not collect metrics. */

View File

@@ -4,6 +4,9 @@
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/beast/utility/Journal.h>
#include <memory>
#include <string>
namespace beast::insight {
/** A Collector that reports metrics to a StatsD server.

View File

@@ -9,6 +9,7 @@
#include <boost/asio/ip/address.hpp>
#include <boost/functional/hash.hpp>
#include <cstddef>
#include <string>
//------------------------------------------------------------------------------

View File

@@ -1,7 +1,5 @@
#pragma once
#include <xrpl/beast/hash/hash_append.h>
#include <boost/asio/ip/address_v4.hpp>
namespace beast::IP {

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