RESTinio

overflow_controlled_integer_accumulator.hpp
Go to the documentation of this file.
1/*
2 * RESTinio
3 */
4
12#pragma once
13
14#include <restinio/compiler_features.hpp>
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//
28 struct check_positive_extremum {};
29
30//
31// check_negative_extremum
32//
33 struct check_negative_extremum {};
34
35 namespace overflow_controlled_integer_accumulator_details
36{
37
38 template< typename T, typename Storage_Type >
39 RESTINIO_NODISCARD
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 >
48 RESTINIO_NODISCARD
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 >
59 struct extremum_value;
60
61 template< typename T >
62 struct extremum_value< T, check_positive_extremum >
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 >
71 struct extremum_value< T, check_negative_extremum >
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 >
135 class overflow_controlled_integer_accumulator_t
136{
137 using extremum_value =
138 overflow_controlled_integer_accumulator_details::extremum_value<
139 T,
140 Extremum_Type >;
141
143 using storage_type = typename extremum_value::storage_type;
144
146 storage_type m_current{};
148 bool m_overflow_detected{ false };
149
150public :
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
176 overflow_detected() const noexcept
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_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