#include <xrpl/basics/contract.h>

#include <xrpl/beast/core/LexicalCast.h>

#include <xrpl/beast/core/SemanticVersion.h>

#include <xrpl/protocol/BuildInfo.h>

#include <boost/preprocessor/stringize.hpp>

#include <algorithm>

#include <optional>

namespace ripple {

namespace BuildInfo {

char const



const versionString = "2.3.0



b1"

#if defined(DEBUG) || defined(SANITIZER)

"+"

#ifdef GIT_COMMIT_HASH

GIT_COMMIT_HASH

"."

#endif

#ifdef DEBUG

"DEBUG"

#ifdef SANITIZER

"."

#endif

#endif

#ifdef SANITIZER

BOOST_PP_STRINGIZE(SANITIZER)

#endif

#endif

;

std::string const& getVersionString() { static std::string const value = [] { std::string const s = versionString; beast::SemanticVersion v; if (!v.parse(s) || v.print() != s) LogicError(s + ": Bad server version string"); return s; }(); return value; }

std::string const& getFullVersionString() { static std::string const value = "rippled-" + getVersionString(); return value; }

static constexpr std::uint64_t implementationVersionIdentifier = 0x183B'0000'0000'0000LLU; static constexpr std::uint64_t implementationVersionIdentifierMask = 0xFFFF'0000'0000'0000LLU;

std::uint64_t

encodeSoftwareVersion(char const



const versionStr)

{

std::uint64_t c = implementationVersionIdentifier;

beast::SemanticVersion v;

if (v.parse(std::string(versionStr))) { if (v.majorVersion >= 0 && v.majorVersion <= 255) c |= static_cast<std::uint64_t>(v.majorVersion) << 40;

if (v.minorVersion >= 0 && v.minorVersion <= 255) c |= static_cast<std::uint64_t>(v.minorVersion) << 32;

if (v.patchVersion >= 0 && v.patchVersion <= 255) c |= static_cast<std::uint64_t>(v.patchVersion) << 24;

if (!v.isPreRelease())

c |= static_cast<std::uint64_t>(0xC00000);

if (v.isPreRelease())

{

std::uint8_t x = 0;

for (auto id : v.preReleaseIdentifiers) { auto parsePreRelease = [](std::string_view identifier, std::string_view prefix, std::uint8_t key, std::uint8_t lok, std::uint8_t hik) -> std::uint8_t { std::uint8_t ret = 0;

if (prefix != identifier.substr(0, prefix.length())) return 0;

if (!beast::lexicalCastChecked(

ret,

std::string(identifier.substr(prefix.length()))))

return 0;

if (std::clamp(ret, lok, hik) != ret) return 0;

return ret + key;

};

x = parsePreRelease(id, "rc", 0x80, 0, 63);

if (x == 0) x = parsePreRelease(id, "b", 0x40, 0, 63);

if (x & 0xC0) { c |= static_cast<std::uint64_t>(x) << 16; break; } } } }

return c;

}

std::uint64_t getEncodedVersion() { static std::uint64_t const cookie = {encodeSoftwareVersion(versionString)}; return cookie; }

bool isRippledVersion(std::uint64_t version) { return (version & implementationVersionIdentifierMask) == implementationVersionIdentifier; }

bool

isNewerVersion(std::uint64_t version)

{

if (isRippledVersion(version))

return version > getEncodedVersion();

return false;

}

}

}