]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/outcome/experimental/status-code/generic_code.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / outcome / experimental / status-code / generic_code.hpp
CommitLineData
92f5a8d4 1/* Proposed SG14 status_code
20effc67 2(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
92f5a8d4
TL
3File Created: Feb 2018
4
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License in the accompanying file
9Licence.txt or at
10
11http://www.apache.org/licenses/LICENSE-2.0
12
13Unless required by applicable law or agreed to in writing, software
14distributed under the License is distributed on an "AS IS" BASIS,
15WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16See the License for the specific language governing permissions and
17limitations under the License.
18
19
20Distributed under the Boost Software License, Version 1.0.
21(See accompanying file Licence.txt or copy at
22http://www.boost.org/LICENSE_1_0.txt)
23*/
24
25#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
26#define BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
27
28#include "status_error.hpp"
29
30#include <cerrno> // for error constants
31
32BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
33
34//! The generic error coding (POSIX)
35enum class errc : int
36{
37 success = 0,
38 unknown = -1,
39
40 address_family_not_supported = EAFNOSUPPORT,
41 address_in_use = EADDRINUSE,
42 address_not_available = EADDRNOTAVAIL,
43 already_connected = EISCONN,
44 argument_list_too_long = E2BIG,
45 argument_out_of_domain = EDOM,
46 bad_address = EFAULT,
47 bad_file_descriptor = EBADF,
48 bad_message = EBADMSG,
49 broken_pipe = EPIPE,
50 connection_aborted = ECONNABORTED,
51 connection_already_in_progress = EALREADY,
52 connection_refused = ECONNREFUSED,
53 connection_reset = ECONNRESET,
54 cross_device_link = EXDEV,
55 destination_address_required = EDESTADDRREQ,
56 device_or_resource_busy = EBUSY,
57 directory_not_empty = ENOTEMPTY,
58 executable_format_error = ENOEXEC,
59 file_exists = EEXIST,
60 file_too_large = EFBIG,
61 filename_too_long = ENAMETOOLONG,
62 function_not_supported = ENOSYS,
63 host_unreachable = EHOSTUNREACH,
64 identifier_removed = EIDRM,
65 illegal_byte_sequence = EILSEQ,
66 inappropriate_io_control_operation = ENOTTY,
67 interrupted = EINTR,
68 invalid_argument = EINVAL,
69 invalid_seek = ESPIPE,
70 io_error = EIO,
71 is_a_directory = EISDIR,
72 message_size = EMSGSIZE,
73 network_down = ENETDOWN,
74 network_reset = ENETRESET,
75 network_unreachable = ENETUNREACH,
76 no_buffer_space = ENOBUFS,
77 no_child_process = ECHILD,
78 no_link = ENOLINK,
79 no_lock_available = ENOLCK,
80 no_message = ENOMSG,
81 no_protocol_option = ENOPROTOOPT,
82 no_space_on_device = ENOSPC,
83 no_stream_resources = ENOSR,
84 no_such_device_or_address = ENXIO,
85 no_such_device = ENODEV,
86 no_such_file_or_directory = ENOENT,
87 no_such_process = ESRCH,
88 not_a_directory = ENOTDIR,
89 not_a_socket = ENOTSOCK,
90 not_a_stream = ENOSTR,
91 not_connected = ENOTCONN,
92 not_enough_memory = ENOMEM,
93 not_supported = ENOTSUP,
94 operation_canceled = ECANCELED,
95 operation_in_progress = EINPROGRESS,
96 operation_not_permitted = EPERM,
97 operation_not_supported = EOPNOTSUPP,
98 operation_would_block = EWOULDBLOCK,
99 owner_dead = EOWNERDEAD,
100 permission_denied = EACCES,
f67539c2 101 protocol_error = EPROTO,
92f5a8d4
TL
102 protocol_not_supported = EPROTONOSUPPORT,
103 read_only_file_system = EROFS,
104 resource_deadlock_would_occur = EDEADLK,
105 resource_unavailable_try_again = EAGAIN,
106 result_out_of_range = ERANGE,
107 state_not_recoverable = ENOTRECOVERABLE,
108 stream_timeout = ETIME,
109 text_file_busy = ETXTBSY,
110 timed_out = ETIMEDOUT,
111 too_many_files_open_in_system = ENFILE,
112 too_many_files_open = EMFILE,
113 too_many_links = EMLINK,
114 too_many_symbolic_link_levels = ELOOP,
115 value_too_large = EOVERFLOW,
116 wrong_protocol_type = EPROTOTYPE
117};
118
119namespace detail
120{
121 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline const char *generic_code_message(errc code) noexcept
122 {
123 switch(code)
124 {
125 case errc::success:
126 return "Success";
127 case errc::address_family_not_supported:
128 return "Address family not supported by protocol";
129 case errc::address_in_use:
130 return "Address already in use";
131 case errc::address_not_available:
132 return "Cannot assign requested address";
133 case errc::already_connected:
134 return "Transport endpoint is already connected";
135 case errc::argument_list_too_long:
136 return "Argument list too long";
137 case errc::argument_out_of_domain:
138 return "Numerical argument out of domain";
139 case errc::bad_address:
140 return "Bad address";
141 case errc::bad_file_descriptor:
142 return "Bad file descriptor";
143 case errc::bad_message:
144 return "Bad message";
145 case errc::broken_pipe:
146 return "Broken pipe";
147 case errc::connection_aborted:
148 return "Software caused connection abort";
149 case errc::connection_already_in_progress:
150 return "Operation already in progress";
151 case errc::connection_refused:
152 return "Connection refused";
153 case errc::connection_reset:
154 return "Connection reset by peer";
155 case errc::cross_device_link:
156 return "Invalid cross-device link";
157 case errc::destination_address_required:
158 return "Destination address required";
159 case errc::device_or_resource_busy:
160 return "Device or resource busy";
161 case errc::directory_not_empty:
162 return "Directory not empty";
163 case errc::executable_format_error:
164 return "Exec format error";
165 case errc::file_exists:
166 return "File exists";
167 case errc::file_too_large:
168 return "File too large";
169 case errc::filename_too_long:
170 return "File name too long";
171 case errc::function_not_supported:
172 return "Function not implemented";
173 case errc::host_unreachable:
174 return "No route to host";
175 case errc::identifier_removed:
176 return "Identifier removed";
177 case errc::illegal_byte_sequence:
178 return "Invalid or incomplete multibyte or wide character";
179 case errc::inappropriate_io_control_operation:
180 return "Inappropriate ioctl for device";
181 case errc::interrupted:
182 return "Interrupted system call";
183 case errc::invalid_argument:
184 return "Invalid argument";
185 case errc::invalid_seek:
186 return "Illegal seek";
187 case errc::io_error:
188 return "Input/output error";
189 case errc::is_a_directory:
190 return "Is a directory";
191 case errc::message_size:
192 return "Message too long";
193 case errc::network_down:
194 return "Network is down";
195 case errc::network_reset:
196 return "Network dropped connection on reset";
197 case errc::network_unreachable:
198 return "Network is unreachable";
199 case errc::no_buffer_space:
200 return "No buffer space available";
201 case errc::no_child_process:
202 return "No child processes";
203 case errc::no_link:
204 return "Link has been severed";
205 case errc::no_lock_available:
206 return "No locks available";
207 case errc::no_message:
208 return "No message of desired type";
209 case errc::no_protocol_option:
210 return "Protocol not available";
211 case errc::no_space_on_device:
212 return "No space left on device";
213 case errc::no_stream_resources:
214 return "Out of streams resources";
215 case errc::no_such_device_or_address:
216 return "No such device or address";
217 case errc::no_such_device:
218 return "No such device";
219 case errc::no_such_file_or_directory:
220 return "No such file or directory";
221 case errc::no_such_process:
222 return "No such process";
223 case errc::not_a_directory:
224 return "Not a directory";
225 case errc::not_a_socket:
226 return "Socket operation on non-socket";
227 case errc::not_a_stream:
228 return "Device not a stream";
229 case errc::not_connected:
230 return "Transport endpoint is not connected";
231 case errc::not_enough_memory:
232 return "Cannot allocate memory";
233#if ENOTSUP != EOPNOTSUPP
234 case errc::not_supported:
235 return "Operation not supported";
236#endif
237 case errc::operation_canceled:
238 return "Operation canceled";
239 case errc::operation_in_progress:
240 return "Operation now in progress";
241 case errc::operation_not_permitted:
242 return "Operation not permitted";
243 case errc::operation_not_supported:
244 return "Operation not supported";
245#if EAGAIN != EWOULDBLOCK
246 case errc::operation_would_block:
247 return "Resource temporarily unavailable";
248#endif
249 case errc::owner_dead:
250 return "Owner died";
251 case errc::permission_denied:
252 return "Permission denied";
f67539c2 253 case errc::protocol_error:
92f5a8d4
TL
254 return "Protocol error";
255 case errc::protocol_not_supported:
256 return "Protocol not supported";
257 case errc::read_only_file_system:
258 return "Read-only file system";
259 case errc::resource_deadlock_would_occur:
260 return "Resource deadlock avoided";
261 case errc::resource_unavailable_try_again:
262 return "Resource temporarily unavailable";
263 case errc::result_out_of_range:
264 return "Numerical result out of range";
265 case errc::state_not_recoverable:
266 return "State not recoverable";
267 case errc::stream_timeout:
268 return "Timer expired";
269 case errc::text_file_busy:
270 return "Text file busy";
271 case errc::timed_out:
272 return "Connection timed out";
273 case errc::too_many_files_open_in_system:
274 return "Too many open files in system";
275 case errc::too_many_files_open:
276 return "Too many open files";
277 case errc::too_many_links:
278 return "Too many links";
279 case errc::too_many_symbolic_link_levels:
280 return "Too many levels of symbolic links";
281 case errc::value_too_large:
282 return "Value too large for defined data type";
283 case errc::wrong_protocol_type:
284 return "Protocol wrong type for socket";
285 default:
286 return "unknown";
287 }
288 }
289} // namespace detail
290
291/*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX).
292 */
293class _generic_code_domain : public status_code_domain
294{
295 template <class> friend class status_code;
296 template <class StatusCode> friend class detail::indirecting_domain;
297 using _base = status_code_domain;
298
299public:
300 //! The value type of the generic code, which is an `errc` as per POSIX.
301 using value_type = errc;
302 using string_ref = _base::string_ref;
303
304public:
305 //! Default constructor
20effc67
TL
306 constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept
307 : _base(id)
308 {
309 }
92f5a8d4
TL
310 _generic_code_domain(const _generic_code_domain &) = default;
311 _generic_code_domain(_generic_code_domain &&) = default;
312 _generic_code_domain &operator=(const _generic_code_domain &) = default;
313 _generic_code_domain &operator=(_generic_code_domain &&) = default;
314 ~_generic_code_domain() = default;
315
316 //! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
317 static inline constexpr const _generic_code_domain &get();
318
319 virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); } // NOLINT
320protected:
321 virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
322 {
323 assert(code.domain() == *this); // NOLINT
324 return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT
325 }
326 virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
327 {
328 assert(code1.domain() == *this); // NOLINT
329 const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT
330 if(code2.domain() == *this)
331 {
332 const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
333 return c1.value() == c2.value();
334 }
335 return false;
336 }
337 virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
338 {
339 assert(code.domain() == *this); // NOLINT
340 return static_cast<const generic_code &>(code); // NOLINT
341 }
342 virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
343 {
344 assert(code.domain() == *this); // NOLINT
345 const auto &c = static_cast<const generic_code &>(code); // NOLINT
346 return string_ref(detail::generic_code_message(c.value()));
347 }
348#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
349 BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
350 {
351 assert(code.domain() == *this); // NOLINT
352 const auto &c = static_cast<const generic_code &>(code); // NOLINT
353 throw status_error<_generic_code_domain>(c);
354 }
355#endif
356};
357//! A specialisation of `status_error` for the generic code domain.
358using generic_error = status_error<_generic_code_domain>;
359//! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
360constexpr _generic_code_domain generic_code_domain;
361inline constexpr const _generic_code_domain &_generic_code_domain::get()
362{
363 return generic_code_domain;
364}
365// Enable implicit construction of generic_code from errc
366BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
367{
368 return generic_code(in_place, c);
369}
370
371
372/*************************************************************************************************************/
373
374
1e59de90 375template <class T> inline BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
92f5a8d4
TL
376{
377 if(_domain && o._domain)
378 {
379 if(_domain->_do_equivalent(*this, o))
380 {
381 return true;
382 }
383 if(o._domain->_do_equivalent(o, *this))
384 {
385 return true;
386 }
387 generic_code c1 = o._domain->_generic_code(o);
388 if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
389 {
390 return true;
391 }
392 generic_code c2 = _domain->_generic_code(*this);
393 if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
394 {
395 return true;
396 }
397 }
398 // If we are both empty, we are equivalent, otherwise not equivalent
399 return (!_domain && !o._domain);
400}
401//! True if the status code's are semantically equal via `equivalent()`.
1e59de90 402template <class DomainType1, class DomainType2> BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
92f5a8d4
TL
403{
404 return a.equivalent(b);
405}
406//! True if the status code's are not semantically equal via `equivalent()`.
1e59de90 407template <class DomainType1, class DomainType2> BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
92f5a8d4
TL
408{
409 return !a.equivalent(b);
410}
411//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
1e59de90
TL
412BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
413 class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
414BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
415BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
92f5a8d4
TL
416{
417 return a.equivalent(make_status_code(b));
418}
419//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
1e59de90
TL
420BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
421 class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
422BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
423BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
92f5a8d4
TL
424{
425 return b.equivalent(make_status_code(a));
426}
427//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
1e59de90
TL
428BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
429 class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
430BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
431BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
92f5a8d4
TL
432{
433 return !a.equivalent(make_status_code(b));
434}
435//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
1e59de90
TL
436BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
437 class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
438BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
439BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
92f5a8d4
TL
440{
441 return !b.equivalent(make_status_code(a));
442}
20effc67
TL
443//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
444template <class DomainType1, class T, //
445 class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
446 >
1e59de90 447BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
20effc67
TL
448{
449 return a.equivalent(QuickStatusCodeType(b));
450}
451//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
452template <class T, class DomainType1, //
453 class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
454 >
1e59de90 455BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
20effc67
TL
456{
457 return b.equivalent(QuickStatusCodeType(a));
458}
459//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
460template <class DomainType1, class T, //
461 class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
462 >
1e59de90 463BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
20effc67
TL
464{
465 return !a.equivalent(QuickStatusCodeType(b));
466}
467//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
468template <class T, class DomainType1, //
469 class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
470 >
1e59de90 471BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
20effc67
TL
472{
473 return !b.equivalent(QuickStatusCodeType(a));
474}
475
92f5a8d4
TL
476
477BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
478
479#endif