mirror of
https://github.com/vtnerd/monero-lws.git
synced 2025-04-02 20:09:03 +00:00
Fixed integer conversion in wire::
This commit is contained in:
parent
ab83c662f0
commit
6c185a406b
2 changed files with 17 additions and 22 deletions
|
@ -35,9 +35,12 @@ void wire::reader::increment_depth()
|
|||
WIRE_DLOG_THROW_(error::schema::maximum_depth);
|
||||
}
|
||||
|
||||
[[noreturn]] void wire::integer::throw_exception(std::intmax_t source, std::intmax_t min)
|
||||
[[noreturn]] void wire::integer::throw_exception(std::intmax_t source, std::intmax_t min, std::uintmax_t max)
|
||||
{
|
||||
WIRE_DLOG_THROW(error::schema::larger_integer, source << " given when " << min << " is minimum permitted");
|
||||
if (source < 0)
|
||||
WIRE_DLOG_THROW(error::schema::larger_integer, source << " given when " << min << " is minimum permitted");
|
||||
else
|
||||
throw_exception(std::uintmax_t(source), max);
|
||||
}
|
||||
[[noreturn]] void wire::integer::throw_exception(std::uintmax_t source, std::uintmax_t max)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/lexical_cast/try_lexical_convert.hpp>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
@ -167,33 +168,24 @@ namespace wire
|
|||
|
||||
namespace integer
|
||||
{
|
||||
[[noreturn]] void throw_exception(std::intmax_t source, std::intmax_t min);
|
||||
[[noreturn]] void throw_exception(std::intmax_t source, std::intmax_t min, std::uintmax_t max);
|
||||
[[noreturn]] void throw_exception(std::uintmax_t source, std::uintmax_t max);
|
||||
|
||||
template<typename Target, typename U>
|
||||
inline Target convert_to(const U source)
|
||||
{
|
||||
using common = typename std::common_type<Target, U>::type;
|
||||
static constexpr const Target target_min = std::numeric_limits<Target>::min();
|
||||
static constexpr const Target target_max = std::numeric_limits<Target>::max();
|
||||
|
||||
/* After optimizations, this is:
|
||||
* 1 check for unsigned -> unsigned (uint, uint)
|
||||
* 2 checks for signed -> signed (int, int)
|
||||
* 2 checks for signed -> unsigned-- (
|
||||
* 1 check for unsigned -> signed (uint, uint)
|
||||
|
||||
Put `WIRE_DLOG_THROW` in cpp to reduce code/ASM duplication. Do not
|
||||
remove first check, signed values can be implicitly converted to
|
||||
unsigned in some checks. */
|
||||
if (!std::numeric_limits<Target>::is_signed && source < 0)
|
||||
throw_exception(std::intmax_t(source), std::intmax_t(0));
|
||||
else if (common(source) < common(target_min))
|
||||
throw_exception(std::intmax_t(source), std::intmax_t(target_min));
|
||||
else if (common(target_max) < common(source))
|
||||
throw_exception(std::uintmax_t(source), std::uintmax_t(target_max));
|
||||
|
||||
return Target(source);
|
||||
|
||||
Target out = 0;
|
||||
if (!boost::conversion::try_lexical_convert(source, out))
|
||||
{
|
||||
if (std::numeric_limits<U>::is_signed)
|
||||
throw_exception(std::intmax_t(source), target_min, target_max);
|
||||
else
|
||||
throw_exception(std::uintmax_t(source), target_max);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue