Compare commits

...

26 Commits

Author SHA1 Message Date
Mayukha Vadari
42c93e333e more stuff 2026-07-10 19:56:00 -04:00
Mayukha Vadari
b8b9da92ee add create/destroy helpers 2026-07-10 16:43:52 -04:00
Mayukha Vadari
9d11ba0ca7 migrate 2026-07-10 10:51:08 -04:00
Mayukha Vadari
fb9b10fc03 migrate lending helpers 2026-07-09 22:31:58 -04:00
Mayukha Vadari
628272a11e set up framework 2026-07-09 21:15:57 -04:00
Sergey Kuznetsov
c7adb215ed chore: Add .envrc for automatic devshell switch by direnv (#7756) 2026-07-08 17:28:48 +00:00
Ayaz Salikhov
71ee0f400b chore: Use same compiler in Nix devshell as in CI (#7751) 2026-07-08 14:51:39 +00:00
Ayaz Salikhov
58af1e6f18 release: Bump version to 3.3.0-b1 (#7755) 2026-07-08 12:40:24 +00:00
Ayaz Salikhov
e372c45836 chore: Enable most performance checks (#7727) 2026-07-07 21:03:56 +00:00
Ayaz Salikhov
2ebc96a4a6 perf: Use std::from/to_chars for JSON double parsing/formating (#7735) 2026-07-07 21:02:39 +00:00
Ayaz Salikhov
c5a6de6ef7 chore: Enable most cppcoreguidelines checks (#7660) 2026-07-07 13:12:52 +00:00
Marek Foss
f5e63f8a91 test: Migrate basics Beast tests to GTest (#7136)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-06 19:48:36 +00:00
Marek Foss
7a153a2bce test: Migrate resource, shamap Beast tests to GTest (#7133)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-06 17:26:19 +00:00
Ayaz Salikhov
f59d5c0894 chore: Enable most misc checks (#7663) 2026-07-06 15:22:11 +00:00
Jingchen
bfde271609 chore: Fix unity build (#7730)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-06 15:22:02 +00:00
Ayaz Salikhov
d07d2aba2e chore: Enable most modernize checks (#7664) 2026-07-06 12:19:52 +00:00
Ayaz Salikhov
c92285f10d chore: Delete dead code (#7718) 2026-07-03 15:59:20 +00:00
Ayaz Salikhov
53649cc298 chore: Enable modernize-use-constraints (#7715) 2026-07-03 14:28:15 +00:00
Ayaz Salikhov
f151293e8a chore: Enable modernize-avoid-bind (#7711) 2026-07-03 11:17:03 +00:00
Ayaz Salikhov
7ba1d76d05 chore: Enable modernize-use-auto (#7707) 2026-07-02 20:02:55 +00:00
Bart
3d847f2a60 build: Add protobuf dependencies to Nix (#7706)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-02 18:46:27 +00:00
yinyiqian1
6003fd03fc feat: Enable ConfidentialTransfer and BatchV1_1 (#7698) 2026-07-02 18:37:37 +00:00
Ayaz Salikhov
41622b87ae chore: Enable modernize-unary-static-assert (#7705) 2026-07-02 18:30:59 +00:00
Ayaz Salikhov
6f0f5b8bb3 chore: Make clang-tidy happy on macOS (#7701) 2026-07-02 16:26:09 +00:00
Bart
3b9e24e0e0 chore: Improve pre-commit hooks (#7702)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-02 15:01:30 +00:00
Timothy Banks
4c619e8a85 refactor: Retire DisallowIncomingV1 fix (#7364) 2026-07-02 14:17:32 +00:00
332 changed files with 9212 additions and 8728 deletions

View File

@@ -9,101 +9,48 @@ Checks: "-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-capturing-lambda-coroutines,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-avoid-reference-coroutine-parameters,
-cppcoreguidelines-c-copy-assignment-signature,
-cppcoreguidelines-explicit-virtual-functions,
-cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-macro-to-enum,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-missing-std-forward,
-cppcoreguidelines-narrowing-conversions,
-cppcoreguidelines-no-malloc,
-cppcoreguidelines-noexcept-destructor,
-cppcoreguidelines-noexcept-move-operations,
-cppcoreguidelines-noexcept-swap,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-prefer-member-initializer,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-slicing,
-cppcoreguidelines-special-member-functions,
llvm-namespace-comment,
misc-*,
-misc-anonymous-namespace-in-header,
-misc-confusable-identifiers,
-misc-coroutine-hostile-raii,
-misc-misleading-bidirectional,
-misc-misleading-identifier,
-misc-multiple-inheritance,
-misc-new-delete-overloads,
-misc-no-recursion,
-misc-non-copyable-objects,
-misc-non-private-member-variables-in-classes,
-misc-override-with-different-visibility,
-misc-predictable-rand,
-misc-unconventional-assign-operator,
-misc-uniqueptr-reset-release,
-misc-unused-parameters,
-misc-use-anonymous-namespace,
-misc-use-internal-linkage,
modernize-*,
-modernize-avoid-bind,
-modernize-avoid-c-arrays,
-modernize-avoid-c-style-cast,
-modernize-avoid-setjmp-longjmp,
-modernize-avoid-variadic-functions,
-modernize-deprecated-ios-base-aliases,
-modernize-loop-convert,
-modernize-macro-to-enum,
-modernize-min-max-use-initializer-list,
-modernize-raw-string-literal,
-modernize-redundant-void-arg,
-modernize-replace-auto-ptr,
-modernize-replace-disallow-copy-and-assign-macro,
-modernize-replace-random-shuffle,
-modernize-return-braced-init-list,
-modernize-shrink-to-fit,
-modernize-unary-static-assert,
-modernize-use-auto,
-modernize-use-bool-literals,
-modernize-use-constraints,
-modernize-use-default-member-init,
-modernize-use-integer-sign-comparison,
-modernize-use-noexcept,
-modernize-use-nullptr,
-modernize-use-std-format,
-modernize-use-std-print,
-modernize-use-trailing-return-type,
-modernize-use-transparent-functors,
-modernize-use-uncaught-exceptions,
performance-*,
-performance-avoid-endl,
-performance-enum-size,
-performance-inefficient-algorithm,
-performance-inefficient-string-concatenation,
-performance-no-int-to-ptr,
-performance-noexcept-destructor,
-performance-noexcept-move-constructor,
-performance-noexcept-swap,
-performance-type-promotion-in-math-fn,
-performance-unnecessary-copy-initialization,
-performance-unnecessary-value-param,

View File

@@ -36,9 +36,7 @@ overrides:
- /'[^']*'/g # single-quoted strings
- /`[^`]*`/g # backtick strings
suggestWords:
- xprl->xrpl
- xprld->xrpld # cspell: disable-line not sure what this problem is....
- unsynched->unsynced # cspell: disable-line not sure what this problem is....
- unsynched->unsynced
- synched->synced
- synch->sync
words:
@@ -281,6 +279,7 @@ words:
- sles
- soci
- socidb
- sponsee
- SRPMS
- sslws
- statsd
@@ -329,6 +328,7 @@ words:
- unserviced
- unshareable
- unshares
- unsponsored
- unsquelch
- unsquelched
- unsquelching

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

View File

@@ -72,7 +72,6 @@ test.app > xrpl.server
test.app > xrpl.shamap
test.app > xrpl.tx
test.basics > test.jtx
test.basics > test.unit_test
test.basics > xrpl.basics
test.basics > xrpl.core
test.basics > xrpld.rpc
@@ -162,9 +161,6 @@ test.protocol > test.unit_test
test.protocol > xrpl.basics
test.protocol > xrpl.json
test.protocol > xrpl.protocol
test.resource > test.unit_test
test.resource > xrpl.basics
test.resource > xrpl.resource
test.rpc > test.jtx
test.rpc > xrpl.basics
test.rpc > xrpl.config
@@ -188,12 +184,6 @@ test.server > xrpld.core
test.server > xrpl.json
test.server > xrpl.protocol
test.server > xrpl.server
test.shamap > test.unit_test
test.shamap > xrpl.basics
test.shamap > xrpl.config
test.shamap > xrpl.nodestore
test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
@@ -205,6 +195,7 @@ tests.libxrpl > xrpl.net
tests.libxrpl > xrpl.nodestore
tests.libxrpl > xrpl.protocol
tests.libxrpl > xrpl.protocol_autogen
tests.libxrpl > xrpl.resource
tests.libxrpl > xrpl.server
tests.libxrpl > xrpl.shamap
tests.libxrpl > xrpl.tx

View File

@@ -90,20 +90,19 @@ repos:
- repo: https://github.com/streetsidesoftware/cspell-cli
rev: ea11f9efc0bec520073405bc30552da887ba71bc # frozen: v10.0.1
hooks:
- id: cspell # Spell check changed files
- id: cspell
name: check changed files spelling
exclude: |
(?x)^(
.config/cspell.config.yaml|
\.cspell\.config\.yaml|
include/xrpl/protocol_autogen/(transactions|ledger_entries)/.*
)$
- id: cspell # Spell check the commit message
- id: cspell
name: check commit message spelling
args:
- --no-must-find-files
- --no-progress
- --no-summary
- --files
- .git/COMMIT_EDITMSG
stages: [commit-msg]
- repo: local

View File

@@ -25,7 +25,7 @@ You can verify that the required tools are installed and runnable with:
| ----------- | --------------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| Apple Clang | 21 |
| MSVC | 19.44[^windows] |
## Operating Systems

View File

@@ -17,9 +17,11 @@ import subprocess
import sys
from pathlib import Path
CLANG_TIDY_VERSION = 22
def find_run_clang_tidy() -> str | None:
for candidate in ("run-clang-tidy-21", "run-clang-tidy"):
for candidate in (f"run-clang-tidy-{CLANG_TIDY_VERSION}", "run-clang-tidy"):
if path := shutil.which(candidate):
return path
return None
@@ -44,8 +46,8 @@ def main():
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.",
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

View File

@@ -33,9 +33,10 @@ with a single command and without installing anything system-wide:
nix --experimental-features 'nix-command flakes' develop
```
On **Linux**, Nix also provides the compiler (GCC). On **macOS**, the shell uses
your **system-wide Apple Clang** as the compiler, so you still need to manage
its version (see below).
On **Linux**, Nix also provides the compiler (GCC); on **macOS**, it provides
Clang. If you instead opt to use your system-wide Apple Clang (via
`nix develop .#apple-clang`), you need to manage its version yourself (see
below).
See [Using the Nix development shell](./nix.md) for installation and usage
details, including how to select a different compiler.
@@ -48,10 +49,10 @@ details, including how to select a different compiler.
### macOS: managing the Apple Clang version
Because the Nix shell uses the system-wide Apple Clang on macOS, the compiler
version is whatever your installed Xcode (or Command Line Tools) provides. The
following command should return a version greater than or equal to the
[minimum required](#tested-compiler-versions):
If you use your system-wide Apple Clang on macOS (via `nix develop .#apple-clang`),
the compiler version is whatever your installed Xcode (or Command Line Tools)
provides. The following command should return a version greater than or equal to
the [minimum required](#tested-compiler-versions):
```bash
clang --version

40
docs/build/nix.md vendored
View File

@@ -9,7 +9,7 @@ This guide explains how to use Nix to set up a reproducible development environm
- **Reproducible environment**: Everyone gets the same versions of tools and compilers
- **Matches CI**: The Linux CI runs in Docker images built from this exact Nix environment
- **No system pollution**: Dependencies are isolated and don't affect your system packages
- **Multiple compiler versions**: Easily switch between different GCC and Clang versions
- **Consistent compilers**: The GCC and Clang shells use the same versions as CI
- **Quick setup**: Get started with a single command
- **Works on Linux and macOS**: Consistent experience across platforms
@@ -31,8 +31,8 @@ This will:
- Download and set up all required development tools (CMake, Ninja, Conan, etc.)
- Configure the appropriate compiler for your platform:
- **Linux**: GCC 15.2 (provided by Nix)
- **macOS**: Apple Clang (your system compiler)
- **Linux**: GCC (provided by Nix)
- **macOS**: Clang (provided by Nix)
The first time you run this command, it will take a few minutes to download and build the environment. Subsequent runs will be much faster.
@@ -40,12 +40,12 @@ The first time you run this command, it will take a few minutes to download and
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
- **macOS**: `nix develop` gives you a full environment too. The compiler is
your system-wide Apple Clang, while every other tool including Conan — is
provided by Nix. Conan has no binary in the Nix cache for macOS, so it is
built from source the first time you enter the shell, which makes the initial
setup slower (this is handled automatically; see
[`nix/devshell.nix`](../../nix/devshell.nix)).
- **macOS**: `nix develop` gives you a full environment too, with Clang (and
every other tool, including Conan) provided by Nix. To use your system-wide
Apple Clang instead, enter `nix develop .#apple-clang`. Conan has no binary in
the Nix cache for macOS, so it is built from source the first time you enter
the shell, which makes the initial setup slower (this is handled
automatically; see [`nix/devshell.nix`](../../nix/devshell.nix)).
> [!TIP]
> To avoid typing `--experimental-features 'nix-command flakes'` every time, you can permanently enable flakes by creating `~/.config/nix/nix.conf`:
@@ -62,7 +62,9 @@ The first time you run this command, it will take a few minutes to download and
### Choosing a different compiler
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#gcc15`.
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#clang`.
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no-compiler` to use the compiler from your system.
@@ -70,11 +72,11 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC 14
nix develop .#gcc14
# Use GCC (same version as CI)
nix develop .#gcc
# Use Clang 19
nix develop .#clang19
# Use Clang (same version as CI)
nix develop .#clang
# Use default for your platform
nix develop
@@ -112,7 +114,15 @@ Once inside the Nix development shell, follow the standard [build instructions](
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`. To use it, install direnv for your shell, then add an `.envrc` containing `use flake` at the repository root and run `direnv allow`.
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`.
The repository already ships an `.envrc` at its root that activates the Nix flake development shell, so you don't need to create one. To use it:
1. [Install direnv](https://direnv.net/docs/installation.html) and [hook it into your shell](https://direnv.net/docs/hook.html) (bash, zsh, fish, …). Installing [nix-direnv](https://github.com/nix-community/nix-direnv) as well is recommended: it caches the shell so that activation is near-instant after the first run.
2. Run `direnv allow` once in the repository root. direnv will then load (and reload) the Nix development shell automatically whenever you enter the directory.
> [!NOTE]
> direnv only caches the `.direnv` directory (already listed in `.gitignore`); no other repository files are affected.
## Conan and Prebuilt Packages

View File

@@ -641,6 +641,9 @@ template <class T>
T*
SharedWeakUnion<T>::unsafeGetRawPtr() const
{
// tp_ packs a raw pointer together with a strength bit; recovering the
// pointer inherently requires an integer-to-pointer cast.
// NOLINTNEXTLINE(performance-no-int-to-ptr)
return reinterpret_cast<T*>(tp_ & kPtrMask);
}

View File

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

View File

@@ -212,11 +212,13 @@ public:
*/
template <class ReturnType = bool>
auto
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>;
insert(key_type const& key, T const& value) -> ReturnType
requires(!IsKeyCache);
template <class ReturnType = bool>
auto
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>;
insert(key_type const& key) -> ReturnType
requires IsKeyCache;
// VFALCO NOTE It looks like this returns a copy of the data in
// the output parameter 'data'. This could be expensive.

View File

@@ -57,7 +57,10 @@ inline TaggedCache<
beast::insight::Collector::ptr const& collector)
: journal_(journal)
, clock_(clock)
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
, stats_(
name,
[this] { collectMetrics(); },
collector)
, name_(name)
, targetSize_(size)
, targetAge_(expiration)
@@ -500,7 +503,8 @@ template <
template <class ReturnType>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>
insert(key_type const& key, T const& value) -> ReturnType
requires(!IsKeyCache)
{
static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
@@ -530,7 +534,8 @@ template <
template <class ReturnType>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>
insert(key_type const& key) -> ReturnType
requires IsKeyCache
{
std::scoped_lock const lock(mutex_);
clock_type::time_point const now(clock_.now());

View File

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

View File

@@ -97,7 +97,7 @@ public:
//
static constexpr std::size_t kBytes = Bits / 8;
static_assert(sizeof(data_) == kBytes, "");
static_assert(sizeof(data_) == kBytes);
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
@@ -280,12 +280,11 @@ public:
{
}
template <
class Container,
class = std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>>>
template <class Container>
explicit BaseUInt(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
// Use AlwaysFalseT so the static_assert condition is dependent
// and only triggers when this constructor template is instantiated.
@@ -295,13 +294,12 @@ public:
"Use base_uint::fromRaw instead.");
}
template <
class Container,
class = std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>>>
template <class Container>
static BaseUInt
fromRaw(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
BaseUInt result;
XRPL_ASSERT(
@@ -312,11 +310,11 @@ public:
}
template <class Container>
std::enable_if_t<
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>,
BaseUInt&>
BaseUInt&
operator=(Container const& c)
requires(
detail::IsContiguousContainer<Container>::value &&
std::is_trivially_copyable_v<typename Container::value_type>)
{
XRPL_ASSERT(
c.size() * sizeof(typename Container::value_type) == size(),

View File

@@ -1,54 +0,0 @@
#pragma once
#include <functional>
namespace xrpl {
#ifdef _MSC_VER
/*
* MSVC 2019 version 16.9.0 added [[nodiscard]] to the std comparison
* operator() functions. boost::bimap checks that the comparator is a
* BinaryFunction, in part by calling the function and ignoring the value.
* These two things don't play well together. These wrapper classes simply
* strip [[nodiscard]] from operator() for use in boost::bimap.
*
* See also:
* https://www.boost.org/doc/libs/1_75_0/libs/bimap/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html
*/
template <class T = void>
struct less
{
using result_type = bool;
constexpr bool
operator()(T const& left, T const& right) const
{
return std::less<T>()(left, right);
}
};
template <class T = void>
struct equal_to
{
using result_type = bool;
constexpr bool
operator()(T const& left, T const& right) const
{
return std::equal_to<T>()(left, right);
}
};
#else
template <class T = void>
using less = std::less<T>;
template <class T = void>
using equal_to = std::equal_to<T>;
#endif
} // namespace xrpl

View File

@@ -138,11 +138,8 @@ public:
{
}
ConstIterator(Iterator const& orig)
ConstIterator(Iterator const& orig) : map(orig.map), ait(orig.ait), mit(orig.mit)
{
map = orig.map;
ait = orig.ait;
mit = orig.mit;
}
const_reference
@@ -231,11 +228,11 @@ private:
public:
PartitionedUnorderedMap(std::optional<std::size_t> partitions = std::nullopt)
{
// Set partitions to the number of hardware threads if the parameter
// is either empty or set to 0.
partitions_ =
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency();
: partitions_(
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency())
{
map_.resize(partitions_);
XRPL_ASSERT(
partitions_,

View File

@@ -91,8 +91,9 @@ defaultPrng()
*/
/** @{ */
template <class Engine, class Integral>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine, Integral min, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
XRPL_ASSERT(max > min, "xrpl::randInt : max over min inputs");
@@ -103,36 +104,41 @@ randInt(Engine& engine, Integral min, Integral max)
}
template <class Integral>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt(Integral min, Integral max)
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), min, max);
}
template <class Engine, class Integral>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
return randInt(engine, Integral(0), max);
}
template <class Integral>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt(Integral max)
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), max);
}
template <class Integral, class Engine>
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
Integral
randInt(Engine& engine)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
{
return randInt(engine, std::numeric_limits<Integral>::max());
}
template <class Integral = int>
std::enable_if_t<std::is_integral_v<Integral>, Integral>
Integral
randInt()
requires(std::is_integral_v<Integral>)
{
return randInt(defaultPrng(), std::numeric_limits<Integral>::max());
}
@@ -141,19 +147,20 @@ randInt()
/** Return a random byte */
/** @{ */
template <class Byte, class Engine>
std::enable_if_t<
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
detail::is_engine<Engine>::value,
Byte>
Byte
randByte(Engine& engine)
requires(
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
detail::is_engine<Engine>::value)
{
return static_cast<Byte>(randInt<Engine, std::uint32_t>(
engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
}
template <class Byte = std::uint8_t>
std::enable_if_t<(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>), Byte>
Byte
randByte()
requires(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>)
{
return randByte<Byte>(defaultPrng());
}

View File

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

View File

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

View File

@@ -43,10 +43,10 @@ public:
TaggedInteger() = default;
template <
class OtherInt,
class = std::enable_if_t<std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int)>>
explicit constexpr TaggedInteger(OtherInt value) noexcept : value_(value)
template <class OtherInt>
explicit constexpr TaggedInteger(OtherInt value) noexcept
requires(std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int))
: value_(value)
{
static_assert(sizeof(TaggedInteger) == sizeof(Int), "tagged_integer is adding padding");
}

View File

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

View File

@@ -30,20 +30,19 @@ public:
// Disable constructing a const_iterator from a non-const_iterator.
// Converting between reverse and non-reverse iterators should be explicit.
template <
bool OtherIsConst,
class OtherIterator,
class = std::enable_if_t<
(!OtherIsConst || IsConst) &&
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>)>>
template <bool OtherIsConst, class OtherIterator>
explicit AgedContainerIterator(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
requires(
(!OtherIsConst || IsConst) &&
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>))
: iter_(other.iter_)
{
}
// Disable constructing a const_iterator from a non-const_iterator.
template <bool OtherIsConst, class = std::enable_if_t<!OtherIsConst || IsConst>>
template <bool OtherIsConst>
AgedContainerIterator(AgedContainerIterator<OtherIsConst, Iterator> const& other)
requires(!OtherIsConst || IsConst)
: iter_(other.iter_)
{
}
@@ -52,7 +51,8 @@ public:
template <bool OtherIsConst, class OtherIterator>
auto
operator=(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
-> std::enable_if_t<!OtherIsConst || IsConst, AgedContainerIterator&>
-> AgedContainerIterator&
requires(!OtherIsConst || IsConst)
{
iter_ = other.iter_;
return *this;

View File

@@ -111,10 +111,9 @@ private:
{
}
template <
class... Args,
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
template <class... Args>
Element(time_point const& when, Args&&... args)
requires(std::is_constructible_v<value_type, Args...>)
: value(std::forward<Args>(args)...), when(when)
{
}
@@ -360,6 +359,7 @@ private:
deleteElement(Element const* p)
{
ElementAllocatorTraits::destroy(config_.alloc(), p);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
}
@@ -608,35 +608,25 @@ public:
//
//--------------------------------------------------------------------------
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
at(K const& k);
at(K const& k)
requires(MaybeMap && !MaybeMulti);
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
at(K const& k) const
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key const& key);
operator[](Key const& key)
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key&& key);
operator[](Key&& key)
requires(MaybeMap && !MaybeMulti);
//--------------------------------------------------------------------------
//
@@ -770,35 +760,40 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insert(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insert(value_type const& value) -> iterator
requires MaybeMulti;
// set
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
insert(value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap);
// multiset
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
insert(value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap);
//---
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(const_iterator hint, value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>;
insert(const_iterator hint, value_type const& value) -> iterator
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert(value);
@@ -807,12 +802,14 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(const_iterator hint, value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>;
insert(const_iterator hint, value_type&& value) -> iterator
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert(std::move(value));
@@ -820,20 +817,18 @@ public:
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplace(std::forward<P>(value));
}
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -855,46 +850,45 @@ public:
// map, set
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplace(Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
emplace(Args&&... args) -> iterator
requires MaybeMulti;
// map, set
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplaceHint(const_iterator hint, Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplaceHint(const_iterator hint, Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
std::enable_if_t<MaybeMulti, iterator>
iterator
emplaceHint(const_iterator /*hint*/, Args&&... args)
requires MaybeMulti
{
// VFALCO TODO Figure out how to utilize 'hint'
return emplace<MaybeMulti>(std::forward<Args>(args)...);
}
// enable_if prevents erase (reverse_iterator pos) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents erase (reverse_iterator pos) from compiling
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos);
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value);
// enable_if prevents erase (reverse_iterator first, reverse_iterator last)
// The constraint prevents erase (reverse_iterator first, reverse_iterator last)
// from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
beast::detail::AgedContainerIterator<IsConst, Iterator> last);
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
requires(!IsBoostReverseIterator<Iterator>::value);
template <class K>
auto
@@ -905,13 +899,11 @@ public:
//--------------------------------------------------------------------------
// enable_if prevents touch (reverse_iterator pos) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents touch (reverse_iterator pos) from compiling
template <bool IsConst, class Iterator>
void
touch(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value)
{
touch(pos, clock().now());
}
@@ -1142,25 +1134,25 @@ public:
}
private:
// enable_if prevents erase (reverse_iterator pos, now) from compiling
template <
bool IsConst,
class Iterator,
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
// The constraint prevents erase (reverse_iterator pos, now) from compiling
template <bool IsConst, class Iterator>
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now);
clock_type::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value);
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<MaybePropagate>
swapData(AgedOrderedContainer& other) noexcept;
void
swapData(AgedOrderedContainer& other) noexcept
requires MaybePropagate;
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<!MaybePropagate>
swapData(AgedOrderedContainer& other) noexcept;
void
swapData(AgedOrderedContainer& other) noexcept
requires(!MaybePropagate);
private:
ConfigT config_;
@@ -1369,9 +1361,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k)
requires(MaybeMap && !MaybeMulti)
{
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
if (iter == cont_.end())
@@ -1380,9 +1373,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional<IsMap, T, void*>::type const&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k) const
requires(MaybeMap && !MaybeMulti)
{
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
if (iter == cont_.end())
@@ -1391,9 +1385,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key const& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
@@ -1409,9 +1404,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key&& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
@@ -1445,7 +1441,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
@@ -1464,7 +1461,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
Element* const p(newElement(value));
@@ -1478,7 +1476,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, bool MaybeMap>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
-> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
@@ -1497,7 +1496,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, bool MaybeMap>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
-> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
-> iterator
requires(MaybeMulti && !MaybeMap)
{
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
Element* const p(newElement(std::move(value)));
@@ -1514,7 +1514,8 @@ template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
const_iterator hint,
value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>
value_type const& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(
@@ -1535,7 +1536,8 @@ template <bool MaybeMulti>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
const_iterator hint,
value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>
value_type&& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(
@@ -1555,7 +1557,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
-> std::pair<iterator, bool>
requires(!MaybeMulti)
{
// VFALCO NOTE Its unfortunate that we need to
// construct element here
@@ -1577,7 +1580,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
-> std::enable_if_t<MaybeMulti, iterator>
-> iterator
requires MaybeMulti
{
Element* const p(newElement(std::forward<Args>(args)...));
auto const before(cont_.upper_bound(extract(p->value), std::cref(config_.keyCompare())));
@@ -1592,7 +1596,8 @@ template <bool MaybeMulti, class... Args>
auto
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplaceHint(
const_iterator hint,
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
// VFALCO NOTE Its unfortunate that we need to
// construct element here
@@ -1611,21 +1616,23 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value)
{
unlinkAndDeleteElement(&*((pos++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator());
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
beast::detail::AgedContainerIterator<false, Iterator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
requires(!IsBoostReverseIterator<Iterator>::value)
{
for (; first != last;)
unlinkAndDeleteElement(&*((first++).iterator()));
@@ -1728,11 +1735,12 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool IsConst, class Iterator, class>
template <bool IsConst, class Iterator>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value)
{
auto& e(*pos.iterator());
e.when = now;
@@ -1742,9 +1750,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybePropagate>
std::enable_if_t<MaybePropagate>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
AgedOrderedContainer& other) noexcept
requires MaybePropagate
{
std::swap(config_.keyCompare(), other.config_.keyCompare());
std::swap(config_.alloc(), other.config_.alloc());
@@ -1753,9 +1762,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapDat
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool MaybePropagate>
std::enable_if_t<!MaybePropagate>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
AgedOrderedContainer& other) noexcept
requires(!MaybePropagate)
{
std::swap(config_.keyCompare(), other.config_.keyCompare());
std::swap(config_.clock, other.config_.clock);

View File

@@ -117,10 +117,9 @@ private:
{
}
template <
class... Args,
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
template <class... Args>
Element(time_point const& when, Args&&... args)
requires(std::is_constructible_v<value_type, Args...>)
: value(std::forward<Args>(args)...), when(when)
{
}
@@ -529,6 +528,7 @@ private:
deleteElement(Element const* p)
{
ElementAllocatorTraits::destroy(config_.alloc(), p);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
}
@@ -841,35 +841,25 @@ public:
//
//--------------------------------------------------------------------------
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
at(K const& k);
at(K const& k)
requires(MaybeMap && !MaybeMulti);
template <
class K,
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
at(K const& k) const
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key const& key);
operator[](Key const& key)
requires(MaybeMap && !MaybeMulti);
template <
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
std::conditional_t<IsMap, T, void*>&
operator[](Key&& key);
operator[](Key&& key)
requires(MaybeMap && !MaybeMulti);
//--------------------------------------------------------------------------
//
@@ -967,28 +957,32 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insert(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insert(value_type const& value) -> iterator
requires MaybeMulti;
// map, set
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value)
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
insert(value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap);
// multimap, multiset
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
auto
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
insert(value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap);
// map, set
template <bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires(!MaybeMulti)
{
// Hint is ignored but we provide the interface so
// callers may use ordered and unordered interchangeably.
@@ -997,8 +991,9 @@ public:
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type const& value)
requires MaybeMulti
{
// VFALCO TODO The hint could be used to let
// the client order equal ranges
@@ -1007,8 +1002,9 @@ public:
// map, set
template <bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires(!MaybeMulti)
{
// Hint is ignored but we provide the interface so
// callers may use ordered and unordered interchangeably.
@@ -1017,8 +1013,9 @@ public:
// multimap, multiset
template <bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, iterator>
iterator
insert(const_iterator /*hint*/, value_type&& value)
requires MaybeMulti
{
// VFALCO TODO The hint could be used to let
// the client order equal ranges
@@ -1027,20 +1024,18 @@ public:
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplace(std::forward<P>(value));
}
// map, multimap
template <class P, bool MaybeMap = IsMap>
std::enable_if_t<
MaybeMap && std::is_constructible_v<value_type, P&&>,
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -1061,23 +1056,26 @@ public:
// set, map
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplace(Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
emplace(Args&&... args) -> iterator
requires MaybeMulti;
// set, map
template <bool MaybeMulti = IsMulti, class... Args>
auto
emplaceHint(const_iterator /*hint*/, Args&&... args)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
emplaceHint(const_iterator /*hint*/, Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multiset, multimap
template <bool MaybeMulti = IsMulti, class... Args>
std::enable_if_t<MaybeMulti, iterator>
iterator
emplaceHint(const_iterator /*hint*/, Args&&... args)
requires MaybeMulti
{
// VFALCO TODO The hint could be used for multi, to let
// the client order equal ranges
@@ -1308,7 +1306,7 @@ public:
class OtherHash,
class OtherAllocator,
bool MaybeMulti = IsMulti>
std::enable_if_t<!MaybeMulti, bool>
bool
operator==(AgedUnorderedContainer<
false,
OtherIsMap,
@@ -1317,7 +1315,8 @@ public:
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const;
OtherAllocator> const& other) const
requires(!MaybeMulti);
template <
bool OtherIsMap,
@@ -1327,7 +1326,7 @@ public:
class OtherHash,
class OtherAllocator,
bool MaybeMulti = IsMulti>
std::enable_if_t<MaybeMulti, bool>
bool
operator==(AgedUnorderedContainer<
true,
OtherIsMap,
@@ -1336,7 +1335,8 @@ public:
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const;
OtherAllocator> const& other) const
requires MaybeMulti;
template <
bool OtherIsMulti,
@@ -1381,13 +1381,14 @@ private:
// map, set
template <bool MaybeMulti = IsMulti>
auto
insertUnchecked(value_type const& value)
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
insertUnchecked(value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti);
// multimap, multiset
template <bool MaybeMulti = IsMulti>
auto
insertUnchecked(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
insertUnchecked(value_type const& value) -> iterator
requires MaybeMulti;
template <class InputIt>
void
@@ -1428,8 +1429,9 @@ private:
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<MaybePropagate>
void
swapData(AgedUnorderedContainer& other) noexcept
requires MaybePropagate
{
std::swap(config_.hashFunction(), other.config_.hashFunction());
std::swap(config_.keyEq(), other.config_.keyEq());
@@ -1439,8 +1441,9 @@ private:
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
std::enable_if_t<!MaybePropagate>
void
swapData(AgedUnorderedContainer& other) noexcept
requires(!MaybePropagate)
{
std::swap(config_.hashFunction(), other.config_.hashFunction());
std::swap(config_.keyEq(), other.config_.keyEq());
@@ -2094,9 +2097,10 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(K const& k)
requires(MaybeMap && !MaybeMulti)
{
auto const iter(
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
@@ -2114,10 +2118,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
template <class K, bool MaybeMulti, bool MaybeMap>
std::conditional<IsMap, T, void*>::type const&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(
K const& k) const
requires(MaybeMap && !MaybeMulti)
{
auto const iter(
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
@@ -2135,10 +2140,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
Key const& key)
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2164,10 +2170,11 @@ template <
class Hash,
class KeyEqual,
class Allocator>
template <bool MaybeMulti, bool MaybeMap, class>
template <bool MaybeMulti, bool MaybeMap>
std::conditional_t<IsMap, T, void*>&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
Key&& key)
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2220,7 +2227,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2249,7 +2257,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
maybeRehash(1);
Element* const p(newElement(value));
@@ -2271,7 +2280,8 @@ template <
template <bool MaybeMulti, bool MaybeMap>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type&& value) -> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
value_type&& value) -> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
@@ -2300,7 +2310,8 @@ template <
template <bool MaybeMulti, bool MaybeMap>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
value_type&& value) -> iterator
requires(MaybeMulti && !MaybeMap)
{
maybeRehash(1);
Element* const p(newElement(std::move(value)));
@@ -2309,7 +2320,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
return iterator(iter);
}
#if 1 // Use insert() instead of insert_check() insert_commit()
// set, map
template <
bool IsMulti,
@@ -2323,7 +2333,8 @@ template <
template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
// VFALCO NOTE Its unfortunate that we need to
@@ -2338,42 +2349,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
deleteElement(p);
return std::make_pair(iterator(result.first), false);
}
#else // As original, use insert_check() / insert_commit () pair.
// set, map
template <
bool IsMulti,
bool IsMap,
class Key,
class T,
class Clock,
class Hash,
class KeyEqual,
class Allocator>
template <bool maybe_multi, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
{
maybe_rehash(1);
// VFALCO NOTE Its unfortunate that we need to
// construct element here
element* const p(new_element(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(
extract(p->value),
std::cref(m_config.hashFunction()),
std::cref(m_config.keyValueEqual()),
d));
if (result.second)
{
auto const iter(m_cont.insert_commit(*p, d));
chronological.list.push_back(*p);
return std::make_pair(iterator(iter), true);
}
delete_element(p);
return std::make_pair(iterator(result.first), false);
}
#endif // 0
// multiset, multimap
template <
@@ -2388,7 +2363,8 @@ template <
template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>
Args&&... args) -> iterator
requires MaybeMulti
{
maybeRehash(1);
Element* const p(newElement(std::forward<Args>(args)...));
@@ -2411,7 +2387,8 @@ template <bool MaybeMulti, class... Args>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplaceHint(
const_iterator /*hint*/,
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
Args&&... args) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
maybeRehash(1);
// VFALCO NOTE Its unfortunate that we need to
@@ -2562,7 +2539,7 @@ template <
class OtherHash,
class OtherAllocator,
bool MaybeMulti>
std::enable_if_t<!MaybeMulti, bool>
bool
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
AgedUnorderedContainer<
false,
@@ -2573,6 +2550,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
requires(!MaybeMulti)
{
if (size() != other.size())
return false;
@@ -2602,7 +2580,7 @@ template <
class OtherHash,
class OtherAllocator,
bool MaybeMulti>
std::enable_if_t<MaybeMulti, bool>
bool
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
AgedUnorderedContainer<
true,
@@ -2613,6 +2591,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
requires MaybeMulti
{
if (size() != other.size())
return false;
@@ -2649,7 +2628,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
auto const result(cont_.insert_check(
@@ -2677,7 +2657,8 @@ template <
template <bool MaybeMulti>
auto
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
value_type const& value) -> iterator
requires MaybeMulti
{
Element* const p(newElement(value));
chronological.list_.push_back(*p);

View File

@@ -29,16 +29,18 @@ struct LexicalCast<std::string, In>
explicit LexicalCast() = default;
template <class Arithmetic = In>
std::enable_if_t<std::is_arithmetic_v<Arithmetic>, bool>
bool
operator()(std::string& out, Arithmetic in)
requires(std::is_arithmetic_v<Arithmetic>)
{
out = std::to_string(in);
return true;
}
template <class Enumeration = In>
std::enable_if_t<std::is_enum_v<Enumeration>, bool>
bool
operator()(std::string& out, Enumeration in)
requires(std::is_enum_v<Enumeration>)
{
out = std::to_string(static_cast<std::underlying_type_t<Enumeration>>(in));
return true;
@@ -56,8 +58,9 @@ struct LexicalCast<Out, std::string_view>
"beast::LexicalCast can only be used with integral types");
template <class Integral = Out>
std::enable_if_t<std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>, bool>
bool
operator()(Integral& out, std::string_view in) const
requires(std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>)
{
auto first = in.data();
auto last = in.data() + in.size();

View File

@@ -41,7 +41,7 @@ public:
operator=(NodePtr node)
{
node_ = node;
return static_cast<LockFreeStackIterator&>(*this);
return *this;
}
LockFreeStackIterator&

View File

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

View File

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

View File

@@ -49,6 +49,11 @@ public:
impl_->set(value);
}
// This is a write-through handle: assignment sets the value of the
// referenced metric. It is const-qualified and returns Gauge const&
// (a non-const Gauge& would require a const_cast), so it does not follow
// the conventional assignment-operator signature.
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
Gauge const&
operator=(value_type value) const
{

View File

@@ -23,6 +23,7 @@ typeName()
if (auto s = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr))
{
name = s;
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
std::free(s);
}
#endif

View File

@@ -10,9 +10,9 @@
#include <boost/assert.hpp>
#include <set>
#include <string>
#include <typeindex>
#include <unordered_set>
#include <string> // IWYU pragma: keep
#include <typeindex> // IWYU pragma: keep
#include <unordered_set> // IWYU pragma: keep
namespace beast::unit_test {

View File

@@ -45,7 +45,10 @@ public:
template <class F, class... Args>
explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s)
{
std::function<void(void)> b = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
std::function<void(void)> b = [f = std::forward<F>(f),
... args = std::forward<Args>(args)]() mutable {
std::invoke(f, args...);
};
t_ = std::thread(&Thread::run, this, std::move(b));
}

View File

@@ -108,12 +108,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(!std::is_default_constructible_v<Sink>, "");
static_assert(!std::is_copy_constructible_v<Sink>, "");
static_assert(!std::is_move_constructible_v<Sink>, "");
static_assert(!std::is_copy_assignable_v<Sink>, "");
static_assert(!std::is_move_assignable_v<Sink>, "");
static_assert(std::is_nothrow_destructible_v<Sink>, "");
static_assert(!std::is_default_constructible_v<Sink>);
static_assert(!std::is_copy_constructible_v<Sink>);
static_assert(!std::is_move_constructible_v<Sink>);
static_assert(!std::is_copy_assignable_v<Sink>);
static_assert(!std::is_move_assignable_v<Sink>);
static_assert(std::is_nothrow_destructible_v<Sink>);
#endif
/** Returns a Sink which does nothing. */
@@ -164,12 +164,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(!std::is_default_constructible_v<ScopedStream>, "");
static_assert(std::is_copy_constructible_v<ScopedStream>, "");
static_assert(std::is_move_constructible_v<ScopedStream>, "");
static_assert(!std::is_copy_assignable_v<ScopedStream>, "");
static_assert(!std::is_move_assignable_v<ScopedStream>, "");
static_assert(std::is_nothrow_destructible_v<ScopedStream>, "");
static_assert(!std::is_default_constructible_v<ScopedStream>);
static_assert(std::is_copy_constructible_v<ScopedStream>);
static_assert(std::is_move_constructible_v<ScopedStream>);
static_assert(!std::is_copy_assignable_v<ScopedStream>);
static_assert(!std::is_move_assignable_v<ScopedStream>);
static_assert(std::is_nothrow_destructible_v<ScopedStream>);
#endif
//--------------------------------------------------------------------------
@@ -246,12 +246,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(std::is_default_constructible_v<Stream>, "");
static_assert(std::is_copy_constructible_v<Stream>, "");
static_assert(std::is_move_constructible_v<Stream>, "");
static_assert(!std::is_copy_assignable_v<Stream>, "");
static_assert(!std::is_move_assignable_v<Stream>, "");
static_assert(std::is_nothrow_destructible_v<Stream>, "");
static_assert(std::is_default_constructible_v<Stream>);
static_assert(std::is_copy_constructible_v<Stream>);
static_assert(std::is_move_constructible_v<Stream>);
static_assert(!std::is_copy_assignable_v<Stream>);
static_assert(!std::is_move_assignable_v<Stream>);
static_assert(std::is_nothrow_destructible_v<Stream>);
#endif
//--------------------------------------------------------------------------
@@ -329,12 +329,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(!std::is_default_constructible_v<Journal>, "");
static_assert(std::is_copy_constructible_v<Journal>, "");
static_assert(std::is_move_constructible_v<Journal>, "");
static_assert(std::is_copy_assignable_v<Journal>, "");
static_assert(std::is_move_assignable_v<Journal>, "");
static_assert(std::is_nothrow_destructible_v<Journal>, "");
static_assert(!std::is_default_constructible_v<Journal>);
static_assert(std::is_copy_constructible_v<Journal>);
static_assert(std::is_move_constructible_v<Journal>);
static_assert(std::is_copy_assignable_v<Journal>);
static_assert(std::is_move_assignable_v<Journal>);
static_assert(std::is_nothrow_destructible_v<Journal>);
#endif
//------------------------------------------------------------------------------

View File

@@ -26,9 +26,7 @@ struct Zero
explicit Zero() = default;
};
namespace {
constexpr Zero kZero{};
} // namespace
inline constexpr Zero kZero{};
/** Default implementation of signum calls the method on the class. */
template <typename T>

View File

@@ -3,7 +3,6 @@
#include <array>
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace beast {
@@ -14,7 +13,7 @@ rngfill(void* const buffer, std::size_t const bytes, Generator& g)
using result_type = Generator::result_type;
constexpr std::size_t kResultSize = sizeof(result_type);
std::uint8_t* const bufferStart = static_cast<std::uint8_t*>(buffer);
auto* const bufferStart = static_cast<std::uint8_t*>(buffer);
std::size_t const completeIterations = bytes / kResultSize;
std::size_t const bytesRemaining = bytes % kResultSize;
@@ -33,16 +32,14 @@ rngfill(void* const buffer, std::size_t const bytes, Generator& g)
}
}
template <
class Generator,
std::size_t N,
class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>>
template <class Generator, std::size_t N>
void
rngfill(std::array<std::uint8_t, N>& a, Generator& g)
requires(N % sizeof(typename Generator::result_type) == 0)
{
using result_type = Generator::result_type;
auto i = N / sizeof(result_type);
result_type* p = reinterpret_cast<result_type*>(a.data());
auto* p = reinterpret_cast<result_type*>(a.data());
while (i--)
*p++ = g();
}

View File

@@ -127,7 +127,7 @@ private:
}
[[nodiscard]] HashRouterFlags
getFlags(void) const
getFlags() const
{
return flags_;
}

View File

@@ -154,16 +154,14 @@ public:
@param type The type of job.
@param name Name of the job.
@param jobHandler Lambda with signature void (Job&). Called when the
job is executed.
@param jobHandler Callable with signature void(). Called when the job is executed.
@return true if jobHandler added to queue.
*/
template <
typename JobHandler,
typename = std::enable_if_t<std::is_same_v<decltype(std::declval<JobHandler&&>()()), void>>>
template <typename JobHandler>
bool
addJob(JobType type, std::string const& name, JobHandler&& jobHandler)
requires(std::is_void_v<std::invoke_result_t<JobHandler>>)
{
if (auto optionalCountedJob = jobCounter_.wrap(std::forward<JobHandler>(jobHandler)))
{

View File

@@ -118,7 +118,7 @@ public:
[[nodiscard]] JobTypeInfo const&
get(JobType jt) const
{
Map::const_iterator const iter(map.find(jt));
auto const iter = map.find(jt);
XRPL_ASSERT(iter != map.end(), "xrpl::JobTypes::get : valid input");
if (iter != map.end())

View File

@@ -154,7 +154,7 @@ private:
Location end,
unsigned int& unicode);
bool
addError(std::string const& message, Token& token, Location extra = 0);
addError(std::string const& message, Token& token, Location extra = nullptr);
bool
recoverFromError(TokenType skipUntilToken);
bool

View File

@@ -5,7 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/Issue.h> // IWYU pragma: keep
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/MPTIssue.h>

View File

@@ -141,7 +141,7 @@ template <class Base>
class CachedView : public detail::CachedViewImpl
{
private:
static_assert(std::is_base_of_v<DigestAwareReadView, Base>, "");
static_assert(std::is_base_of_v<DigestAwareReadView, Base>);
std::shared_ptr<Base const> sp_;

View File

@@ -82,7 +82,7 @@ private:
using txs_map = std::map<
key_type,
TxData,
std::less<key_type>,
std::less<>,
boost::container::pmr::polymorphic_allocator<std::pair<key_type const, TxData>>>;
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be

View File

@@ -7,7 +7,7 @@
#include <xrpl/ledger/detail/ReadViewFwdRange.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/Issue.h> // IWYU pragma: keep
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerHeader.h>
#include <xrpl/protocol/MPTIssue.h>

View File

@@ -105,7 +105,7 @@ private:
using items_t = std::map<
key_type,
SleAction,
std::less<key_type>,
std::less<>,
boost::container::pmr::polymorphic_allocator<std::pair<key_type const, SleAction>>>;
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
// easily moved.

View File

@@ -108,8 +108,8 @@ public:
std::optional<value_type> mutable cache_;
};
static_assert(std::is_nothrow_move_constructible<Iterator>{}, "");
static_assert(std::is_nothrow_move_assignable<Iterator>{}, "");
static_assert(std::is_nothrow_move_constructible<Iterator>{});
static_assert(std::is_nothrow_move_assignable<Iterator>{});
using const_iterator = Iterator;

View File

@@ -19,11 +19,7 @@ namespace xrpl {
namespace detail {
template <
class V,
class N,
class = std::enable_if_t<
std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>>>
template <class V, class N>
bool
internalDirNext(
V& view,
@@ -31,6 +27,7 @@ internalDirNext(
std::shared_ptr<N>& page,
unsigned int& index,
uint256& entry)
requires(std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>)
{
auto const& svIndexes = page->getFieldV256(sfIndexes);
XRPL_ASSERT(index <= svIndexes.size(), "xrpl::detail::internalDirNext : index inside range");
@@ -68,11 +65,7 @@ internalDirNext(
return true;
}
template <
class V,
class N,
class = std::enable_if_t<
std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>>>
template <class V, class N>
bool
internalDirFirst(
V& view,
@@ -80,6 +73,7 @@ internalDirFirst(
std::shared_ptr<N>& page,
unsigned int& index,
uint256& entry)
requires(std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>)
{
if constexpr (std::is_const_v<N>)
{

View File

@@ -54,7 +54,7 @@ escrowUnlockApplyHelper<Issue>(
bool createAsset,
beast::Journal journal)
{
Issue const& issue = amount.get<Issue>();
auto const& issue = amount.get<Issue>();
Keylet const trustLineKey = keylet::trustLine(receiver, issue);
bool const recvLow = issuer > receiver;
bool const senderIssuer = issuer == sender;

View File

@@ -7,8 +7,9 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/LedgerFormats.h> // IWYU pragma: keep
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/SField.h>
@@ -47,11 +48,9 @@ namespace xrpl {
*/
[[nodiscard]] TER
canApplyToBrokerCover(
ReadView const& view,
SLE::const_ref sleBroker,
LoanBrokerEntry<ReadView> const& sleBroker,
Asset const& vaultAsset,
STAmount const& amount,
beast::Journal j,
std::string_view logPrefix);
// Lending protocol has dependencies, so capture them here.
@@ -214,7 +213,7 @@ adjustImpreciseNumber(
}
inline int
getAssetsTotalScale(SLE::const_ref vaultSle)
getAssetsTotalScale(VaultEntry<ReadView> const& vaultSle)
{
if (!vaultSle)
return Number::kMinExponent - 1; // LCOV_EXCL_LINE
@@ -225,7 +224,10 @@ getAssetsTotalScale(SLE::const_ref vaultSle)
// DebtTotal is a broker-level aggregate maintained at vault scale, so the
// rounding must also use vault scale — never an individual loan's scale.
inline Number
minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::const_ref vaultSle)
minimumBrokerCover(
Number const& debtTotal,
TenthBips32 coverRateMinimum,
VaultEntry<ReadView> const& vaultSle)
{
XRPL_ASSERT(
vaultSle && vaultSle->getType() == ltVAULT, "xrpl::minimumBrokerCover : valid Vault sle");
@@ -263,7 +265,7 @@ constructLoanState(
// Constructs a valid LoanState object from a Loan object, which always has
// rounded values
LoanState
constructRoundedLoanState(SLE::const_ref loan);
constructRoundedLoanState(LoanEntry<ReadView> const& loan);
Number
computeManagementFee(
@@ -544,11 +546,9 @@ enum class LoanPaymentType { Regular = 0, Late, Full, Overpayment };
std::expected<LoanPaymentParts, TER>
loanMakePayment(
Asset const& asset,
ApplyView& view,
SLE::ref loan,
SLE::const_ref brokerSle,
LoanEntry<ApplyView>& loan,
LoanBrokerEntry<ReadView> const& brokerSle,
STAmount const& amount,
LoanPaymentType const paymentType,
beast::Journal j);
LoanPaymentType const paymentType);
} // namespace xrpl

View File

@@ -0,0 +1,31 @@
#pragma once
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STArray.h> // IWYU pragma: keep
#include <xrpl/protocol/STLedgerEntry.h>
#include <cstddef>
#include <cstdint>
namespace xrpl {
constexpr std::uint32_t kMinOracleReserveCount = 1;
constexpr std::uint32_t kMaxOracleReserveCount = 2;
constexpr std::size_t kOracleReserveCountThreshold = 5;
template <typename T>
requires requires(T const& t) { t.size(); }
inline std::uint32_t
calculateOracleReserve(T const& priceDataSeries)
{
return priceDataSeries.size() > kOracleReserveCountThreshold ? kMaxOracleReserveCount
: kMinOracleReserveCount;
}
inline std::uint32_t
calculateOracleReserve(SLE::const_ref oracleSle)
{
return calculateOracleReserve(oracleSle->getFieldArray(sfPriceDataSeries));
}
} // namespace xrpl

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
@@ -22,7 +23,11 @@ namespace xrpl {
* fails; tefINTERNAL if the source account SLE cannot be found.
*/
TER
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j);
closeChannel(
PayChannelEntry<ApplyView>& slep,
ApplyView& view,
uint256 const& key,
beast::Journal j);
/** Add two uint32_t values with saturation at UINT32_MAX.
*

View File

@@ -0,0 +1,445 @@
#pragma once
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> // adjustOwnerCount
#include <xrpl/ledger/helpers/DirectoryHelpers.h> // describeOwnerDir
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/Indexes.h> // keylet::account, keylet::ownerDir
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <concepts>
#include <cstdint>
#include <memory>
#include <optional>
#include <stdexcept>
#include <type_traits>
#include <vector>
namespace xrpl {
// Concept to distinguish read-only vs writable view types
template <typename V>
concept WritableView = std::derived_from<V, ApplyView>;
/** Describes one directory a ledger entry is linked into, for create()/destroy().
*
* @param owner the account whose owner directory this is (the directory
* is keylet::ownerDir(owner)).
* @param node the field on the entry holding this directory's page
* index (sfOwnerNode, sfDestinationNode, sfSubjectNode, ...).
* @param countsToward whether linking here consumes `owner`'s OwnerCount /
* reserve (true for the owning account, false for auxiliary
* links such as a destination's tracking directory).
*/
struct OwnerDirLink
{
AccountID owner;
SField const* node;
bool countsToward;
};
/**
* View-parameterized base class for all ledger entry wrappers.
*
* SLEBase<ReadView> — read-only: holds shared_ptr<SLE const> + ReadView const&
* SLEBase<ApplyView> — writable: holds shared_ptr<SLE> + ApplyView& + Keylet,
* plus insert/update/erase operations
*
* Write-only members are gated by `requires` clauses, providing compile-time
* guarantees that read-only wrappers cannot mutate state.
*
* Derived classes should provide domain-specific accessors that hide
* implementation details of the underlying ledger entry format.
*/
template <typename ViewT>
class SLEBase
{
public:
static constexpr bool kIsWritable = WritableView<ViewT>;
// SLE pointer type: mutable for writable views, const for read-only
using sle_ptr_type = std::conditional_t<kIsWritable, std::shared_ptr<SLE>, SLE::const_pointer>;
// View reference type: ApplyView& for writable, ReadView const& for read-only
using view_ref_type = std::conditional_t<kIsWritable, ApplyView&, ReadView const&>;
virtual ~SLEBase() = default;
SLEBase(SLEBase const&) = default;
SLEBase(SLEBase&&) = default;
SLEBase&
operator=(SLEBase const&) = delete;
SLEBase&
operator=(SLEBase&&) = delete;
SLEBase() = delete;
// --- Common interface (always available) ---
/** Returns true if the ledger entry exists */
[[nodiscard]] bool
exists() const
{
return sle_ != nullptr;
}
/** Explicit conversion to bool for convenient existence checking */
explicit
operator bool() const
{
return exists();
}
/** Returns the underlying SLE for read access */
[[nodiscard]] SLE::const_pointer
sle() const
{
return sle_;
}
/** Returns the read view (always available; ApplyView inherits ReadView) */
[[nodiscard]] ReadView const&
readView() const
{
return view_;
}
/** Const dereference operators (always available) */
STLedgerEntry const*
operator->() const
{
XRPL_ASSERT(exists(), "xrpl::SLEBase::operator-> : exists");
return sle_.get();
}
STLedgerEntry const&
operator*() const
{
XRPL_ASSERT(exists(), "xrpl::SLEBase::operator* : exists");
return *sle_;
}
// --- Writable interface (compile-time gated) ---
/** Returns a mutable SLE for write operations */
[[nodiscard]] sle_ptr_type const&
mutableSle() const
requires kIsWritable
{
return sle_;
}
/** Returns true if this wrapper supports write operations */
[[nodiscard]] bool
canModify() const
requires kIsWritable
{
return sle_ != nullptr;
}
/** Returns the apply view for write operations */
[[nodiscard]] ApplyView&
applyView() const
requires kIsWritable
{
return view_;
}
/** Mutable dereference operators */
STLedgerEntry*
operator->()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::operator-> : can modify");
return sle_.get();
}
STLedgerEntry&
operator*()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::operator* : can modify");
return *sle_;
}
void
insert()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::insert : can modify");
view_.insert(sle_);
}
void
erase()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::erase : can modify");
view_.erase(sle_);
}
void
update()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::update : can modify");
view_.update(sle_);
}
void
newSLE()
requires kIsWritable
{
XRPL_ASSERT(!canModify(), "xrpl::SLEBase::newSLE : no existing SLE");
sle_ = std::make_shared<SLE>(key_);
}
/** The field holding the account that owns this entry (sfAccount, sfOwner,
* sfIssuer, ...).
*
* Single-directory entry types override this to name their owning-account
* field; the default ownerDirs() then links a single owner directory keyed
* on it. Types that live in multiple directories override ownerDirs()
* directly instead. The generic base has no owner.
*/
[[nodiscard]] virtual SField const&
ownerField() const
{
UNREACHABLE("xrpl::SLEBase::ownerField : type does not define an owner field");
return sfAccount; // unreachable; present only to satisfy the return type
}
/** The directories this entry is linked into, and where each stores its
* page index.
*
* Default: a single owner directory for ownerField()'s account, recorded in
* sfOwnerNode, counting toward that account's reserve. Types linked into
* more than one directory (e.g. Check/PayChannel/Escrow's destination
* directory, Credential's subject directory) override this to list them;
* only links with `countsToward == true` consume an OwnerCount/reserve slot.
*/
[[nodiscard]] virtual std::vector<OwnerDirLink>
ownerDirs() const
{
return {{sle_->getAccountID(ownerField()), &sfOwnerNode, /*countsToward=*/true}};
}
/** Number of OwnerCount/reserve slots a counted link consumes (default 1).
* Types whose footprint scales with their contents (e.g. Oracle) override.
*/
[[nodiscard]] virtual std::uint32_t
reserveCount() const
{
return 1;
}
/** Link this entry into each listed owner directory (keylet::ownerDir), and
* record the assigned page in the link's node field.
*
* This is the shared directory-linking primitive used by create() and by
* the bespoke create() overrides of entries that live in several owner
* directories. The OwnerDirLink::countsToward flag is ignored here —
* reserve and OwnerCount accounting is the caller's responsibility. Returns
* tecDIR_FULL if any directory is full.
*/
[[nodiscard]] TER
linkOwnerDirs(std::vector<OwnerDirLink> const& dirs)
requires kIsWritable
{
for (auto const& d : dirs)
{
auto const page =
view_.dirInsert(keylet::ownerDir(d.owner), sle_->key(), describeOwnerDir(d.owner));
if (!page)
return tecDIR_FULL; // LCOV_EXCL_LINE
sle_->setFieldU64(*d.node, *page);
}
return tesSUCCESS;
}
/** Unlink this entry from each listed owner directory, using the page stored
* in each link's node field. Inverse of linkOwnerDirs(). Returns
* tefBAD_LEDGER if any removal fails. */
[[nodiscard]] TER
unlinkOwnerDirs(std::vector<OwnerDirLink> const& dirs)
requires kIsWritable
{
for (auto const& d : dirs)
if (!view_.dirRemove(
keylet::ownerDir(d.owner),
sle_->getFieldU64(*d.node),
sle_->key(),
/*keepRoot=*/false))
return tefBAD_LEDGER; // LCOV_EXCL_LINE
return tesSUCCESS;
}
/** Link a freshly-populated entry into its owner directories and insert it.
*
* Handles the create-time boilerplate shared by owned ledger entries:
* 1. reserve check against `ownerReserveBalance` (the owner's pre-fee XRP
* balance — pass the transactor's preFeeBalance_ when the entry is
* owned by the transaction submitter). Pass std::nullopt to skip the
* check entirely, e.g. for entries an internal caller installs on a
* pseudo-account (VaultCreate),
* 2. link into each ownerDirs() directory, recording the page in its node
* field,
* 3. bump the OwnerCount of each counted owner by reserveCount(),
* 4. insert the entry into the view.
*
* The caller must have already called newSLE() and populated the entry's
* domain fields (in particular the account fields ownerDirs() reads).
*/
[[nodiscard]] TER
create(std::optional<XRPAmount> ownerReserveBalance)
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::create : can modify");
auto const dirs = ownerDirs();
for (auto const& d : dirs)
{
if (!d.countsToward)
continue;
auto const ownerSle = view_.peek(keylet::account(d.owner));
if (!ownerSle)
return tecNO_ENTRY; // LCOV_EXCL_LINE
if (ownerReserveBalance &&
*ownerReserveBalance <
view_.fees().accountReserve((*ownerSle)[sfOwnerCount] + reserveCount()))
return tecINSUFFICIENT_RESERVE;
}
if (auto const ter = linkOwnerDirs(dirs); !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE
for (auto const& d : dirs)
if (d.countsToward)
adjustOwnerCount(view_, view_.peek(keylet::account(d.owner)), reserveCount(), j_);
view_.insert(sle_);
return tesSUCCESS;
}
/** Unlink an owned entry from its directories and erase it.
*
* Inverse of create(): removes the entry from each ownerDirs() directory
* (using the stored node fields), decrements each counted owner's OwnerCount
* by reserveCount(), and erases the entry.
*/
[[nodiscard]] TER
destroy()
requires kIsWritable
{
XRPL_ASSERT(canModify(), "xrpl::SLEBase::destroy : can modify");
auto const dirs = ownerDirs();
if (auto const ter = unlinkOwnerDirs(dirs); !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE
for (auto const& d : dirs)
if (d.countsToward)
if (auto ownerSle = view_.peek(keylet::account(d.owner)))
adjustOwnerCount(
view_, ownerSle, -static_cast<std::int32_t>(reserveCount()), j_);
view_.erase(sle_);
return tesSUCCESS;
}
[[nodiscard]] beast::Journal
journal() const
{
return j_;
}
// --- Constructors that adopt/resolve an SLE (public so the ReadOnlySLE /
// WritableSLE aliases and the per-type wrappers can be built directly
// from an already-fetched SLE or a keylet). ---
/** Constructor for read-only context */
explicit SLEBase(
SLE::const_pointer sle,
ReadView const& view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
requires(!kIsWritable)
: view_(view), sle_(std::move(sle)), j_(j)
{
}
/** Constructor for read-only context (read from view by keylet) */
explicit SLEBase(
Keylet const& key,
ReadView const& view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
requires(!kIsWritable)
: view_(view), sle_(view.read(key)), j_(j)
{
}
/** Converting constructor: writable → read-only.
* Enables implicit conversion from SLEBase<ApplyView> to
* SLEBase<ReadView>, so functions taking ReadOnlySLE const& can
* accept WritableSLE.
*/
template <WritableView OtherViewT>
SLEBase(SLEBase<OtherViewT> const& other)
requires(!kIsWritable)
: view_(other.readView()), sle_(other.sle()), j_(other.journal())
{
}
/** Constructor for writable context (from existing SLE) */
explicit SLEBase(
std::shared_ptr<SLE> sle,
ApplyView& view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
requires kIsWritable
: view_(view)
, key_(sle ? Keylet(sle->getType(), sle->key()) : Keylet(ltANY, uint256{}))
, sle_(std::move(sle))
, j_(j)
{
}
/** Constructor for writable context (peek from view by keylet) */
explicit SLEBase(
Keylet const& key,
ApplyView& view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
requires kIsWritable
: view_(view), key_(key), sle_(view_.peek(key)), j_(j)
{
}
protected:
view_ref_type view_{};
// Keylet is only meaningful for writable views, but we conditionally
// include it to avoid wasting space in read-only wrappers.
struct Empty
{
};
[[no_unique_address]]
std::conditional_t<kIsWritable, Keylet, Empty> key_{};
sle_ptr_type sle_{};
beast::Journal j_;
};
/** Generic (any-entry-type) SLE handles.
*
* Use these when the concrete ledger entry type is not known at a given site;
* otherwise prefer the per-type wrappers in SLEWrappers.h.
*
* SLE::const_pointer / SLE::const_ref -> ReadOnlySLE
* SLE::pointer / SLE::ref -> WritableSLE
*/
using ReadOnlySLE = SLEBase<ReadView>;
using WritableSLE = SLEBase<ApplyView>;
} // namespace xrpl

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
#pragma once
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/TxFormats.h>
#include <cstdint>
#include <expected>
#include <optional>
#include <unordered_set>
namespace xrpl {
std::optional<AccountID>
getLedgerEntryOwner(ReadView const& view, SLE const& sle, AccountID const& account);
std::uint32_t
getLedgerEntryOwnerCount(SLE const& sle);
} // namespace xrpl

View File

@@ -1,6 +1,7 @@
#pragma once
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -20,7 +21,10 @@ namespace xrpl {
@return The number of shares, or nullopt on error.
*/
[[nodiscard]] std::optional<STAmount>
assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets);
assetsToSharesDeposit(
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& assets);
/** From the perspective of a vault, return the number of assets to take from
depositor when they receive a fixed amount of shares. Note, since shares are
@@ -33,7 +37,10 @@ assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
@return The number of assets, or nullopt on error.
*/
[[nodiscard]] std::optional<STAmount>
sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares);
sharesToAssetsDeposit(
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& shares);
/** Controls whether to truncate shares instead of rounding. */
enum class TruncateShares : bool { No = false, Yes = true };
@@ -62,8 +69,8 @@ enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
*/
[[nodiscard]] std::optional<STAmount>
assetsToSharesWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& assets,
TruncateShares truncate = TruncateShares::No,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
@@ -82,8 +89,8 @@ assetsToSharesWithdraw(
*/
[[nodiscard]] std::optional<STAmount>
sharesToAssetsWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& shares,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
@@ -97,6 +104,9 @@ sharesToAssetsWithdraw(
both the share MPTID and the outstanding-amount total.
*/
[[nodiscard]] bool
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance);
isSoleShareholder(
ReadView const& view,
AccountID const& account,
MPTokenIssuanceEntry<ReadView> const& issuance);
} // namespace xrpl

View File

@@ -120,12 +120,9 @@ public:
socket_->next_layer().async_receive(
boost::asio::buffer(buffer_),
boost::asio::socket_base::message_peek,
std::bind(
&AutoSocket::handleAutodetect,
this,
cbFunc,
std::placeholders::_1,
std::placeholders::_2));
[this, cbFunc](error_code const& ec, size_t bytesTransferred) {
handleAutodetect(cbFunc, ec, bytesTransferred);
});
}
}

View File

@@ -13,7 +13,6 @@
#include <openssl/err.h>
#include <openssl/tls1.h>
#include <functional>
#include <stdexcept>
#include <string>
#include <type_traits>
@@ -84,13 +83,12 @@ public:
*
* @return error_code indicating failures, if any
*/
template <
class T,
class = std::enable_if_t<
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ||
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>>>
template <class T>
boost::system::error_code
preConnectVerify(T& strm, std::string const& host)
requires(
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ||
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>)
{
boost::system::error_code ec;
if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
@@ -104,11 +102,7 @@ public:
return ec;
}
template <
class T,
class = std::enable_if_t<
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ||
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>>>
template <class T>
/**
* @brief invoked after connect/async_connect but before sending data
* on an ssl stream - to setup name verification.
@@ -118,6 +112,9 @@ public:
*/
boost::system::error_code
postConnectVerify(T& strm, std::string const& host)
requires(
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ||
std::is_same_v<T, boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>)
{
boost::system::error_code ec;
@@ -127,8 +124,9 @@ public:
if (!ec)
{
strm.set_verify_callback(
std::bind(
&rfc6125Verify, host, std::placeholders::_1, std::placeholders::_2, j_),
[host, j = j_](bool preverified, boost::asio::ssl::verify_context& ctx) {
return rfc6125Verify(host, preverified, ctx, j);
},
ec);
}
}

View File

@@ -34,11 +34,11 @@ public:
createObject();
private:
bool success_;
bool success_{false};
void const* key_;
NodeObjectType objectType_;
unsigned char const* objectData_;
NodeObjectType objectType_{NodeObjectType::Unknown};
unsigned char const* objectData_{nullptr};
int dataBytes_;
};

View File

@@ -62,7 +62,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
auto const n = writeVarint(vi.data(), inSize);
auto const outMax = LZ4_compressBound(inSize);
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
auto* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
result.first = out;
std::memcpy(out, vi.data(), n);
auto const outSize = LZ4_compress_default(
@@ -90,7 +90,7 @@ nodeobjectDecompress(void const* in, std::size_t inSize, BufferFactory&& bf)
{
using namespace nudb::detail;
std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(in);
auto const* p = reinterpret_cast<std::uint8_t const*>(in);
std::size_t type = 0;
auto const vn = readVarint(p, inSize, type);
if (vn == 0)
@@ -237,7 +237,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
auto const vs = sizeVarint(type);
result.second = vs + field<std::uint16_t>::size + // mask
(n * 32); // hashes
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);
@@ -249,7 +249,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
auto const type = 3U;
auto const vs = sizeVarint(type);
result.second = vs + (n * 32); // hashes
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);

View File

@@ -39,7 +39,7 @@ readVarint(void const* buf, std::size_t buflen, std::size_t& t)
if (buflen == 0)
return 0;
t = 0;
std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
auto const* p = reinterpret_cast<std::uint8_t const*>(buf);
std::size_t n = 0;
while (p[n] & 0x80)
{
@@ -68,9 +68,10 @@ readVarint(void const* buf, std::size_t buflen, std::size_t& t)
return used;
}
template <class T, std::enable_if_t<std::is_unsigned_v<T>>* = nullptr>
template <class T>
std::size_t
sizeVarint(T v)
requires(std::is_unsigned_v<T>)
{
std::size_t n = 0;
do
@@ -86,7 +87,7 @@ std::size_t
writeVarint(void* p0, std::size_t v)
{
// NOLINTNEXTLINE(misc-const-correctness)
std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
auto* p = reinterpret_cast<std::uint8_t*>(p0);
do
{
std::uint8_t d = v % 127;
@@ -100,9 +101,10 @@ writeVarint(void* p0, std::size_t v)
// input stream
template <class T, std::enable_if_t<std::is_same_v<T, varint>>* = nullptr>
template <class T>
void
read(nudb::detail::istream& is, std::size_t& u)
requires(std::is_same_v<T, varint>)
{
auto p0 = is(1);
auto p1 = p0;
@@ -113,9 +115,10 @@ read(nudb::detail::istream& is, std::size_t& u)
// output stream
template <class T, std::enable_if_t<std::is_same_v<T, varint>>* = nullptr>
template <class T>
void
write(nudb::detail::ostream& os, std::size_t t)
requires(std::is_same_v<T, varint>)
{
writeVarint(os.data(sizeVarint(t)), t);
}

View File

@@ -13,7 +13,7 @@
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <limits>
#include <limits> // IWYU pragma: keep
#include <stdexcept>
#include <type_traits>

View File

@@ -13,7 +13,6 @@
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/STXChainBridge.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/jss.h>
#include <array>
#include <cstdint>
@@ -363,20 +362,10 @@ struct KeyletDesc
};
// This list should include all of the keylet functions that take a single
// AccountID parameter.
std::array<KeyletDesc<AccountID const&>, 6> const kDirectAccountKeylets{
{{.function = &keylet::account, .expectedLEName = jss::AccountRoot, .includeInTests = false},
{.function = &keylet::ownerDir, .expectedLEName = jss::DirectoryNode, .includeInTests = true},
{.function = &keylet::signerList, .expectedLEName = jss::SignerList, .includeInTests = true},
// It's normally impossible to create an item at nftpage_min, but
// test it anyway, since the invariant checks for it.
{.function = &keylet::nftokenPageMin,
.expectedLEName = jss::NFTokenPage,
.includeInTests = true},
{.function = &keylet::nftokenPageMax,
.expectedLEName = jss::NFTokenPage,
.includeInTests = true},
{.function = &keylet::did, .expectedLEName = jss::DID, .includeInTests = true}}};
// AccountID parameter. Defined in Indexes.cpp so that this header does not
// need to include jss.h (which transitively re-includes transactions.macro
// and breaks headers processed inside the TRANSACTION_INCLUDE machinery).
extern std::array<KeyletDesc<AccountID const&>, 6> const kDirectAccountKeylets;
MPTID
makeMptID(std::uint32_t sequence, AccountID const& account);

View File

@@ -282,7 +282,7 @@ public:
auto const maxVMantissa = mantissa(maxV);
auto const expDiff = exponent(maxV) - exponent(minV);
double const minVD = static_cast<double>(minVMantissa);
auto const minVD = static_cast<double>(minVMantissa);
double const maxVD =
(expDiff != 0) ? maxVMantissa * pow(10, expDiff) : static_cast<double>(maxVMantissa);

View File

@@ -32,17 +32,13 @@ public:
STArray() = default;
STArray(STArray const&) = default;
template <
class Iter,
class = std::enable_if_t<
std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>>>
explicit STArray(Iter first, Iter last);
template <class Iter>
explicit STArray(Iter first, Iter last)
requires(std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>);
template <
class Iter,
class = std::enable_if_t<
std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>>>
STArray(SField const& f, Iter first, Iter last);
template <class Iter>
STArray(SField const& f, Iter first, Iter last)
requires(std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>);
STArray&
operator=(STArray const&) = default;
@@ -170,13 +166,17 @@ private:
friend class detail::STVar;
};
template <class Iter, class>
STArray::STArray(Iter first, Iter last) : v_(first, last)
template <class Iter>
STArray::STArray(Iter first, Iter last)
requires(std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>)
: v_(first, last)
{
}
template <class Iter, class>
STArray::STArray(SField const& f, Iter first, Iter last) : STBase(f), v_(first, last)
template <class Iter>
STArray::STArray(SField const& f, Iter first, Iter last)
requires(std::is_convertible_v<typename std::iterator_traits<Iter>::reference, STObject>)
: STBase(f), v_(first, last)
{
}

View File

@@ -148,7 +148,7 @@ template <int Bits>
bool
STBitString<Bits>::isEquivalent(STBase const& t) const
{
STBitString const* v = dynamic_cast<STBitString const*>(&t);
auto const* v = dynamic_cast<STBitString const*>(&t);
return v && (value_ == v->value_);
}

View File

@@ -115,7 +115,7 @@ template <typename Integer>
inline bool
STInteger<Integer>::isEquivalent(STBase const& t) const
{
STInteger const* v = dynamic_cast<STInteger const*>(&t);
auto const* v = dynamic_cast<STInteger const*>(&t);
return v && (value_ == v->value_);
}

View File

@@ -555,9 +555,14 @@ public:
ValueProxy&
operator=(ValueProxy const&) = delete;
// Write-through proxy: assignment sets the referenced field to the given
// value, so it intentionally takes the assigned value rather than a
// ValueProxy.
template <class U>
std::enable_if_t<std::is_assignable_v<T, U>, ValueProxy&>
operator=(U&& u);
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
ValueProxy&
operator=(U&& u)
requires(std::is_assignable_v<T, U>);
// Convenience operators for value types supporting
// arithmetic operations
@@ -691,8 +696,9 @@ public:
operator=(optional_type const& v);
template <class U>
std::enable_if_t<std::is_assignable_v<T, U>, OptionalProxy&>
operator=(U&& u);
OptionalProxy&
operator=(U&& u)
requires(std::is_assignable_v<T, U>);
private:
friend class STObject;
@@ -798,8 +804,10 @@ STObject::Proxy<T>::assign(U&& u)
template <class T>
template <class U>
std::enable_if_t<std::is_assignable_v<T, U>, STObject::ValueProxy<T>&>
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
STObject::ValueProxy<T>&
STObject::ValueProxy<T>::operator=(U&& u)
requires(std::is_assignable_v<T, U>)
{
this->assign(std::forward<U>(u));
return *this;
@@ -902,8 +910,9 @@ STObject::OptionalProxy<T>::operator=(optional_type const& v) -> OptionalProxy&
template <class T>
template <class U>
std::enable_if_t<std::is_assignable_v<T, U>, STObject::OptionalProxy<T>&>
STObject::OptionalProxy<T>&
STObject::OptionalProxy<T>::operator=(U&& u)
requires(std::is_assignable_v<T, U>)
{
this->assign(std::forward<U>(u));
return *this;
@@ -1241,7 +1250,7 @@ template <typename T, typename V>
void
STObject::setFieldUsingSetValue(SField const& field, V value)
{
static_assert(!std::is_lvalue_reference_v<V>, "");
static_assert(!std::is_lvalue_reference_v<V>);
STBase* rf = getPField(field, true);

View File

@@ -240,6 +240,9 @@ private:
inline STPathElement::STPathElement() : type_(TypeNone), isOffer_(true)
{
// hashValue_ is derived from the whole object, so it is computed in the body
// once every other member is initialized (as in the other constructors).
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
hashValue_ = getHash(*this);
}
@@ -315,6 +318,9 @@ inline STPathElement::STPathElement(
assetID_.visit(
[&](Currency const&) { type_ = type_ & (~Type::TypeMpt); },
[&](MPTID const&) { type_ = type_ & (~Type::TypeCurrency); });
// hashValue_ must be computed after type_ is adjusted above, so this cannot
// be a member initializer.
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
hashValue_ = getHash(*this);
}

View File

@@ -334,7 +334,7 @@ public:
template <int N>
explicit SerialIter(std::uint8_t const (&data)[N]) : SerialIter(&data[0], N)
{
static_assert(N > 0, "");
static_assert(N > 0);
}
[[nodiscard]] bool

View File

@@ -411,7 +411,7 @@ TERtoInt(TECcodes v)
//------------------------------------------------------------------------------
// Template class that is specific to selected ranges of error codes. The
// Trait tells std::enable_if which ranges are allowed.
// Trait tells the requires-clause which ranges are allowed.
template <template <typename> class Trait>
class TERSubset
{
@@ -437,11 +437,11 @@ public:
return TERSubset(from);
}
// Trait tells enable_if which types are allowed for construction.
template <
typename T,
typename = std::enable_if_t<Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
constexpr TERSubset(T rhs) : code_(TERtoInt(rhs))
// Trait tells the requires-clause which types are allowed for construction.
template <typename T>
constexpr TERSubset(T rhs)
requires(Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value)
: code_(TERtoInt(rhs))
{
}
@@ -451,10 +451,11 @@ public:
constexpr TERSubset&
operator=(TERSubset&& rhs) = default;
// Trait tells enable_if which types are allowed for assignment.
// Trait tells the requires-clause which types are allowed for assignment.
template <typename T>
constexpr auto
operator=(T rhs) -> std::enable_if_t<Trait<T>::value, TERSubset&>
operator=(T rhs) -> TERSubset&
requires(Trait<T>::value)
{
code_ = TERtoInt(rhs);
return *this;
@@ -508,54 +509,60 @@ public:
// Only enabled if both arguments return int if TERtiInt is called with them.
template <typename L, typename R>
constexpr auto
operator==(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator==(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) == TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator!=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator!=(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) != TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator<(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator<(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) < TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator<=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator<=(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) <= TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator>(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator>(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) > TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator>=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same_v<decltype(TERtoInt(lhs)), int> && std::is_same_v<decltype(TERtoInt(rhs)), int>,
bool>
operator>=(L const& lhs, R const& rhs) -> bool
requires(
std::is_same_v<decltype(TERtoInt(lhs)), int> &&
std::is_same_v<decltype(TERtoInt(rhs)), int>)
{
return TERtoInt(lhs) >= TERtoInt(rhs);
}

View File

@@ -50,14 +50,13 @@ public:
STVar&
operator=(STVar&& rhs);
STVar(STBase&& t) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
STVar(STBase&& t) : p_(t.move(kMaxSize, &d_))
{
p_ = t.move(kMaxSize, &d_);
}
STVar(STBase const& t)
STVar(STBase const& t) : p_(t.copy(kMaxSize, &d_))
{
p_ = t.copy(kMaxSize, &d_);
}
STVar(DefaultObjectT, SField const& name);

View File

@@ -15,9 +15,9 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FEATURE(BatchV1_1, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(BatchV1_1, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocolV1_1, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(ConfidentialTransfer, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(ConfidentialTransfer, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_3_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_2_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo)
@@ -60,7 +60,6 @@ XRPL_FEATURE(PriceOracle, Supported::Yes, VoteBehavior::DefaultNo
XRPL_FIX (AMMOverflowOffer, Supported::Yes, VoteBehavior::DefaultYes)
XRPL_FIX (FillOrKill, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DID, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (DisallowIncomingV1, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(XChainBridge, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(XRPFees, Supported::Yes, VoteBehavior::DefaultNo)
@@ -100,6 +99,7 @@ XRPL_RETIRE_FIX(1623)
XRPL_RETIRE_FIX(1781)
XRPL_RETIRE_FIX(AmendmentMajorityCalc)
XRPL_RETIRE_FIX(CheckThreading)
XRPL_RETIRE_FIX(DisallowIncomingV1)
XRPL_RETIRE_FIX(InnerObjTemplate)
XRPL_RETIRE_FIX(MasterKeyAsRegularKey)
XRPL_RETIRE_FIX(NonFungibleTokensV1_2)

View File

@@ -351,10 +351,9 @@ public:
Import& import(iter->second);
if (iter->second.whenExpires <= elapsed)
{
for (auto itemIter(import.items.begin()); itemIter != import.items.end();
++itemIter)
for (auto& item : import.items)
{
itemIter->consumer.entry().remoteBalance -= itemIter->balance;
item.consumer.entry().remoteBalance -= item.balance;
}
iter = importTable_.erase(iter);

View File

@@ -161,13 +161,12 @@ deserializeManifest(
return deserializeManifest(makeSlice(s), journal);
}
template <
class T,
class = std::enable_if_t<std::is_same_v<T, char> || std::is_same_v<T, unsigned char>>>
template <class T>
std::optional<Manifest>
deserializeManifest(
std::vector<T> const& v,
beast::Journal journal = beast::Journal(beast::Journal::getNullSink()))
requires(std::is_same_v<T, char> || std::is_same_v<T, unsigned char>)
{
return deserializeManifest(makeSlice(v), journal);
}

View File

@@ -223,10 +223,7 @@ BaseHTTPPeer<Handler, Impl>::close()
{
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(
(void (BaseHTTPPeer::*)(void))&BaseHTTPPeer::close, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->close(); });
}
boost::beast::get_lowest_layer(impl().stream_).close();
}
@@ -322,22 +319,18 @@ BaseHTTPPeer<Handler, Impl>::onWrite(error_code const& ec, std::size_t bytesTran
v,
bind_executor(
strand_,
std::bind(
&BaseHTTPPeer::onWrite,
impl().shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
[self = impl().shared_from_this()](
error_code const& ec, std::size_t bytesTransferred) {
self->onWrite(ec, bytesTransferred);
}));
}
if (!complete_)
return;
if (graceful_)
return doClose();
util::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::doRead,
impl().shared_from_this(),
std::placeholders::_1));
util::spawn(strand_, [self = impl().shared_from_this()](yield_context doYield) {
self->doRead(doYield);
});
}
template <class Handler, class Impl>
@@ -351,14 +344,9 @@ BaseHTTPPeer<Handler, Impl>::doWriter(
{
auto const p = impl().shared_from_this();
resume = std::function<void(void)>([this, p, writer, keepAlive]() {
util::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::doWriter,
p,
writer,
keepAlive,
std::placeholders::_1));
util::spawn(strand_, [p, writer, keepAlive](yield_context doYield) {
p->doWriter(writer, keepAlive, doYield);
});
});
}
@@ -379,12 +367,9 @@ BaseHTTPPeer<Handler, Impl>::doWriter(
if (!keepAlive)
return doClose();
util::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::doRead,
impl().shared_from_this(),
std::placeholders::_1));
util::spawn(strand_, [self = impl().shared_from_this()](yield_context doYield) {
self->doRead(doYield);
});
}
//------------------------------------------------------------------------------
@@ -405,8 +390,7 @@ BaseHTTPPeer<Handler, Impl>::write(void const* buf, std::size_t bytes)
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(&BaseHTTPPeer::onWrite, impl().shared_from_this(), error_code{}, 0));
strand_, [self = impl().shared_from_this()] { self->onWrite(error_code{}, 0); });
}
return onWrite(error_code{}, 0);
}
@@ -417,13 +401,9 @@ void
BaseHTTPPeer<Handler, Impl>::write(std::shared_ptr<Writer> const& writer, bool keepAlive)
{
util::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::doWriter,
impl().shared_from_this(),
writer,
keepAlive,
std::placeholders::_1));
strand_, [self = impl().shared_from_this(), writer, keepAlive](yield_context doYield) {
self->doWriter(writer, keepAlive, doYield);
});
}
// DEPRECATED
@@ -443,8 +423,7 @@ BaseHTTPPeer<Handler, Impl>::complete()
{
if (!strand_.running_in_this_thread())
{
return post(
strand_, std::bind(&BaseHTTPPeer<Handler, Impl>::complete, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->complete(); });
}
message_ = {};
@@ -457,12 +436,9 @@ BaseHTTPPeer<Handler, Impl>::complete()
}
// keep-alive
util::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::doRead,
impl().shared_from_this(),
std::placeholders::_1));
util::spawn(strand_, [self = impl().shared_from_this()](yield_context doYield) {
self->doRead(doYield);
});
}
// DEPRECATED
@@ -474,11 +450,7 @@ BaseHTTPPeer<Handler, Impl>::close(bool graceful)
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(
(void (BaseHTTPPeer::*)(bool))&BaseHTTPPeer<Handler, Impl>::close,
impl().shared_from_this(),
graceful));
strand_, [self = impl().shared_from_this(), graceful] { self->close(graceful); });
}
complete_ = true;

View File

@@ -10,7 +10,6 @@
#include <atomic>
#include <chrono>
#include <functional>
#include <string>
#include <utility>
@@ -84,7 +83,7 @@ void
BasePeer<Handler, Impl>::close()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BasePeer::close, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->close(); });
error_code ec;
xrpl::getLowestLayer(impl().ws_).socket().close(ec);
}

View File

@@ -20,6 +20,7 @@
#include <algorithm>
#include <chrono>
#include <cstddef>
#include <functional>
#include <iterator>
#include <list>
@@ -180,12 +181,13 @@ void
BaseWSPeer<Handler, Impl>::run()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::run, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->run(); });
impl().ws_.set_option(port().pmdOptions);
// Must manage the control callback memory outside of the `control_callback`
// function
controlCallback_ =
std::bind(&BaseWSPeer::onPingPong, this, std::placeholders::_1, std::placeholders::_2);
controlCallback_ = [this](
boost::beast::websocket::frame_type kind,
boost::beast::string_view payload) { onPingPong(kind, payload); };
impl().ws_.control_callback(controlCallback_);
startTimer();
closeOnTimer_ = true;
@@ -193,11 +195,9 @@ BaseWSPeer<Handler, Impl>::run()
res.set(boost::beast::http::field::server, BuildInfo::getFullVersionString());
}));
impl().ws_.async_accept(
request_,
bind_executor(
strand_,
std::bind(
&BaseWSPeer::onWsHandshake, impl().shared_from_this(), std::placeholders::_1)));
request_, bind_executor(strand_, [self = impl().shared_from_this()](error_code const& ec) {
self->onWsHandshake(ec);
}));
}
template <class Handler, class Impl>
@@ -205,7 +205,10 @@ void
BaseWSPeer<Handler, Impl>::send(std::shared_ptr<WSMsg> w)
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::send, impl().shared_from_this(), std::move(w)));
{
return post(
strand_, [self = impl().shared_from_this(), w = std::move(w)] { self->send(w); });
}
if (doClose_)
return;
if (wq_.size() > port().wsQueueLimit)
@@ -258,7 +261,7 @@ void
BaseWSPeer<Handler, Impl>::complete()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::complete, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->complete(); });
doRead();
}
@@ -277,7 +280,7 @@ void
BaseWSPeer<Handler, Impl>::doWrite()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::doWrite, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->doWrite(); });
onWrite({});
}
@@ -288,8 +291,7 @@ BaseWSPeer<Handler, Impl>::onWrite(error_code const& ec)
if (ec)
return fail(ec, "write");
auto& w = *wq_.front();
auto const result =
w.prepare(65536, std::bind(&BaseWSPeer::doWrite, impl().shared_from_this()));
auto const result = w.prepare(65536, [self = impl().shared_from_this()] { self->doWrite(); });
if (boost::indeterminate(result.first))
return;
startTimer();
@@ -299,8 +301,9 @@ BaseWSPeer<Handler, Impl>::onWrite(error_code const& ec)
static_cast<bool>(result.first),
result.second,
bind_executor(
strand_,
std::bind(&BaseWSPeer::onWrite, impl().shared_from_this(), std::placeholders::_1)));
strand_, [self = impl().shared_from_this()](error_code const& ec, std::size_t) {
self->onWrite(ec);
}));
}
else
{
@@ -308,9 +311,9 @@ BaseWSPeer<Handler, Impl>::onWrite(error_code const& ec)
static_cast<bool>(result.first),
result.second,
bind_executor(
strand_,
std::bind(
&BaseWSPeer::onWriteFin, impl().shared_from_this(), std::placeholders::_1)));
strand_, [self = impl().shared_from_this()](error_code const& ec, std::size_t) {
self->onWriteFin(ec);
}));
}
}
@@ -324,10 +327,9 @@ BaseWSPeer<Handler, Impl>::onWriteFin(error_code const& ec)
if (doClose_)
{
impl().ws_.async_close(
cr_,
bind_executor(
strand_,
std::bind(&BaseWSPeer::onClose, impl().shared_from_this(), std::placeholders::_1)));
cr_, bind_executor(strand_, [self = impl().shared_from_this()](error_code const& ec) {
self->onClose(ec);
}));
}
else if (!wq_.empty())
{
@@ -340,12 +342,13 @@ void
BaseWSPeer<Handler, Impl>::doRead()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::doRead, impl().shared_from_this()));
return post(strand_, [self = impl().shared_from_this()] { self->doRead(); });
impl().ws_.async_read(
rb_,
bind_executor(
strand_,
std::bind(&BaseWSPeer::onRead, impl().shared_from_this(), std::placeholders::_1)));
strand_, [self = impl().shared_from_this()](error_code const& ec, std::size_t) {
self->onRead(ec);
}));
}
template <class Handler, class Impl>
@@ -389,11 +392,7 @@ BaseWSPeer<Handler, Impl>::startTimer()
}
timer_.async_wait(bind_executor(
strand_,
std::bind(
&BaseWSPeer<Handler, Impl>::onTimer,
impl().shared_from_this(),
std::placeholders::_1)));
strand_, [self = impl().shared_from_this()](error_code const& ec) { self->onTimer(ec); }));
}
// Convenience for discarding the error code
@@ -461,10 +460,9 @@ BaseWSPeer<Handler, Impl>::onTimer(error_code ec)
beast::rngfill(payload_.begin(), payload_.size(), cryptoPrng());
impl().ws_.async_ping(
payload_,
bind_executor(
strand_,
std::bind(
&BaseWSPeer::onPing, impl().shared_from_this(), std::placeholders::_1)));
bind_executor(strand_, [self = impl().shared_from_this()](error_code const& ec) {
self->onPing(ec);
}));
JLOG(this->j_.trace()) << "sent ping";
return;
}

View File

@@ -33,7 +33,6 @@
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <sstream>
@@ -182,7 +181,7 @@ void
Door<Handler>::Detector::run()
{
util::spawn(
strand_, std::bind(&Detector::doDetect, this->shared_from_this(), std::placeholders::_1));
strand_, [self = this->shared_from_this()](yield_context yield) { self->doDetect(yield); });
}
template <class Handler>
@@ -297,8 +296,7 @@ void
Door<Handler>::run()
{
util::spawn(
strand_,
std::bind(&Door<Handler>::doAccept, this->shared_from_this(), std::placeholders::_1));
strand_, [self = this->shared_from_this()](yield_context yield) { self->doAccept(yield); });
}
template <class Handler>
@@ -307,8 +305,7 @@ Door<Handler>::close()
{
if (!strand_.running_in_this_thread())
{
return boost::asio::post(
strand_, std::bind(&Door<Handler>::close, this->shared_from_this()));
return boost::asio::post(strand_, [self = this->shared_from_this()] { self->close(); });
}
backoffTimer_.cancel();
error_code ec;

View File

@@ -9,7 +9,6 @@
#include <boost/beast/core/tcp_stream.hpp>
#include <functional>
#include <memory>
#include <utility>
@@ -89,7 +88,9 @@ PlainHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remoteAddress_))
{
util::spawn(this->strand_, std::bind(&PlainHTTPPeer::doClose, this->shared_from_this()));
util::spawn(this->strand_, [self = this->shared_from_this()](boost::asio::yield_context) {
self->doClose();
});
return;
}
@@ -97,8 +98,9 @@ PlainHTTPPeer<Handler>::run()
return;
util::spawn(
this->strand_,
std::bind(&PlainHTTPPeer::doRead, this->shared_from_this(), std::placeholders::_1));
this->strand_, [self = this->shared_from_this()](boost::asio::yield_context doYield) {
self->doRead(doYield);
});
}
template <class Handler>

View File

@@ -13,7 +13,6 @@
#include <boost/beast/core/tcp_stream.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>
#include <functional>
#include <memory>
#include <utility>
@@ -99,14 +98,15 @@ SSLHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remoteAddress_))
{
util::spawn(this->strand_, std::bind(&SSLHTTPPeer::doClose, this->shared_from_this()));
util::spawn(
this->strand_, [self = this->shared_from_this()](yield_context) { self->doClose(); });
return;
}
if (!socket_.is_open())
return;
util::spawn(
this->strand_,
std::bind(&SSLHTTPPeer::doHandshake, this->shared_from_this(), std::placeholders::_1));
util::spawn(this->strand_, [self = this->shared_from_this()](yield_context doYield) {
self->doHandshake(doYield);
});
}
template <class Handler>
@@ -142,9 +142,9 @@ SSLHTTPPeer<Handler>::doHandshake(yield_context doYield)
this->port().protocol.count("https") > 0;
if (http)
{
util::spawn(
this->strand_,
std::bind(&SSLHTTPPeer::doRead, this->shared_from_this(), std::placeholders::_1));
util::spawn(this->strand_, [self = this->shared_from_this()](yield_context doYield) {
self->doRead(doYield);
});
return;
}
// `this` will be destroyed
@@ -172,7 +172,7 @@ SSLHTTPPeer<Handler>::doClose()
this->startTimer();
stream_.async_shutdown(bind_executor(
this->strand_,
std::bind(&SSLHTTPPeer::onShutdown, this->shared_from_this(), std::placeholders::_1)));
[self = this->shared_from_this()](error_code const& ec) { self->onShutdown(ec); }));
}
template <class Handler>

View File

@@ -103,7 +103,7 @@ public:
/** generation determines whether cached entry is valid */
std::uint32_t
getGeneration(void) const
getGeneration() const
{
return gen_;
}

View File

@@ -138,6 +138,7 @@ intrusive_ptr_release(SHAMapItem const* x)
// If the slabber doesn't claim this pointer, it was allocated
// manually, so we free it manually.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
if (!detail::gSlabber.deallocate(const_cast<std::uint8_t*>(p)))
delete[] p;
}

View File

@@ -507,6 +507,9 @@ TaggedPointer::operator=(TaggedPointer&& other)
[[nodiscard]] inline std::pair<std::uint8_t, void*>
TaggedPointer::decode() const
{
// tp_ packs a raw pointer together with the tag bits; recovering the
// pointer inherently requires an integer-to-pointer cast.
// NOLINTNEXTLINE(performance-no-int-to-ptr)
return {tp_ & kTagMask, reinterpret_cast<void*>(tp_ & kPtrMask)};
}
@@ -535,6 +538,9 @@ TaggedPointer::getHashesAndChildren() const
[[nodiscard]] inline SHAMapHash*
TaggedPointer::getHashes() const
{
// tp_ packs a raw pointer together with the tag bits; recovering the
// pointer inherently requires an integer-to-pointer cast.
// NOLINTNEXTLINE(performance-no-int-to-ptr)
return reinterpret_cast<SHAMapHash*>(tp_ & kPtrMask);
};

View File

@@ -92,6 +92,7 @@ public:
[[nodiscard]] TOffer<TIn, TOut>&
tip() const
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
return const_cast<TOfferStreamBase*>(this)->offer_;
}

View File

@@ -6,7 +6,7 @@
#include <xrpl/protocol/MPTAmount.h> // IWYU pragma: keep
#include <xrpl/protocol/XRPAmount.h>
#include <ostream>
#include <ostream> // IWYU pragma: keep
#include <stdexcept>
#include <variant>

View File

@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STTx.h>
@@ -87,7 +88,7 @@ private:
destroySignerList();
void
writeSignersToSLE(SLE::pointer const& ledgerEntry, std::uint32_t flags) const;
writeSignersToSLE(SignerListEntry<ApplyView>& ledgerEntry, std::uint32_t flags) const;
};
} // namespace xrpl

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -166,7 +167,7 @@ public:
static std::pair<TER, bool>
deleteAMMAccountIfEmpty(
Sandbox& sb,
SLE::pointer const ammSle,
AMMEntry<ApplyView>& ammSle,
STAmount const& lpTokenBalance,
Asset const& asset1,
Asset const& asset2,

View File

@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
@@ -40,32 +41,26 @@ public:
*/
static TER
defaultLoan(
ApplyView& view,
SLE::ref loanSle,
SLE::ref brokerSle,
SLE::ref vaultSle,
Asset const& vaultAsset,
beast::Journal j);
LoanEntry<ApplyView>& loanSle,
LoanBrokerEntry<ApplyView>& brokerSle,
VaultEntry<ApplyView>& vaultSle,
Asset const& vaultAsset);
/** Helper function that might be needed by other transactors
*/
static TER
impairLoan(
ApplyView& view,
SLE::ref loanSle,
SLE::ref vaultSle,
Asset const& vaultAsset,
beast::Journal j);
LoanEntry<ApplyView>& loanSle,
VaultEntry<ApplyView>& vaultSle,
Asset const& vaultAsset);
/** Helper function that might be needed by other transactors
*/
[[nodiscard]] static TER
unimpairLoan(
ApplyView& view,
SLE::ref loanSle,
SLE::ref vaultSle,
Asset const& vaultAsset,
beast::Journal j);
LoanEntry<ApplyView>& loanSle,
VaultEntry<ApplyView>& vaultSle,
Asset const& vaultAsset);
TER
doApply() override;

View File

@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STTx.h>
@@ -21,10 +22,10 @@ private:
pay(AccountID const& from, AccountID const& to, STAmount const& amount);
TER
acceptOffer(SLE::ref offer);
acceptOffer(NFTokenOfferEntry<ApplyView> const& offer);
TER
bridgeOffers(SLE::ref buy, SLE::ref sell);
bridgeOffers(NFTokenOfferEntry<ApplyView> const& buy, NFTokenOfferEntry<ApplyView> const& sell);
TER
transferNFToken(AccountID const& buyer, AccountID const& seller, uint256 const& nfTokenID);

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STTx.h>
@@ -48,8 +49,8 @@ public:
private:
std::expected<std::pair<STAmount, STAmount>, TER>
assetsToClawback(
SLE::ref vault,
SLE::const_ref sleShareIssuance,
VaultEntry<ApplyView>& vault,
MPTokenIssuanceEntry<ReadView> const& sleShareIssuance,
AccountID const& holder,
STAmount const& clawbackAmount);
};

View File

@@ -4,14 +4,16 @@
...
}:
let
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
inherit (pkgs) lib;
inherit (import ./packages.nix { inherit pkgs; })
commonPackages
gccPackage
llvmPackages
llvmVersion
;
# Underlying compiler toolchains to wrap. Bump these in one place to
# roll the whole environment forward.
customGccPackage = pkgs.gcc15;
customLlvmPackages = pkgs.llvmPackages_22;
customClangMajor = lib.versions.major (lib.getVersion customLlvmPackages.clang-unwrapped);
# Underlying compiler toolchains to wrap (versions pinned in packages.nix).
customGccPackage = gccPackage;
customLlvmPackages = llvmPackages;
# binutils wrapped to emit binaries that reference the custom glibc
# (dynamic linker path, library search path, RPATH).
@@ -90,7 +92,7 @@ let
extraBuildCommands = ''
rsrc="$out/resource-root"
mkdir "$rsrc"
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${customClangMajor}/include" "$rsrc/include"
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${toString llvmVersion}/include" "$rsrc/include"
ln -s "${customCompilerRt.out}/lib" "$rsrc/lib"
ln -s "${customCompilerRt.out}/share" "$rsrc/share" || true
echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags

View File

@@ -1,127 +1,57 @@
{ pkgs, ... }:
let
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
inherit (import ./packages.nix { inherit pkgs; })
commonPackages
gccVersion
llvmPackages
;
# Supported compiler versions
gccVersion = pkgs.lib.range 13 15;
clangVersions = pkgs.lib.range 18 21;
# Plain nixpkgs stdenvs — no custom glibc, unlike ci-env.nix.
gccStdenv = pkgs."gcc${toString gccVersion}Stdenv";
clangStdenv = llvmPackages.stdenv;
defaultCompiler = if pkgs.stdenv.isDarwin then "apple-clang" else "gcc";
defaultGccVersion = pkgs.lib.last gccVersion;
defaultClangVersion = pkgs.lib.last clangVersions;
strToCompilerEnv =
compiler: version:
(
if compiler == "gcc" then
let
gccPkg = pkgs."gcc${toString version}Stdenv" or null;
in
if gccPkg != null && builtins.elem version gccVersion then
gccPkg
else
throw "Invalid GCC version: ${toString version}. Must be one of: ${toString gccVersion}"
else if compiler == "clang" then
let
clangPkg = pkgs."llvmPackages_${toString version}".stdenv or null;
in
if clangPkg != null && builtins.elem version clangVersions then
clangPkg
else
throw "Invalid Clang version: ${toString version}. Must be one of: ${toString clangVersions}"
else if compiler == "apple-clang" || compiler == "none" then
pkgs.stdenvNoCC
else
throw "Invalid compiler: ${compiler}. Must be one of: gcc, clang, apple-clang, none"
);
# Helper function to create a shell with a specific compiler
# compilerName is the command used to print the version, or null for none.
makeShell =
{
compiler ? defaultCompiler,
version ? (
if compiler == "gcc" then
defaultGccVersion
else if compiler == "clang" then
defaultClangVersion
else
null
),
stdenv,
compilerName,
}:
let
compilerStdEnv = strToCompilerEnv compiler version;
compilerName =
if compiler == "apple-clang" then
"clang"
else if compiler == "none" then
null
else
compiler;
gccOnMacWarning =
if pkgs.stdenv.isDarwin && compiler == "gcc" then
''
echo "WARNING: Using GCC on macOS with Conan may not work."
echo " Consider using 'nix develop .#clang' or the default shell instead."
echo ""
''
else
"";
compilerVersion =
if compilerName != null then
if compilerName == null then
''echo "No compiler specified - using system compiler"''
else
''
echo "Compiler: "
${compilerName} --version
''
else
''
echo "No compiler specified - using system compiler"
'';
shellAttrs = {
packages = commonPackages;
shellHook = ''
echo "Welcome to xrpld development shell";
${gccOnMacWarning}${compilerVersion}
'';
};
in
pkgs.mkShell.override { stdenv = compilerStdEnv; } shellAttrs;
# Generate shells for each compiler version
gccShells = builtins.listToAttrs (
map (version: {
name = "gcc${toString version}";
value = makeShell {
compiler = "gcc";
version = version;
};
}) gccVersion
);
clangShells = builtins.listToAttrs (
map (version: {
name = "clang${toString version}";
value = makeShell {
compiler = "clang";
version = version;
};
}) clangVersions
);
(pkgs.mkShell.override { inherit stdenv; }) {
packages = commonPackages;
shellHook = ''
echo "Welcome to xrpld development shell";
${compilerVersion}
'';
};
in
gccShells
// clangShells
// {
# Default shells
default = makeShell { };
gcc = makeShell { compiler = "gcc"; };
clang = makeShell { compiler = "clang"; };
rec {
# macOS: Nix Clang. Linux: Nix GCC.
default = if pkgs.stdenv.isDarwin then clang else gcc;
# No compiler
no-compiler = makeShell { compiler = "none"; };
apple-clang = makeShell { compiler = "apple-clang"; };
gcc = makeShell {
stdenv = gccStdenv;
compilerName = "gcc";
};
clang = makeShell {
stdenv = clangStdenv;
compilerName = "clang";
};
# Nix provides no compiler; use the one from your system (e.g. Apple Clang).
no-compiler = makeShell {
stdenv = pkgs.stdenvNoCC;
compilerName = null;
};
apple-clang = no-compiler;
}

View File

@@ -1,15 +1,33 @@
{ pkgs }:
let
# Compiler versions used across the dev shell and the CI environment.
gccVersion = 15;
llvmVersion = 22;
gccPackage = pkgs."gcc${toString gccVersion}";
llvmPackages = pkgs."llvmPackages_${toString llvmVersion}";
# Bound explicitly so it tracks llvmPackages above, not the `with pkgs` default.
clangTools = llvmPackages.clang-tools;
# In LLVM 22, run-clang-tidy.py moved from share/clang/ to bin/, so nixpkgs
# clang-tools no longer links it. Wrap it manually.
runClangTidy = pkgs.writeShellScriptBin "run-clang-tidy" ''
exec ${pkgs.python3}/bin/python3 ${pkgs.llvmPackages_22.clang-unwrapped}/bin/run-clang-tidy "$@"
exec ${pkgs.python3}/bin/python3 ${llvmPackages.clang-unwrapped}/bin/run-clang-tidy "$@"
'';
in
{
inherit
gccVersion
llvmVersion
gccPackage
llvmPackages
;
commonPackages = with pkgs; [
ccache
clangbuildanalyzer
clangTools
cmake
conan
curlMinimal # needed for codecov/codecov-action
@@ -23,7 +41,6 @@ in
gnumake
gnupg # needed for signing commits & codecov/codecov-action
graphviz
llvmPackages_22.clang-tools
less # needed for git diff
mold
nettools # provides netstat, used to debug failures in CI
@@ -32,6 +49,15 @@ in
perl # needed for openssl
pkg-config
pre-commit
# protoc generates the Go gRPC bindings and embeds its own version string into every committed
# .pb.go file. To allow CI to verify those files with a plain `git diff`, we pin the version to
# `protobuf_34` rather than the rolling `protobuf` to keep regeneration reproducible across the
# Nix frequently changing unstable channel. The protoc-gen-go* plugins have no versioned
# attributes in nixpkgs; protoc-gen-go's version is in turn constrained by the go.mod require
# on google.golang.org/protobuf.
protobuf_34 # provides protoc
protoc-gen-go # protoc plugin for the Go message bindings
protoc-gen-go-grpc # protoc plugin for the Go gRPC service stubs
python3
runClangTidy
vim

View File

@@ -876,7 +876,7 @@ Number::operator/=(Number const& y)
int const ds = (dp ? -1 : 1);
// Create the denominator as 128-bit unsigned, since that's what we
// need to work with.
uint128_t const dm = static_cast<uint128_t>(y.mantissa_);
auto const dm = static_cast<uint128_t>(y.mantissa_);
auto const de = y.exponent_;
auto const& range = kRange.get();

View File

@@ -192,7 +192,7 @@ public:
boost::asio::dispatch(
ioContext,
boost::asio::bind_executor(
strand, std::bind(&ResolverAsioImpl::doStop, this, CompletionCounter(this))));
strand, [this, counter = CompletionCounter(this)] { doStop(counter); }));
JLOG(journal.debug()) << "Queued a stop request";
}
@@ -221,9 +221,9 @@ public:
boost::asio::dispatch(
ioContext,
boost::asio::bind_executor(
strand,
std::bind(
&ResolverAsioImpl::doResolve, this, names, handler, CompletionCounter(this))));
strand, [this, names, handler, counter = CompletionCounter(this)] {
doResolve(names, handler, counter);
}));
}
//-------------------------------------------------------------------------
@@ -272,7 +272,7 @@ public:
boost::asio::post(
ioContext,
boost::asio::bind_executor(
strand, std::bind(&ResolverAsioImpl::doWork, this, CompletionCounter(this))));
strand, [this, counter = CompletionCounter(this)] { doWork(counter); }));
}
static HostAndPort
@@ -291,8 +291,10 @@ public:
// a port separator
// Attempt to find the first and last non-whitespace
auto const findWhitespace =
std::bind(&std::isspace<std::string::value_type>, std::placeholders::_1, std::locale());
std::locale const loc;
auto const findWhitespace = [&loc](std::string::value_type c) {
return std::isspace<std::string::value_type>(c, loc);
};
auto hostFirst = std::ranges::find_if_not(str, findWhitespace);
@@ -348,7 +350,7 @@ public:
boost::asio::post(
ioContext,
boost::asio::bind_executor(
strand, std::bind(&ResolverAsioImpl::doWork, this, CompletionCounter(this))));
strand, [this, counter = CompletionCounter(this)] { doWork(counter); }));
return;
}
@@ -356,14 +358,11 @@ public:
resolver.async_resolve(
host,
port,
std::bind(
&ResolverAsioImpl::doFinish,
this,
name,
std::placeholders::_1,
handler,
std::placeholders::_2,
CompletionCounter(this)));
[this, name, handler, counter = CompletionCounter(this)](
boost::system::error_code const& ec,
boost::asio::ip::tcp::resolver::results_type results) {
doFinish(name, ec, handler, results, counter);
});
}
void
@@ -383,8 +382,7 @@ public:
boost::asio::post(
ioContext,
boost::asio::bind_executor(
strand,
std::bind(&ResolverAsioImpl::doWork, this, CompletionCounter(this))));
strand, [this, counter = CompletionCounter(this)] { doWork(counter); }));
}
}
}

View File

@@ -325,9 +325,9 @@ public:
postBuffer(std::string&& buffer)
{
boost::asio::dispatch(
ioContext_,
boost::asio::bind_executor(
strand_, std::bind(&StatsDCollectorImp::doPostBuffer, this, std::move(buffer))));
ioContext_, boost::asio::bind_executor(strand_, [this, buffer = std::move(buffer)] {
doPostBuffer(buffer);
}));
}
// The keepAlive parameter makes sure the buffers sent to
@@ -392,12 +392,10 @@ public:
log(buffers);
socket_.async_send(
buffers,
std::bind(
&StatsDCollectorImp::onSend,
this,
keepAlive,
std::placeholders::_1,
std::placeholders::_2));
[this, keepAlive](
boost::system::error_code const& ec, std::size_t bytesTransferred) {
onSend(keepAlive, ec, bytesTransferred);
});
buffers.clear();
size = 0;
}
@@ -411,12 +409,10 @@ public:
log(buffers);
socket_.async_send(
buffers,
std::bind(
&StatsDCollectorImp::onSend,
this,
keepAlive,
std::placeholders::_1,
std::placeholders::_2));
[this, keepAlive](
boost::system::error_code const& ec, std::size_t bytesTransferred) {
onSend(keepAlive, ec, bytesTransferred);
});
}
}
@@ -425,7 +421,7 @@ public:
{
using namespace std::chrono_literals;
timer_.expires_after(1s);
timer_.async_wait(std::bind(&StatsDCollectorImp::onTimer, this, std::placeholders::_1));
timer_.async_wait([this](boost::system::error_code const& ec) { onTimer(ec); });
}
void
@@ -513,10 +509,9 @@ StatsDCounterImpl::increment(CounterImpl::value_type amount)
{
boost::asio::dispatch(
impl_->getIoContext(),
std::bind(
&StatsDCounterImpl::doIncrement,
std::static_pointer_cast<StatsDCounterImpl>(shared_from_this()),
amount));
[self = std::static_pointer_cast<StatsDCounterImpl>(shared_from_this()), amount] {
self->doIncrement(amount);
});
}
void
@@ -558,10 +553,9 @@ StatsDEventImpl::notify(EventImpl::value_type const& value)
{
boost::asio::dispatch(
impl_->getIoContext(),
std::bind(
&StatsDEventImpl::doNotify,
std::static_pointer_cast<StatsDEventImpl>(shared_from_this()),
value));
[self = std::static_pointer_cast<StatsDEventImpl>(shared_from_this()), value] {
self->doNotify(value);
});
}
void
@@ -591,10 +585,9 @@ StatsDGaugeImpl::set(GaugeImpl::value_type value)
{
boost::asio::dispatch(
impl_->getIoContext(),
std::bind(
&StatsDGaugeImpl::doSet,
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
value));
[self = std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()), value] {
self->doSet(value);
});
}
void
@@ -602,10 +595,9 @@ StatsDGaugeImpl::increment(GaugeImpl::difference_type amount)
{
boost::asio::dispatch(
impl_->getIoContext(),
std::bind(
&StatsDGaugeImpl::doIncrement,
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
amount));
[self = std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()), amount] {
self->doIncrement(amount);
});
}
void
@@ -640,14 +632,14 @@ StatsDGaugeImpl::doIncrement(GaugeImpl::difference_type amount)
if (amount > 0)
{
GaugeImpl::value_type const d(static_cast<GaugeImpl::value_type>(amount));
auto const d = static_cast<GaugeImpl::value_type>(amount);
value += (d >= std::numeric_limits<GaugeImpl::value_type>::max() - value_)
? std::numeric_limits<GaugeImpl::value_type>::max() - value_
: d;
}
else if (amount < 0)
{
GaugeImpl::value_type const d(static_cast<GaugeImpl::value_type>(-amount));
auto const d = static_cast<GaugeImpl::value_type>(-amount);
value = (d >= value) ? 0 : value - d;
}
@@ -678,10 +670,9 @@ StatsDMeterImpl::increment(MeterImpl::value_type amount)
{
boost::asio::dispatch(
impl_->getIoContext(),
std::bind(
&StatsDMeterImpl::doIncrement,
std::static_pointer_cast<StatsDMeterImpl>(shared_from_this()),
amount));
[self = std::static_pointer_cast<StatsDMeterImpl>(shared_from_this()), amount] {
self->doIncrement(amount);
});
}
void

View File

@@ -13,7 +13,6 @@
#include <algorithm>
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <set>
@@ -36,7 +35,7 @@ JobQueue::JobQueue(
{
JLOG(journal_.info()) << "Using " << threadCount << " threads";
hook_ = collector_->makeHook(std::bind(&JobQueue::collect, this));
hook_ = collector_->makeHook([this] { collect(); });
jobCount_ = collector_->makeGauge("job_count");
{
@@ -122,7 +121,7 @@ JobQueue::getJobCount(JobType t) const
{
std::scoped_lock const lock(mutex_);
JobDataMap::const_iterator const c = jobData_.find(t);
auto const c = jobData_.find(t);
return (c == jobData_.end()) ? 0 : c->second.waiting;
}
@@ -132,7 +131,7 @@ JobQueue::getJobCountTotal(JobType t) const
{
std::scoped_lock const lock(mutex_);
JobDataMap::const_iterator const c = jobData_.find(t);
auto const c = jobData_.find(t);
return (c == jobData_.end()) ? 0 : (c->second.waiting + c->second.running);
}
@@ -157,7 +156,7 @@ JobQueue::getJobCountGE(JobType t) const
std::unique_ptr<LoadEvent>
JobQueue::makeLoadEvent(JobType t, std::string const& name)
{
JobDataMap::iterator const iter(jobData_.find(t));
auto const iter = jobData_.find(t);
XRPL_ASSERT(iter != jobData_.end(), "xrpl::JobQueue::makeLoadEvent : valid job type input");
if (iter == jobData_.end())
@@ -172,7 +171,7 @@ JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed)
if (isStopped())
logicError("JobQueue::addLoadEvents() called after JobQueue stopped");
JobDataMap::iterator const iter(jobData_.find(t));
auto const iter = jobData_.find(t);
XRPL_ASSERT(iter != jobData_.end(), "xrpl::JobQueue::addLoadEvents : valid job type input");
iter->second.load().addSamples(count, elapsed);
}
@@ -250,7 +249,7 @@ JobQueue::rendezvous()
JobTypeData&
JobQueue::getJobTypeData(JobType type)
{
JobDataMap::iterator const c(jobData_.find(type));
auto const c = jobData_.find(type);
XRPL_ASSERT(c != jobData_.end(), "xrpl::JobQueue::getJobTypeData : valid job type input");
// NIKB: This is ugly and I hate it. We must remove JtInvalid completely

View File

@@ -434,7 +434,7 @@ RFC1751::getWordFromBlob(void const* blob, size_t bytes)
// This is a simple implementation of the Jenkins one-at-a-time hash
// algorithm:
// http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time
unsigned char const* data = static_cast<unsigned char const*>(blob);
auto const* data = static_cast<unsigned char const*>(blob);
std::uint32_t hash = 0;
for (size_t i = 0; i < bytes; ++i)

View File

@@ -230,9 +230,8 @@ Writer::~Writer()
impl_->finishAll();
}
Writer::Writer(Writer&& w) noexcept
Writer::Writer(Writer&& w) noexcept : impl_(std::move(w.impl_))
{
impl_ = std::move(w.impl_);
}
Writer&

View File

@@ -5,12 +5,13 @@
#include <algorithm>
#include <cctype>
#include <charconv>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <istream>
#include <stdexcept>
#include <string>
#include <system_error>
namespace json {
// Implementation of class Reader
@@ -86,8 +87,8 @@ Reader::parse(char const* beginDoc, char const* endDoc, Value& root)
begin_ = beginDoc;
end_ = endDoc;
current_ = begin_;
lastValueEnd_ = 0;
lastValue_ = 0;
lastValueEnd_ = nullptr;
lastValue_ = nullptr;
errors_.clear();
while (!nodes_.empty())
@@ -605,34 +606,17 @@ bool
Reader::decodeDouble(Token& token)
{
double value = 0;
int const bufferSize = 32;
int count = 0;
int const length = int(token.end - token.start);
// Sanity check to avoid buffer overflow exploits.
if (length < 0)
{
return addError("Unable to parse token length", token);
}
// Avoid using a string constant for the format control string given to
// sscanf, as this can cause hard to debug crashes on OS X. See here for
// more info:
//
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
char format[] = "%lf";
if (length <= bufferSize)
{
Char buffer[bufferSize + 1];
memcpy(buffer, token.start, length);
buffer[length] = 0;
count = sscanf(buffer, format, &value);
}
else
{
std::string const buffer(token.start, token.end);
count = sscanf(buffer.c_str(), format, &value);
}
if (count != 1)
auto const [ptr, ec] = std::from_chars(token.start, token.end, value);
// Reject anything from_chars could not turn into a finite double:
// - ec != std::errc{}: no valid conversion, or an out-of-range magnitude
// (e.g. 1e400).
// - ptr != token.end: readNumber() is permissive about which characters
// it collects into a token (it will, for example, keep a '+' mid-token),
// but from_chars() will stop at the first character it cannot parse.
if (ec != std::errc{} || ptr != token.end)
return addError("'" + std::string(token.start, token.end) + "' is not a number.", token);
currentValue() = value;
return true;
}
@@ -908,9 +892,8 @@ Reader::getFormattedErrorMessages() const
{
std::string formattedMessage;
for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
for (auto const& error : errors_)
{
ErrorInfo const& error = *itError;
formattedMessage += "* " + getLocationLineAndColumn(error.token.start) + "\n";
formattedMessage += " " + error.message + "\n";

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