Compare commits

..

48 Commits

Author SHA1 Message Date
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
972 changed files with 33064 additions and 5625 deletions

View File

@@ -1,159 +1,140 @@
--- ---
Checks: "-*, Checks: "-*,
bugprone-argument-comment, bugprone-*,
bugprone-assert-side-effect, -bugprone-easily-swappable-parameters,
bugprone-bad-signal-to-kill-thread, -bugprone-exception-escape,
bugprone-bool-pointer-implicit-conversion, -bugprone-implicit-widening-of-multiplication-result,
bugprone-capturing-this-in-member-variable, -bugprone-narrowing-conversions,
bugprone-casting-through-void, -bugprone-throwing-static-initialization,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function, cppcoreguidelines-*,
bugprone-copy-constructor-init, -cppcoreguidelines-avoid-c-arrays,
bugprone-crtp-constructor-accessibility, -cppcoreguidelines-avoid-capturing-lambda-coroutines,
bugprone-dangling-handle, -cppcoreguidelines-avoid-const-or-ref-data-members,
bugprone-dynamic-static-initializers, -cppcoreguidelines-avoid-do-while,
bugprone-empty-catch, -cppcoreguidelines-avoid-goto,
bugprone-fold-init-type, -cppcoreguidelines-avoid-magic-numbers,
bugprone-forward-declaration-namespace, -cppcoreguidelines-avoid-non-const-global-variables,
bugprone-inaccurate-erase, -cppcoreguidelines-avoid-reference-coroutine-parameters,
bugprone-inc-dec-in-conditions, -cppcoreguidelines-c-copy-assignment-signature,
bugprone-incorrect-enable-if, -cppcoreguidelines-explicit-virtual-functions,
bugprone-incorrect-roundings, -cppcoreguidelines-interfaces-global-init,
bugprone-infinite-loop, -cppcoreguidelines-macro-to-enum,
bugprone-integer-division, -cppcoreguidelines-macro-usage,
bugprone-lambda-function-name, -cppcoreguidelines-missing-std-forward,
bugprone-macro-parentheses, -cppcoreguidelines-narrowing-conversions,
bugprone-macro-repeated-side-effects, -cppcoreguidelines-no-malloc,
bugprone-misleading-setter-of-reference, -cppcoreguidelines-noexcept-destructor,
bugprone-misplaced-operator-in-strlen-in-alloc, -cppcoreguidelines-noexcept-move-operations,
bugprone-misplaced-pointer-arithmetic-in-alloc, -cppcoreguidelines-noexcept-swap,
bugprone-misplaced-widening-cast, -cppcoreguidelines-non-private-member-variables-in-classes,
bugprone-move-forwarding-reference, -cppcoreguidelines-owning-memory,
bugprone-multi-level-implicit-pointer-conversion, -cppcoreguidelines-prefer-member-initializer,
bugprone-multiple-new-in-one-expression, -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
bugprone-multiple-statement-macro, -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
bugprone-no-escape, -cppcoreguidelines-pro-bounds-constant-array-index,
bugprone-non-zero-enum-to-bool-conversion, -cppcoreguidelines-pro-bounds-pointer-arithmetic,
bugprone-optional-value-conversion, -cppcoreguidelines-pro-type-const-cast,
bugprone-parent-virtual-call, -cppcoreguidelines-pro-type-cstyle-cast,
bugprone-pointer-arithmetic-on-polymorphic-object, -cppcoreguidelines-pro-type-reinterpret-cast,
bugprone-posix-return, -cppcoreguidelines-pro-type-union-access,
bugprone-redundant-branch-condition, -cppcoreguidelines-pro-type-vararg,
bugprone-reserved-identifier, -cppcoreguidelines-slicing,
bugprone-return-const-ref-from-parameter, -cppcoreguidelines-special-member-functions,
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,
llvm-namespace-comment, llvm-namespace-comment,
misc-const-correctness,
misc-definitions-in-headers, misc-*,
misc-header-include-cycle, -misc-anonymous-namespace-in-header,
misc-include-cleaner, -misc-confusable-identifiers,
misc-misplaced-const, -misc-coroutine-hostile-raii,
misc-redundant-expression, -misc-misleading-bidirectional,
misc-static-assert, -misc-misleading-identifier,
misc-throw-by-value-catch-by-reference, -misc-multiple-inheritance,
misc-unused-alias-decls, -misc-new-delete-overloads,
misc-unused-using-decls, -misc-no-recursion,
modernize-concat-nested-namespaces, -misc-non-copyable-objects,
modernize-deprecated-headers, -misc-non-private-member-variables-in-classes,
modernize-make-shared, -misc-override-with-different-visibility,
modernize-make-unique, -misc-predictable-rand,
modernize-pass-by-value, -misc-unconventional-assign-operator,
modernize-type-traits, -misc-uniqueptr-reset-release,
modernize-use-designated-initializers, -misc-unused-parameters,
modernize-use-emplace, -misc-use-anonymous-namespace,
modernize-use-equals-default, -misc-use-internal-linkage,
modernize-use-equals-delete,
modernize-use-nodiscard, modernize-*,
modernize-use-override, -modernize-avoid-c-arrays,
modernize-use-ranges, -modernize-avoid-c-style-cast,
modernize-use-scoped-lock, -modernize-avoid-setjmp-longjmp,
modernize-use-starts-ends-with, -modernize-avoid-variadic-functions,
modernize-use-std-numbers, -modernize-deprecated-ios-base-aliases,
modernize-use-using, -modernize-loop-convert,
performance-faster-string-find, -modernize-macro-to-enum,
performance-for-range-copy, -modernize-min-max-use-initializer-list,
performance-implicit-conversion-in-loop, -modernize-raw-string-literal,
performance-inefficient-vector-operation, -modernize-redundant-void-arg,
performance-move-const-arg, -modernize-replace-auto-ptr,
performance-move-constructor-init, -modernize-replace-disallow-copy-and-assign-macro,
performance-no-automatic-move, -modernize-replace-random-shuffle,
performance-trivially-destructible, -modernize-return-braced-init-list,
readability-ambiguous-smartptr-reset-call, -modernize-shrink-to-fit,
readability-avoid-nested-conditional-operator, -modernize-use-bool-literals,
readability-avoid-return-with-void-value, -modernize-use-default-member-init,
readability-braces-around-statements, -modernize-use-integer-sign-comparison,
readability-const-return-type, -modernize-use-noexcept,
readability-container-contains, -modernize-use-nullptr,
readability-container-size-empty, -modernize-use-std-format,
readability-convert-member-functions-to-static, -modernize-use-std-print,
readability-duplicate-include, -modernize-use-trailing-return-type,
readability-else-after-return, -modernize-use-transparent-functors,
readability-enum-initial-value, -modernize-use-uncaught-exceptions,
readability-identifier-naming,
readability-implicit-bool-conversion, performance-*,
readability-make-member-function-const, -performance-avoid-endl,
readability-math-missing-parentheses, -performance-enum-size,
readability-misleading-indentation, -performance-inefficient-algorithm,
readability-non-const-parameter, -performance-inefficient-string-concatenation,
readability-redundant-casting, -performance-no-int-to-ptr,
readability-redundant-declaration, -performance-noexcept-destructor,
readability-redundant-inline-specifier, -performance-noexcept-move-constructor,
readability-redundant-member-init, -performance-noexcept-swap,
readability-redundant-string-init, -performance-type-promotion-in-math-fn,
readability-reference-to-constructed-temporary, -performance-unnecessary-copy-initialization,
readability-simplify-boolean-expr, -performance-unnecessary-value-param,
readability-static-definition-in-anonymous-namespace,
readability-suspicious-call-argument, readability-*,
readability-use-std-min-max -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-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 # 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-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc 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-braces-around-statements.ShortStatementLines: 2
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE readability-identifier-naming.MacroDefinitionCase: UPPER_CASE

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ inputs:
remote_url: remote_url:
description: "The URL of the Conan endpoint to use." description: "The URL of the Conan endpoint to use."
required: false required: false
default: https://conan.ripplex.io default: https://conan.xrplf.org/repository/conan/
runs: runs:
using: composite 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 Loop: xrpld.app xrpld.overlay
xrpld.app > xrpld.overlay xrpld.app > xrpld.overlay

