overflow_controlled_integer_accumulator.hpp
Go to the documentation of this file.
/*
* RESTinio
*/
#pragma once
#include <restinio/compiler_features.hpp>
#include <type_traits>
#include <limits>
namespace restinio
{
namespace impl
{
//
// check_positive_extremum
//
struct check_positive_extremum {};
//
// check_negative_extremum
//
struct check_negative_extremum {};
namespace overflow_controlled_integer_accumulator_details
{
template< typename T, typename Storage_Type >
RESTINIO_NODISCARD
typename std::enable_if< std::is_signed<T>::value, bool >::type
is_greater_than_maximum( Storage_Type v, Storage_Type maximum )
{
return v > maximum;
}
// If T is unsigned type then this comparison has no sense.
template< typename T, typename Storage_Type >
RESTINIO_NODISCARD
typename std::enable_if< !std::is_signed<T>::value, bool >::type
is_greater_than_maximum( Storage_Type, Storage_Type )
{
return false;
}
//
// extremum_value
//
template< typename T, typename Ext >
struct extremum_value;
template< typename T >
struct extremum_value< T, check_positive_extremum >
{
using storage_type = std::make_unsigned_t<T>;
static constexpr storage_type value = static_cast<storage_type>(
std::numeric_limits<T>::max() );
};
template< typename T >
struct extremum_value< T, check_negative_extremum >
{
static_assert( std::is_signed<T>::value,
"extremum_value<T, check_negative_extremum> is defined only "
"for signed numeric types" );
using storage_type = std::make_unsigned_t<T>;
static constexpr storage_type value = static_cast<storage_type>(
std::numeric_limits<T>::min() );
static_assert(
value == (static_cast<storage_type>(std::numeric_limits<T>::max()) + 1u),
"The integer representation is expected to be two's complement" );
};
} /* namespace overflow_controlled_integer_accumulator_details */
//
// overflow_controlled_integer_accumulator_t
//
template<
typename T,
int Multiplier,
typename Extremum_Type = check_positive_extremum >
class overflow_controlled_integer_accumulator_t
{
using extremum_value =
overflow_controlled_integer_accumulator_details::extremum_value<
T,
Extremum_Type >;
using storage_type = typename extremum_value::storage_type;
storage_type m_current{};
bool m_overflow_detected{ false };
public :
void
next_digit( T digit ) noexcept
{
using namespace overflow_controlled_integer_accumulator_details;
constexpr storage_type multiplier{
static_cast<storage_type>(Multiplier)
};
const storage_type updated_value = m_current * multiplier +
static_cast<storage_type>(digit);
if( updated_value < m_current ||
is_greater_than_maximum<T>( updated_value, extremum_value::value ) )
m_overflow_detected = true;
else
m_current = updated_value;
}
bool
overflow_detected() const noexcept
{
return m_overflow_detected;
}
T
value() const noexcept
{
return static_cast<T>(m_current);
}
};
} /* namespace restinio */
} /* namespace restinio */
restinio::impl::overflow_controlled_integer_accumulator_t
Helper class for accumulating integer value during parsing it from string (with check for overflow).
Definition: overflow_controlled_integer_accumulator.hpp:136
restinio::impl::overflow_controlled_integer_accumulator_t::m_current
storage_type m_current
The current value of the accumulator.
Definition: overflow_controlled_integer_accumulator.hpp:146
restinio::impl::overflow_controlled_integer_accumulator_t::next_digit
void next_digit(T digit) noexcept
Try to add another digit to the accumulator.
Definition: overflow_controlled_integer_accumulator.hpp:156
restinio::impl::overflow_controlled_integer_accumulator_t::storage_type
typename extremum_value::storage_type storage_type
Type to be used for holding intermediate value.
Definition: overflow_controlled_integer_accumulator.hpp:143
restinio::impl::overflow_controlled_integer_accumulator_t::value
T value() const noexcept
Get the current accumulator value.
Definition: overflow_controlled_integer_accumulator.hpp:183
restinio::impl::overflow_controlled_integer_accumulator_t::overflow_detected
bool overflow_detected() const noexcept
Is overflow detected during previous call to next_digit?
Definition: overflow_controlled_integer_accumulator.hpp:176
restinio::impl::overflow_controlled_integer_accumulator_t::m_overflow_detected
bool m_overflow_detected
Overflow detection flag.
Definition: overflow_controlled_integer_accumulator.hpp:148
compiler_features.hpp
Detection of compiler version and absence of various features.
RESTINIO_NODISCARD
#define RESTINIO_NODISCARD
Definition: compiler_features.hpp:33
restinio::easy_parser::digit
RESTINIO_NODISCARD auto digit() noexcept
A factory function to create a clause that expects a decimal digit, extracts it and then skips it.
Definition: easy_parser.hpp:4154
restinio::http_field_parsers::qvalue_details::maximum
constexpr underlying_uint_t maximum
The maximal allowed value for a qvalue.
Definition: basics.hpp:39
restinio::impl::overflow_controlled_integer_accumulator_details::is_greater_than_maximum
RESTINIO_NODISCARD std::enable_if< std::is_signed< T >::value, bool >::type is_greater_than_maximum(Storage_Type v, Storage_Type maximum)
Definition: overflow_controlled_integer_accumulator.hpp:41
restinio
Definition: asio_include.hpp:21
restinio::impl::check_negative_extremum
Definition: overflow_controlled_integer_accumulator.hpp:33
restinio::impl::check_positive_extremum
Definition: overflow_controlled_integer_accumulator.hpp:28
restinio::impl::overflow_controlled_integer_accumulator_details::extremum_value
Definition: overflow_controlled_integer_accumulator.hpp:59
restinio::impl::overflow_controlled_integer_accumulator_details::extremum_value< T, check_positive_extremum >::storage_type
std::make_unsigned_t< T > storage_type
Definition: overflow_controlled_integer_accumulator.hpp:64
restinio::impl::overflow_controlled_integer_accumulator_details::extremum_value< T, check_negative_extremum >::storage_type
std::make_unsigned_t< T > storage_type
Definition: overflow_controlled_integer_accumulator.hpp:77
const
#define const
Definition: zconf.h:230