]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/safe_numerics/exception.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / safe_numerics / exception.hpp
CommitLineData
92f5a8d4
TL
1#ifndef BOOST_NUMERIC_EXCEPTION
2#define BOOST_NUMERIC_EXCEPTION
3
4// Copyright (c) 2012 Robert Ramey
5//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
10// contains error indicators for results of doing checked
11// arithmetic on native C++ types
12
13#include <algorithm>
14#include <system_error> // error_code, system_error
15#include <string>
16#include <cassert>
17#include <cstdint> // std::uint8_t
18
19// Using the system_error code facility. This facility is more complex
20// than meets the eye. To fully understand what out intent here is,
21// review http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-5.html
22// "Giving context-specific meaning to generic error codes"
23
24namespace boost {
25namespace safe_numerics {
26
27// errors codes for safe numerics
28
29// in spite of the similarity, this list is distinct from the exceptions
30// listed in documentation for std::exception.
31
32// note: Don't reorder these. Code in the file checked_result_operations.hpp
33// depends upon this order !!!
34enum class safe_numerics_error : std::uint8_t {
35 success = 0,
36 positive_overflow_error, // result is above representational maximum
37 negative_overflow_error, // result is below representational minimum
38 domain_error, // one operand is out of valid range
39 range_error, // result cannot be produced for this operation
40 precision_overflow_error, // result lost precision
41 underflow_error, // result is too small to be represented
42 negative_value_shift, // negative value in shift operator
43 negative_shift, // shift a negative value
44 shift_too_large, // l/r shift exceeds variable size
45 uninitialized_value // creating of uninitialized value
46};
47
20effc67
TL
48const char * literal_string(const safe_numerics_error & e){
49 switch(e){
50 case safe_numerics_error::success: return "success";
51 case safe_numerics_error::positive_overflow_error: return "positive_overflow_error";
52 case safe_numerics_error::negative_overflow_error: return "negative_overflow_error";
53 case safe_numerics_error::domain_error: return "domain_error";
54 case safe_numerics_error::range_error: return "range_error";
55 case safe_numerics_error::precision_overflow_error: return "precision_overflow_error";
56 case safe_numerics_error::underflow_error: return "underflow_error";
57 case safe_numerics_error::negative_value_shift: return "negative_value_shift";
58 case safe_numerics_error::negative_shift: return "negative_shift";
59 case safe_numerics_error::shift_too_large: return "shift_too_large";
60 case safe_numerics_error::uninitialized_value: return "uninitialized_value";
61 default:
62 assert(false); // should never arrive here
63 }
64}
65
92f5a8d4
TL
66const std::uint8_t safe_numerics_casting_error_count =
67 static_cast<std::uint8_t>(safe_numerics_error::domain_error) + 1;
68
69const std::uint8_t safe_numerics_error_count =
70 static_cast<std::uint8_t>(safe_numerics_error::uninitialized_value) + 1;
71
72} // safe_numerics
73} // boost
74
75namespace std {
76 template <>
77 struct is_error_code_enum<boost::safe_numerics::safe_numerics_error>
78 : public true_type {};
79} // std
80
81namespace boost {
82namespace safe_numerics {
83
84const class : public std::error_category {
85public:
86 virtual const char* name() const noexcept{
87 return "safe numerics error";
88 }
89 virtual std::string message(int ev) const {
90 switch(static_cast<safe_numerics_error>(ev)){
91 case safe_numerics_error::success:
92 return "success";
93 case safe_numerics_error::positive_overflow_error:
94 return "positive overflow error";
95 case safe_numerics_error::negative_overflow_error:
96 return "negative overflow error";
97 case safe_numerics_error::underflow_error:
98 return "underflow error";
99 case safe_numerics_error::range_error:
100 return "range error";
f67539c2
TL
101 case safe_numerics_error::precision_overflow_error:
102 return "precision_overflow_error";
92f5a8d4
TL
103 case safe_numerics_error::domain_error:
104 return "domain error";
105 case safe_numerics_error::negative_shift:
106 return "negative shift";
107 case safe_numerics_error::negative_value_shift:
108 return "negative value shift";
109 case safe_numerics_error::shift_too_large:
110 return "shift too large";
111 case safe_numerics_error::uninitialized_value:
112 return "uninitialized value";
113 default:
114 assert(false);
115 }
116 return ""; // suppress bogus warning
117 }
118} safe_numerics_error_category {};
119
120// constexpr - damn, can't use constexpr due to std::error_code
121inline std::error_code make_error_code(const safe_numerics_error & e){
122 return std::error_code(static_cast<int>(e), safe_numerics_error_category);
123}
124
125// actions for error_codes for safe numerics. I've leveraged on
126// error_condition in order to do this. I'm not sure this is a good
127// idea or not.
128
129enum class safe_numerics_actions {
130 no_action = 0,
131 uninitialized_value,
132 arithmetic_error,
133 implementation_defined_behavior,
134 undefined_behavior
135};
136
137} // safe_numerics
138} // boost
139
140namespace std {
141 template <>
142 struct is_error_condition_enum<boost::safe_numerics::safe_numerics_actions>
143 : public true_type {};
144} // std
145
146namespace boost {
147namespace safe_numerics {
148
149const class : public std::error_category {
150public:
151 virtual const char* name() const noexcept {
152 return "safe numerics error group";
153 }
154 virtual std::string message(int) const {
155 return "safe numerics error group";
156 }
157 // return true if a given error code corresponds to a
158 // given safe numeric action
159 virtual bool equivalent(
160 const std::error_code & code,
161 int condition
162 ) const noexcept {
163 if(code.category() != safe_numerics_error_category)
164 return false;
165 switch (static_cast<safe_numerics_actions>(condition)){
166 case safe_numerics_actions::no_action:
167 return code == safe_numerics_error::success;
168 case safe_numerics_actions::uninitialized_value:
169 return code == safe_numerics_error::uninitialized_value;
170 case safe_numerics_actions::arithmetic_error:
171 return code == safe_numerics_error::positive_overflow_error
172 || code == safe_numerics_error::negative_overflow_error
173 || code == safe_numerics_error::underflow_error
174 || code == safe_numerics_error::range_error
175 || code == safe_numerics_error::domain_error;
176 case safe_numerics_actions::implementation_defined_behavior:
177 return code == safe_numerics_error::negative_value_shift
178 || code == safe_numerics_error::negative_shift
179 || code == safe_numerics_error::shift_too_large;
180 case safe_numerics_actions::undefined_behavior:
181 return false;
182 default:
183 ;
184 }
185 // should never arrive here
186 assert(false);
187 // suppress bogus warning
188 return false;
189 }
190} safe_numerics_actions_category {};
191
192// the following function is used to "finish" implementation of conversion
193// of safe_numerics_error to std::error_condition. At least for now, this
194// isn't being used and defining here it can lead duplicate symbol errors
195// depending on the compiler. So suppress it until further notice
196#if 0
197std::error_condition make_error_condition(const safe_numerics_error & e) {
198 return std::error_condition(
199 static_cast<int>(e),
200 safe_numerics_error_category
201 );
202}
203#endif
204
205} // safe_numerics
206} // boost
207
208#endif // BOOST_NUMERIC_CHECKED_RESULT