View File

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

View File

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

View File

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

View File

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

View File

@@ -70,6 +70,7 @@ jobs:
.github/workflows/reusable-upload-recipe.yml .github/workflows/reusable-upload-recipe.yml
.clang-tidy .clang-tidy
.codecov.yml .codecov.yml
bin/check-tools.sh
cfg/** cfg/**
cmake/** cmake/**
conan/** conan/**
@@ -121,7 +122,6 @@ jobs:
issues: write issues: write
contents: read contents: read
with: with:
check_only_changed: true
create_issue_on_failure: false create_issue_on_failure: false
build-test: 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') }} 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 uses: ./.github/workflows/reusable-upload-recipe.yml
secrets: secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
notify-clio: notify-clio:
needs: upload-recipe needs: upload-recipe

View File

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

View File

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

View File

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

View File

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

View File

@@ -82,7 +82,7 @@ jobs:
name: ${{ inputs.config_name }} name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }} runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }} container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }} timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 180 }}
env: env:
# Use a namespace to keep the objects separate for each configuration. # Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }} CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -113,7 +113,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8 uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with: with:
enable_ccache: ${{ inputs.ccache_enabled }} enable_ccache: ${{ inputs.ccache_enabled }}
@@ -163,7 +163,7 @@ jobs:
CMAKE_ARGS: ${{ inputs.cmake_args }} CMAKE_ARGS: ${{ inputs.cmake_args }}
run: | run: |
cmake \ 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_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \ ${CMAKE_ARGS} \
@@ -227,23 +227,7 @@ jobs:
--build . \ --build . \
--config "${BUILD_TYPE}" \ --config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \ --parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}" \ --target "${CMAKE_TARGET}"
2>&1 | tee build.log
# 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 - name: Show ccache statistics
if: ${{ inputs.ccache_enabled }} if: ${{ inputs.ccache_enabled }}
@@ -341,7 +325,7 @@ jobs:
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
- name: Show test failure summary - name: Show test failure summary
if: ${{ failure() }} if: ${{ failure() && !inputs.build_only }}
env: env:
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }} WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: | run: |
@@ -352,17 +336,13 @@ jobs:
cd "${WORKING_DIR}" cd "${WORKING_DIR}"
if [ -f unittest.log ]; then if [ ! -f unittest.log ]; then
if ! grep -E "failed" unittest.log | grep -vE "^I[0-9]|^[0-9]+> (ERR:|FTL:)"; then
echo "unittest.log present but no failure lines found."
fi
else
echo "unittest.log not found; embedded tests may not have run." echo "unittest.log not found; embedded tests may not have run."
if [ -f build.log ]; then exit 0
if ! grep -E "error:" build.log; then fi
echo "build.log present but no compile errors found."
fi if ! grep -E "failed" unittest.log; then
fi echo "Log present but no failure lines found in unittest.log."
fi fi
- name: Debug failure (Linux) - name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }} if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}

View File

@@ -3,10 +3,6 @@ name: Run clang-tidy on files
on: on:
workflow_call: workflow_call:
inputs: 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: create_issue_on_failure:
description: "Whether to create an issue if the check failed" description: "Whether to create an issue if the check failed"
type: boolean type: boolean
@@ -29,17 +25,16 @@ env:
jobs: jobs:
determine-files: determine-files:
if: ${{ inputs.check_only_changed }}
permissions: permissions:
contents: read 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: run-clang-tidy:
name: Run clang tidy name: Run clang tidy
needs: [determine-files] 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"] 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: permissions:
contents: read contents: read
issues: write issues: write
@@ -48,7 +43,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8 uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with: with:
enable_ccache: false enable_ccache: false
@@ -84,6 +79,7 @@ jobs:
-Dtests=ON \ -Dtests=ON \
-Dwerr=ON \ -Dwerr=ON \
-Dxrpld=ON \ -Dxrpld=ON \
-Dverify_headers=ON \
.. ..
# clang-tidy needs headers generated from proto files # clang-tidy needs headers generated from proto files
@@ -96,15 +92,15 @@ jobs:
id: run_clang_tidy id: run_clang_tidy
continue-on-error: true continue-on-error: true
env: 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: | run: |
set -o pipefail 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}" 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' }} if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: | run: |
sed '/error\||/!d' "${OUTPUT_FILE}" bin/filter-clang-tidy.py "${OUTPUT_FILE}"
- name: Upload clang-tidy output - name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }} if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
@@ -148,12 +144,12 @@ jobs:
\`\`\` \`\`\`
EOF 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' }} if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: | run: |
if [ -f "${OUTPUT_FILE}" ]; then if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:' # Filter to the unique errors with their source context.
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >"${FILTERED_OUTPUT_FILE}" || true 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 filtered output is empty, use original (might be a different error format)
if [ ! -s "${FILTERED_OUTPUT_FILE}" ]; then if [ ! -s "${FILTERED_OUTPUT_FILE}" ]; then

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ You can verify that the required tools are installed and runnable with:
| ----------- | --------------- | | ----------- | --------------- |
| GCC | 15.2 | | GCC | 15.2 |
| Clang | 22 | | Clang | 22 |
| Apple Clang | 17 | | Apple Clang | 21 |
| MSVC | 19.44[^windows] | | MSVC | 19.44[^windows] |
## Operating Systems ## 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: Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
```bash ```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 ### Set Up Ccache
@@ -317,21 +317,41 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
## Options ## Options
| Option | Default Value | Description | | Option | Default Value | Description |
| ---------- | ------------- | -------------------------------------------------------------- | | ---------------- | ------------- | ----------------------------------------------------------------------------- |
| `assert` | OFF | Force enabling assertions. | | `assert` | OFF | Force enabling assertions. |
| `coverage` | OFF | Prepare the coverage report. | | `coverage` | OFF | Prepare the coverage report. |
| `tests` | OFF | Build tests. | | `tests` | OFF | Build tests. |
| `unity` | OFF | Configure a unity build. | | `unity` | OFF | Configure a unity build. |
| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. | | `verify_headers` | ON | Make the `verify-headers` target available to compile each header on its own. |
| `werr` | OFF | Treat compilation warnings as errors | | `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. |
| `wextra` | OFF | Enable additional compilation warnings | | `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 [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 memory) since they concatenate sources into fewer translation units. Non-unity
builds may be faster for incremental builds, and can be helpful for detecting builds may be faster for incremental builds, and can be helpful for detecting
`#include` omissions. `#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 ## Troubleshooting
### Conan ### Conan

View File

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

View File

@@ -90,16 +90,19 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check perl check perl
check pkg-config check pkg-config
check vim check vim
check zip
# These tools are present in our Linux CI images and in local development # 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 # setups, but not in the macOS CI environment. So check them everywhere
# except when running in CI on macOS. # except when running in CI on macOS.
if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then
check clang-format check clang-format
check dot
check doxygen check doxygen
check gcovr check gcovr
check gh check gh
check git-cliff check git-cliff
check git-lfs
check gpg check gpg
# pre-commit, or its alternative implementation prek # pre-commit, or its alternative implementation prek
check pre-commit sh -c 'pre-commit --version || prek --version' 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 #!/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 from __future__ import annotations
import json
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
from collections import defaultdict
from pathlib import Path from pathlib import Path
HEADER_EXTENSIONS = {".h", ".hpp", ".ipp"} CLANG_TIDY_VERSION = 22
SOURCE_EXTENSIONS = {".cpp"}
INCLUDE_RE = re.compile(r"^\s*#\s*include\s*[<\"]([^>\"]+)[>\"]")
def find_run_clang_tidy() -> str | None: 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): if path := shutil.which(candidate):
return path return path
return None return None
@@ -32,142 +35,23 @@ def find_build_dir(repo_root: Path) -> Path | None:
return 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(): def main():
if not os.environ.get("TIDY"): if not os.environ.get("TIDY"):
return 0 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( repo_root = Path(
subprocess.check_output( subprocess.check_output(
["git", "rev-parse", "--show-toplevel"], ["git", "rev-parse", "--show-toplevel"],
@@ -175,19 +59,6 @@ def main():
text=True, text=True,
).strip() ).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) build_dir = find_build_dir(repo_root)
if not build_dir: if not build_dir:
print( print(
@@ -197,13 +68,9 @@ def main():
) )
return 1 return 1
tidy_files = resolve_files(files, build_dir, repo_root)
if not tidy_files:
return 0
result = subprocess.run( result = subprocess.run(
[run_clang_tidy, "-quiet", "-p", str(build_dir), "-fix", "-allow-no-checks"] [run_clang_tidy, "-quiet", "-p", str(build_dir), "-fix", "-allow-no-checks"]
+ tidy_files + files
) )
return result.returncode 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() else()
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}") message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif() 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. # Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking.
# #
# Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in # Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in

View File

@@ -247,6 +247,7 @@ target_link_modules(
if(xrpld) if(xrpld)
add_executable(xrpld) add_executable(xrpld)
patch_nix_binary(xrpld)
if(tests) if(tests)
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS) target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
target_compile_definitions( target_compile_definitions(
@@ -292,4 +293,13 @@ if(xrpld)
PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk
) )
endif() 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() endif()

View File

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

View File

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

View File

@@ -30,6 +30,23 @@ if(tests)
endif() endif()
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) option(unity "Creates a build using UNITY support in cmake." OFF)
if(unity) if(unity)
if(NOT is_ci) if(NOT is_ci)

View File

@@ -1,4 +1,5 @@
include(isolate_headers) include(isolate_headers)
include(verify_headers)
# Create an OBJECT library target named # Create an OBJECT library target named
# #
@@ -37,4 +38,20 @@ function(add_module parent name)
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
PRIVATE 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() 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", "version": "0.5",
"requires": [ "requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503", "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987", "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149", "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231", "soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329", "secp256k1/0.7.1#b1f450b7f78a36fff75bb6934a356f3a%1782338841.3729",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1782392413.075713",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888", "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1782392402.431897",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12", "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506", "openssl/3.6.3#1163d4ddc603907084d08a6a0c6e580f%1782307150.583886",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408", "nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1782392402.297166",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "mpt-crypto/0.4.0-rc2#a580f2f9ad0e795de696aa62d54fb9af%1782425834.488828",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", "lz4/1.10.0#982d9b673900f665a1da109e09c17cab%1782392402.164188",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", "libiconv/1.17#9923bc6dc6f106646d6967e0039a5ada%1782392792.775744",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1782392402.420732",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228", "jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152", "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342", "grpc/1.81.1#5217e6ef0544c42b46f4af35d5e7f649%1782307148.845616",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681", "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1782392402.296732",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9", "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1782392419.475605",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
], ],
"build_requires": [ "build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503", "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964", "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1782395692.540639",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12", "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649", "msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#4523e4347b55cd26ae918bd5770cab9a%1778062762.471", "m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183", "cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447", "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86", "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
], ],
"python_requires": [], "python_requires": [],
"overrides": { "overrides": {
@@ -57,7 +58,7 @@
"boost/1.91.0" "boost/1.91.0"
], ],
"lz4/[>=1.9.4 <2]": [ "lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504" "lz4/1.10.0#982d9b673900f665a1da109e09c17cab"
] ]
}, },
"config_requires": [] "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 # 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 # patched are used. We also add it there to not created huge diff when the
# official Conan Center Index is updated. # 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. # Delete any existing lockfile.
rm -f conan.lock rm -f conan.lock

View File

@@ -10,16 +10,18 @@
os={{ os }} os={{ os }}
arch={{ arch }} arch={{ arch }}
build_type=Debug build_type=Debug
compiler={{compiler}} compiler={{ compiler }}
compiler.version={{ compiler_version }} compiler.version={{ compiler_version }}
compiler.cppstd=23 compiler.cppstd=23
{% if os == "Windows" %} {% if os == "Windows" %}
compiler.runtime=static compiler.runtime=static
{% else %} {% else %}
compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}} compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
{% endif %} {% endif %}
[conf] [conf]
{% if compiler == "gcc" and compiler_version < 13 %} {# By default, Conan tries to reuse binaries built with different cppstd versions. #}
tools.build:cxxflags+=['-Wno-restrict'] {# We want to avoid that to improve reproduceability, so we add the cppstd version to the package ID. #}
{% endif %} {# 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 %} {% endif %}
[conf] [conf]
tools.build:defines+={{defines}} tools.build:defines+={{ defines }}
tools.build:cxxflags+={{sanitizer_compiler_flags}} tools.build:cxxflags+={{ sanitizer_compiler_flags }}
tools.build:sharedlinkflags+={{sanitizer_linker_flags}} tools.build:sharedlinkflags+={{ sanitizer_linker_flags }}
tools.build:exelinkflags+={{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"] 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" # &: 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] [options]
{% if enable_asan %} {% if enable_asan %}

View File

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

View File

@@ -288,7 +288,7 @@ components with non-trivial changes are colored green.
validated. validated.
![Sequence diagram](./negativeUNL_highLevel_sequence.png?raw=true "Negative UNL ![Sequence diagram](./negativeUNL_highLevel_sequence.png?raw=true "Negative UNL
Changes") Changes")
## Roads Not Taken ## 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: can do this by running:
```bash ```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: Alternatively, you can pull our recipes from the repository and export them locally:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -211,15 +211,17 @@ operator<<(Stream& s, Slice const& v)
} }
template <class T, std::size_t N> 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) 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()); return Slice(a.data(), a.size());
} }
template <class T, class Alloc> 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) 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()); return Slice(v.data(), v.size());
} }

View File

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

View File

@@ -1,22 +1,46 @@
#pragma once #pragma once
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/SharedWeakCachePointer.h>
#include <xrpl/basics/Log.h> #include <xrpl/basics/SharedWeakCachePointer.ipp> // IWYU pragma: keep
#include <xrpl/basics/SharedWeakCachePointer.ipp>
#include <xrpl/basics/UnorderedContainers.h> #include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/hardened_hash.h> #include <xrpl/basics/hardened_hash.h>
#include <xrpl/beast/clock/abstract_clock.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 <atomic>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional> #include <functional>
#include <memory>
#include <mutex> #include <mutex>
#include <string>
#include <thread> #include <thread>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
namespace xrpl { 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. /** Map/cache combination.
This class implements a cache and a map. The cache keeps objects alive 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 in the map. The map allows multiple code paths that reference objects
@@ -96,6 +120,32 @@ public:
bool bool
del(key_type const& key, bool valid); 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: public:
/** Replace aliased objects with originals. /** Replace aliased objects with originals.
@@ -104,19 +154,52 @@ public:
This routine eliminates the duplicate and performs a replacement This routine eliminates the duplicate and performs a replacement
on the callers shared pointer if needed. 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 key The key corresponding to the object
@param data A shared pointer to the data 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. @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 R> **/
template <class Callback>
bool 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 bool
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data); 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 bool
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data); canonicalizeReplaceClient(key_type const& key, SharedPointerType& data);
@@ -129,11 +212,13 @@ public:
*/ */
template <class ReturnType = bool> template <class ReturnType = bool>
auto 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> template <class ReturnType = bool>
auto 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 // VFALCO NOTE It looks like this returns a copy of the data in
// the output parameter 'data'. This could be expensive. // the output parameter 'data'. This could be expensive.
@@ -262,7 +347,7 @@ private:
sweepHelper( sweepHelper(
clock_type::time_point const& whenExpire, clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now, [[maybe_unused]] clock_type::time_point const& now,
typename KeyValueCacheType::map_type& partition, KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep, SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&); std::scoped_lock<std::recursive_mutex> const&);
@@ -271,7 +356,7 @@ private:
sweepHelper( sweepHelper(
clock_type::time_point const& whenExpire, clock_type::time_point const& whenExpire,
clock_type::time_point const& now, clock_type::time_point const& now,
typename KeyOnlyCacheType::map_type& partition, KeyOnlyCacheType::map_type& partition,
SweptPointersVector&, SweptPointersVector&,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&); std::scoped_lock<std::recursive_mutex> const&);

