]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/outcome/experimental/status-code/generic_code.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / outcome / experimental / status-code / generic_code.hpp
1 /* Proposed SG14 status_code
2 (C) 2018 - 2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
3 File Created: Feb 2018
4
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License in the accompanying file
9 Licence.txt or at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19
20 Distributed under the Boost Software License, Version 1.0.
21 (See accompanying file Licence.txt or copy at
22 http://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
32 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
33
34 //! The generic error coding (POSIX)
35 enum 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,
101 protcol_error = EPROTO,
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
119 namespace 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";
253 case errc::protcol_error:
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 */
293 class _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
299 public:
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
304 public:
305 //! Default constructor
306 constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept : _base(id) {}
307 _generic_code_domain(const _generic_code_domain &) = default;
308 _generic_code_domain(_generic_code_domain &&) = default;
309 _generic_code_domain &operator=(const _generic_code_domain &) = default;
310 _generic_code_domain &operator=(_generic_code_domain &&) = default;
311 ~_generic_code_domain() = default;
312
313 //! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
314 static inline constexpr const _generic_code_domain &get();
315
316 virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); } // NOLINT
317 protected:
318 virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
319 {
320 assert(code.domain() == *this); // NOLINT
321 return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT
322 }
323 virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
324 {
325 assert(code1.domain() == *this); // NOLINT
326 const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT
327 if(code2.domain() == *this)
328 {
329 const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
330 return c1.value() == c2.value();
331 }
332 return false;
333 }
334 virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
335 {
336 assert(code.domain() == *this); // NOLINT
337 return static_cast<const generic_code &>(code); // NOLINT
338 }
339 virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
340 {
341 assert(code.domain() == *this); // NOLINT
342 const auto &c = static_cast<const generic_code &>(code); // NOLINT
343 return string_ref(detail::generic_code_message(c.value()));
344 }
345 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
346 BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
347 {
348 assert(code.domain() == *this); // NOLINT
349 const auto &c = static_cast<const generic_code &>(code); // NOLINT
350 throw status_error<_generic_code_domain>(c);
351 }
352 #endif
353 };
354 //! A specialisation of `status_error` for the generic code domain.
355 using generic_error = status_error<_generic_code_domain>;
356 //! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
357 constexpr _generic_code_domain generic_code_domain;
358 inline constexpr const _generic_code_domain &_generic_code_domain::get()
359 {
360 return generic_code_domain;
361 }
362 // Enable implicit construction of generic_code from errc
363 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
364 {
365 return generic_code(in_place, c);
366 }
367
368
369 /*************************************************************************************************************/
370
371
372 template <class T> inline bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
373 {
374 if(_domain && o._domain)
375 {
376 if(_domain->_do_equivalent(*this, o))
377 {
378 return true;
379 }
380 if(o._domain->_do_equivalent(o, *this))
381 {
382 return true;
383 }
384 generic_code c1 = o._domain->_generic_code(o);
385 if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
386 {
387 return true;
388 }
389 generic_code c2 = _domain->_generic_code(*this);
390 if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
391 {
392 return true;
393 }
394 }
395 // If we are both empty, we are equivalent, otherwise not equivalent
396 return (!_domain && !o._domain);
397 }
398 //! True if the status code's are semantically equal via `equivalent()`.
399 template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
400 {
401 return a.equivalent(b);
402 }
403 //! True if the status code's are not semantically equal via `equivalent()`.
404 template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
405 {
406 return !a.equivalent(b);
407 }
408 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
409 template <class DomainType1, class T, //
410 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
411 typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
412 inline bool operator==(const status_code<DomainType1> &a, const T &b)
413 {
414 return a.equivalent(make_status_code(b));
415 }
416 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
417 template <class T, class DomainType1, //
418 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
419 typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
420 inline bool operator==(const T &a, const status_code<DomainType1> &b)
421 {
422 return b.equivalent(make_status_code(a));
423 }
424 //! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
425 template <class DomainType1, class T, //
426 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
427 typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
428 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
429 {
430 return !a.equivalent(make_status_code(b));
431 }
432 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
433 template <class T, class DomainType1, //
434 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
435 typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
436 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
437 {
438 return !b.equivalent(make_status_code(a));
439 }
440
441 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
442
443 #endif