RESTinio
overflow_controlled_integer_accumulator.hpp
Go to the documentation of this file.
1 /*
2  * RESTinio
3  */
4 
12 #pragma once
13 
15 
16 #include <type_traits>
17 #include <limits>
18 
19 namespace restinio
20 {
21 
22 namespace impl
23 {
24 
25 //
26 // check_positive_extremum
27 //
29 
30 //
31 // check_negative_extremum
32 //
34 
35 namespace overflow_controlled_integer_accumulator_details
36 {
37 
38 template< typename T, typename Storage_Type >
40 typename std::enable_if< std::is_signed<T>::value, bool >::type
41 is_greater_than_maximum( Storage_Type v, Storage_Type maximum )
42 {
43  return v > maximum;
44 }
45 
46 // If T is unsigned type then this comparison has no sense.
47 template< typename T, typename Storage_Type >
49 typename std::enable_if< !std::is_signed<T>::value, bool >::type
50 is_greater_than_maximum( Storage_Type, Storage_Type )
51 {
52  return false;
53 }
54 
55 //
56 // extremum_value
57 //
58 template< typename T, typename Ext >
60 
61 template< typename T >
63 {
64  using storage_type = std::make_unsigned_t<T>;
65 
66  static constexpr storage_type value = static_cast<storage_type>(
67  std::numeric_limits<T>::max() );
68 };
69 
70 template< typename T >
72 {
73  static_assert( std::is_signed<T>::value,
74  "extremum_value<T, check_negative_extremum> is defined only "
75  "for signed numeric types" );
76 
77  using storage_type = std::make_unsigned_t<T>;
78 
79  static constexpr storage_type value = static_cast<storage_type>(
80  std::numeric_limits<T>::min() );
81 
82  static_assert(
83  value == (static_cast<storage_type>(std::numeric_limits<T>::max()) + 1u),
84  "The integer representation is expected to be two's complement" );
85 };
86 
87 } /* namespace overflow_controlled_integer_accumulator_details */
88 
89 //
90 // overflow_controlled_integer_accumulator_t
91 //
131 template<
132  typename T,
133  int Multiplier,
134  typename Extremum_Type = check_positive_extremum >
136 {
137  using extremum_value =
139  T,
140  Extremum_Type >;
141 
143  using storage_type = typename extremum_value::storage_type;
144 
148  bool m_overflow_detected{ false };
149 
150 public :
152 
155  void
156  next_digit( T digit ) noexcept
157  {
158  using namespace overflow_controlled_integer_accumulator_details;
159 
160  constexpr storage_type multiplier{
161  static_cast<storage_type>(Multiplier)
162  };
163 
164  const storage_type updated_value = m_current * multiplier +
165  static_cast<storage_type>(digit);
166 
167  if( updated_value < m_current ||
168  is_greater_than_maximum<T>( updated_value, extremum_value::value ) )
169  m_overflow_detected = true;
170  else
171  m_current = updated_value;
172  }
173 
175  bool
177  {
178  return m_overflow_detected;
179  }
180 
182  T
183  value() const noexcept
184  {
185  return static_cast<T>(m_current);
186  }
187 };
188 
189 } /* namespace restinio */
190 
191 } /* namespace restinio */
192 
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_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::impl::check_positive_extremum
Definition: overflow_controlled_integer_accumulator.hpp:28
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_details::extremum_value< T, check_negative_extremum >::storage_type
std::make_unsigned_t< T > storage_type
Definition: overflow_controlled_integer_accumulator.hpp:77
restinio::impl::overflow_controlled_integer_accumulator_t::m_overflow_detected
bool m_overflow_detected
Overflow detection flag.
Definition: overflow_controlled_integer_accumulator.hpp:148
restinio::impl::overflow_controlled_integer_accumulator_details::extremum_value
Definition: overflow_controlled_integer_accumulator.hpp:59
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_details::extremum_value< T, check_positive_extremum >::storage_type
std::make_unsigned_t< T > storage_type
Definition: overflow_controlled_integer_accumulator.hpp:64
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::check_negative_extremum
Definition: overflow_controlled_integer_accumulator.hpp:33
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::value
T value() const noexcept
Get the current accumulator value.
Definition: overflow_controlled_integer_accumulator.hpp:183
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
Definition: asio_include.hpp:21
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
compiler_features.hpp
Detection of compiler version and absence of various features.
const
#define const
Definition: zconf.h:230