View File

@@ -1,10 +1,35 @@
#pragma once #pragma once
#include <xrpl/basics/IntrusivePointer.ipp> #include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Log.h> // IWYU pragma: keep
#include <xrpl/basics/TaggedCache.h> #include <xrpl/basics/TaggedCache.h>
namespace xrpl { 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 < template <
class Key, class Key,
class T, class T,
@@ -32,7 +57,10 @@ inline TaggedCache<
beast::insight::Collector::ptr const& collector) beast::insight::Collector::ptr const& collector)
: journal_(journal) : journal_(journal)
, clock_(clock) , clock_(clock)
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector) , stats_(
name,
[this] { collectMetrics(); },
collector)
, name_(name) , name_(name)
, targetSize_(size) , targetSize_(size)
, targetAge_(expiration) , targetAge_(expiration)
@@ -300,13 +328,29 @@ template <
class Hash, class Hash,
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
template <class R> template <class Policy, class Callback>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: 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 canonical value, store if needed, refresh in cache
// Return values: true=we had the data already // 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_); std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key); auto cit = cache_.find(key);
@@ -324,13 +368,14 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
Entry& entry = cit->second; Entry& entry = cit->second;
entry.touch(clock_.now()); entry.touch(clock_.now());
auto shouldReplace = [&] { auto shouldReplaceCached = [&] {
if constexpr (std::is_invocable_r_v<bool, R>) if constexpr (replaceCached)
{ {
// The reason for this extra complexity is for intrusive return true;
// strong/weak combo getting a strong is relatively expensive }
// and not needed for many cases. else if constexpr (std::is_same_v<Policy, detail::ReplaceClient>)
return replaceCallback(); {
return false;
} }
else else
{ {
@@ -340,11 +385,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached()) if (entry.isCached())
{ {
if (shouldReplace()) if (shouldReplaceCached())
{ {
entry.ptr = data; entry.ptr = data;
} }
else else if constexpr (!replaceCached)
{ {
data = entry.ptr.getStrong(); data = entry.ptr.getStrong();
} }
@@ -356,11 +401,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (cachedData) if (cachedData)
{ {
if (shouldReplace()) if (shouldReplaceCached())
{ {
entry.ptr = data; entry.ptr = data;
} }
else else if constexpr (!replaceCached)
{ {
entry.ptr.convertToStrong(); entry.ptr.convertToStrong();
data = cachedData; data = cachedData;
@@ -376,6 +421,24 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return false; 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 < template <
class Key, class Key,
class T, class T,
@@ -389,7 +452,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data) canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data)
{ {
return canonicalize(key, const_cast<SharedPointerType&>(data), []() { return true; }); return canonicalizeImpl(key, data, detail::ReplaceCached{});
} }
template < template <
@@ -405,7 +468,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data) canonicalizeReplaceClient(key_type const& key, SharedPointerType& data)
{ {
return canonicalize(key, data, []() { return false; }); return canonicalizeImpl(key, data, detail::ReplaceClient{});
} }
template < template <
@@ -440,7 +503,8 @@ template <
template <class ReturnType> template <class ReturnType>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: 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( static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> || std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
@@ -470,7 +534,8 @@ template <
template <class ReturnType> template <class ReturnType>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: 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_); std::scoped_lock const lock(mutex_);
clock_type::time_point const now(clock_.now()); clock_type::time_point const now(clock_.now());
@@ -676,7 +741,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper( sweepHelper(
clock_type::time_point const& whenExpire, clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now, [[maybe_unused]] clock_type::time_point const& now,
typename KeyValueCacheType::map_type& partition, KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep, SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&) std::scoped_lock<std::recursive_mutex> const&)
@@ -756,7 +821,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper( sweepHelper(
clock_type::time_point const& whenExpire, clock_type::time_point const& whenExpire,
clock_type::time_point const& now, clock_type::time_point const& now,
typename KeyOnlyCacheType::map_type& partition, KeyOnlyCacheType::map_type& partition,
SweptPointersVector&, SweptPointersVector&,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&) std::scoped_lock<std::recursive_mutex> const&)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,8 +4,10 @@
#include <xrpl/beast/insight/Event.h> #include <xrpl/beast/insight/Event.h>
#include <xrpl/beast/insight/Gauge.h> #include <xrpl/beast/insight/Gauge.h>
#include <xrpl/beast/insight/Hook.h> #include <xrpl/beast/insight/Hook.h>
#include <xrpl/beast/insight/HookImpl.h>
#include <xrpl/beast/insight/Meter.h> #include <xrpl/beast/insight/Meter.h>
#include <memory>
#include <string> #include <string>
namespace beast::insight { 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 <xrpl/beast/insight/Collector.h>
#include <memory>
namespace beast::insight { namespace beast::insight {
/** A Collector which does not collect metrics. */ /** A Collector which does not collect metrics. */

View File

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

View File

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

View File

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

View File

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

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