| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef RIPPLE_RPC_CTID_H_INCLUDED |
| #define RIPPLE_RPC_CTID_H_INCLUDED |
|
|
| #include <boost/algorithm/string/predicate.hpp> |
| #include <boost/regex.hpp> |
| #include <optional> |
| #include <regex> |
| #include <sstream> |
|
|
| namespace ripple { |
|
|
| namespace RPC { |
|
|
| inline std::optional<std::string> |
| encodeCTID( |
| uint32_t ledger_seq, |
| uint16_t txn_index, |
| uint16_t network_id) noexcept |
| { |
| if (ledger_seq > 0x0FFF'FFFF) |
| return {}; |
|
|
| uint64_t ctidValue = |
| ((0xC000'0000ULL + static_cast<uint64_t>(ledger_seq)) << 32) + |
| (static_cast<uint64_t>(txn_index) << 16) + network_id; |
|
|
| std::stringstream buffer; |
| buffer << std::hex << std::uppercase << std::setfill('0') << std::setw(16) |
| << ctidValue; |
| return {buffer.str()}; |
| } |
|
|
| template <typename T> |
| inline std::optional<std::tuple<uint32_t, uint16_t, uint16_t>> |
| decodeCTID(const T ctid) noexcept |
| { |
| uint64_t ctidValue{0}; |
| if constexpr ( |
| std::is_same_v<T, std::string> || std::is_same_v<T, char*> || |
| std::is_same_v<T, const char*> || std::is_same_v<T, std::string_view>) |
| { |
| std::string const ctidString(ctid); |
|
|
| if (ctidString.length() != 16) |
| return {}; |
|
|
| if (!boost::regex_match(ctidString, boost::regex("^[0-9A-F]+$"))) |
| return {}; |
|
|
| ctidValue = std::stoull(ctidString, nullptr, 16); |
| } |
| else if constexpr (std::is_integral_v<T>) |
| ctidValue = ctid; |
| else |
| return {}; |
|
|
| if ((ctidValue & 0xF000'0000'0000'0000ULL) != 0xC000'0000'0000'0000ULL) |
| return {}; |
|
|
| uint32_t ledger_seq = (ctidValue >> 32) & 0xFFFF'FFFUL; |
| uint16_t txn_index = (ctidValue >> 16) & 0xFFFFU; |
| uint16_t network_id = ctidValue & 0xFFFFU; |
| return {{ledger_seq, txn_index, network_id}}; |
| } |
|
|
| } |
| } |
|
|
| #endif |
|
|