Photon microGUI widgets library 0.6.0
system_error.hpp
1#ifndef _STDEX_SYSTEM_ERROR_H
2#define _STDEX_SYSTEM_ERROR_H
3
4#if _MSC_VER > 1000
5#pragma once
6#endif // _MSC_VER > 1000
7
8// stdex includes
9#include "./type_traits.hpp" // stdex::enable_if, stdex::integral_constant
10
11// POSIX includes
12/*none*/
13
14// std includes
15
16
17#ifdef __STDC_WANT_LIB_EXT1__
18
19#define __STDC_WANT_LIB_EXT1__ 1
20// As with all bounds-checked functions, strerror_s and strerrorlen_s are only guaranteed to be available
21// if __STDC_LIB_EXT1__ is defined by the implementation and
22// if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including string.h.
23#include <string.h>
24
25#endif
26
27#include <errno.h>
28#include <cerrno>
29#include <cstdlib> // std::strerror
30#include <cstring> // std::strerror
31#include <stdexcept> // std::runtime_error
32#include <string> // std::string
33#include <functional>
34
35
36#ifdef _STDEX_NATIVE_CPP11_SUPPORT
37
38#define _STDEX_DELETED_FUNCTION =delete
39#define _STDEX_NOEXCEPT_FUNCTION noexcept
40
41#else
42
43#define _STDEX_DELETED_FUNCTION
44#define _STDEX_NOEXCEPT_FUNCTION throw()
45
46#endif
47
48namespace stdex
49{
50 struct errc
51 {
52 typedef
53 enum errc_t { // names for generic error codes
54#ifdef EAFNOSUPPORT
55 address_family_not_supported = EAFNOSUPPORT,
56#else
57 address_family_not_supported = 102,
58#endif
59#ifdef EADDRINUSE
60 address_in_use = EADDRINUSE,
61#else
62 address_in_use = 100,
63#endif
64#ifdef EADDRNOTAVAIL
65 address_not_available = EADDRNOTAVAIL,
66#else
67 address_not_available = 101,
68#endif
69#ifdef EISCONN
70 already_connected = EISCONN,
71#else
72 already_connected = 113,
73#endif
74 argument_list_too_long = E2BIG,
75 argument_out_of_domain = EDOM,
76 bad_address = EFAULT,
77 bad_file_descriptor = EBADF,
78#ifdef EBADMSG
79 bad_message = EBADMSG,
80#else
81 bad_message = 103,
82#endif
83 broken_pipe = EPIPE,
84#ifdef ECONNABORTED
85 connection_aborted = ECONNABORTED,
86#else
87 connection_aborted = 106,
88#endif
89#ifdef EALREADY
90 connection_already_in_progress = EALREADY,
91#else
92 connection_already_in_progress = 103,
93#endif
94#ifdef ECONNREFUSED
95 connection_refused = ECONNREFUSED,
96#else
97 connection_refused = 107,
98#endif
99#ifdef ECONNRESET
100 connection_reset = ECONNRESET,
101#else
102 connection_reset = 108,
103#endif
104 cross_device_link = EXDEV,
105#ifdef EDESTADDRREQ
106 destination_address_required = EDESTADDRREQ,
107#else
108 destination_address_required = 109,
109#endif
110 device_or_resource_busy = EBUSY,
111 directory_not_empty = ENOTEMPTY,
112 executable_format_error = ENOEXEC,
113 file_exists = EEXIST,
114 file_too_large = EFBIG,
115 filename_too_long = ENAMETOOLONG,
116#ifdef ENOSYS
117 function_not_supported = ENOSYS,
118#else
119 function_not_supported = 40,
120#endif
121#ifdef EHOSTUNREACH
122 host_unreachable = EHOSTUNREACH,
123#else
124 host_unreachable = 110,
125#endif
126#ifdef EIDRM
127 identifier_removed = EIDRM,
128#else
129 identifier_removed = 111,
130#endif
131#ifdef EILSEQ
132 illegal_byte_sequence = EILSEQ,
133#else
134 illegal_byte_sequence = 42,
135#endif
136 inappropriate_io_control_operation = ENOTTY,
137 interrupted = EINTR,
138 invalid_argument = EINVAL,
139 invalid_seek = ESPIPE,
140 io_error = EIO,
141 is_a_directory = EISDIR,
142#ifdef EMSGSIZE
143 message_size = EMSGSIZE,
144#else
145 message_size = 115,
146#endif
147#ifdef ENETDOWN
148 network_down = ENETDOWN,
149#else
150 network_down = 116,
151#endif
152#ifdef ENETRESET
153 network_reset = ENETRESET,
154#else
155 network_reset = 117,
156#endif
157#ifdef ENETUNREACH
158 network_unreachable = ENETUNREACH,
159#else
160 network_unreachable = 118,
161#endif
162#ifdef ENOBUFS
163 no_buffer_space = ENOBUFS,
164#else
165 no_buffer_space = 119,
166#endif
167 no_child_process = ECHILD,
168#ifdef ENOLINK
169 no_link = ENOLINK,
170#else
171 no_link = 121,
172#endif
173#ifdef ENOLCK
174 no_lock_available = ENOLCK,
175#else
176 no_lock_available = 39,
177#endif
178#ifdef ENODATA
179 no_message_available = ENODATA,
180#else
181 no_message_available = 120,
182#endif
183#ifdef ENOMSG
184 no_message = ENOMSG,
185#else
186 no_message = 122,
187#endif
188#ifdef ENOPROTOOPT
189 no_protocol_option = ENOPROTOOPT,
190#else
191 no_protocol_option = 123,
192#endif
193 no_space_on_device = ENOSPC,
194#ifdef ENOSR
195 no_stream_resources = ENOSR,
196#else
197 no_stream_resources = 124,
198#endif
199 no_such_device_or_address = ENXIO,
200 no_such_device = ENODEV,
201 no_such_file_or_directory = ENOENT,
202 no_such_process = ESRCH,
203 not_a_directory = ENOTDIR,
204#ifdef ENOTSOCK
205 not_a_socket = ENOTSOCK,
206#else
207 not_a_socket = 128,
208#endif
209#ifdef ENOSTR
210 not_a_stream = ENOSTR,
211#else
212 not_a_stream = 125,
213#endif
214#ifdef ENOTCONN
215 not_connected = ENOTCONN,
216#else
217 not_connected = 126,
218#endif
219 not_enough_memory = ENOMEM,
220#ifdef ENOTSUP
221 not_supported = ENOTSUP,
222#else
223 not_supported = 129,
224#endif
225#ifdef ECANCELED
226 operation_canceled = ECANCELED,
227#else
228 operation_canceled = 105,
229#endif
230#ifdef EINPROGRESS
231 operation_in_progress = EINPROGRESS,
232#else
233 operation_in_progress = 112,
234#endif
235 operation_not_permitted = EPERM,
236#ifdef EOPNOTSUPP
237 operation_not_supported = EOPNOTSUPP,
238#else
239 operation_not_supported = 130,
240#endif
241#ifdef EWOULDBLOCK
242 operation_would_block = EWOULDBLOCK,
243#else
244 operation_would_block = 140,
245#endif
246#ifdef EOWNERDEAD
247 owner_dead = EOWNERDEAD,
248#else
249 owner_dead = 133,
250#endif
251 permission_denied = EACCES,
252#ifdef EPROTO
253 protocol_error = EPROTO,
254#else
255 protocol_error = 134,
256#endif
257#ifdef EPROTONOSUPPORT
258 protocol_not_supported = EPROTONOSUPPORT,
259#else
260 protocol_not_supported = 135,
261#endif
262 read_only_file_system = EROFS,
263#ifdef EDEADLK
264 resource_deadlock_would_occur = EDEADLK,
265#else
266 resource_deadlock_would_occur = 36,
267#endif
268 resource_unavailable_try_again = EAGAIN,
269 result_out_of_range = ERANGE,
270#ifdef ENOTRECOVERABLE
271 state_not_recoverable = ENOTRECOVERABLE,
272#else
273 state_not_recoverable = 127,
274#endif
275#ifdef ETIME
276 stream_timeout = ETIME,
277#else
278 stream_timeout = 137,
279#endif
280#ifdef ETXTBSY
281 text_file_busy = ETXTBSY,
282#else
283 text_file_busy = 139,
284#endif
285#ifdef ETIMEDOUT
286 timed_out = ETIMEDOUT,
287#else
288 timed_out = 138,
289#endif
290 too_many_files_open_in_system = ENFILE,
291 too_many_files_open = EMFILE,
292 too_many_links = EMLINK,
293#ifdef ELOOP
294 too_many_symbolic_link_levels = ELOOP,
295#else
296 too_many_symbolic_link_levels = 114,
297#endif
298#ifdef EOVERFLOW
299 value_too_large = EOVERFLOW,
300#else
301 value_too_large = 132,
302#endif
303#ifdef EPROTOTYPE
304 wrong_protocol_type = EPROTOTYPE
305#else
306 wrong_protocol_type = 136
307#endif
308 } type;
309
310 errc(type code):
311 _code(code)
312 {
313
314 }
315
316 operator type&()
317 {
318 return _code;
319 }
320
321 operator const type&() const
322 {
323 return _code;
324 }
325
326 private:
327 type _code;
328 };
329
330 typedef errc generic_errno;
331
332 struct io_errc
333 {
334 typedef
335 enum io_errc_t
336 {
337 stream = 1
338 } type;
339
340 io_errc(type code):
341 _code(code)
342 {
343
344 }
345
346 operator type&()
347 {
348 return _code;
349 }
350
351 operator const type&() const
352 {
353 return _code;
354 }
355
356 private:
357 type _code;
358 };
359
360 // TEMPLATE CLASS is_error_code_enum
361 template<class _Enum>
362 struct is_error_code_enum
363 { // tests for error_code enumeration
364 static const bool value = false;
365 };
366
367 template<>
368 struct is_error_code_enum<io_errc>
369 { // tests for error_code enumeration
370 static const bool value = true;
371 };
372
373 template<>
374 struct is_error_code_enum<io_errc::type>
375 { // tests for error_code enumeration
376 static const bool value = true;
377 };
378
379 // TEMPLATE CLASS is_error_condition_enum
380 template<class _Enum>
381 struct is_error_condition_enum
382 { // tests for error_condition enumeration
383 static const bool value = false;
384 };
385
386 template<>
387 struct is_error_condition_enum<errc::type>
388 {
389 static const bool value = true;
390 };
391
392 template<>
393 struct is_error_condition_enum<generic_errno>
394 { // tests for error_condition enumeration
395 static const bool value = true;
396 };
397
398 class error_code;
399 class error_condition;
400
401
402 error_code make_error_code(errc::errc_t) _STDEX_NOEXCEPT_FUNCTION;
403 error_code make_error_code(io_errc) _STDEX_NOEXCEPT_FUNCTION;
404 error_condition make_error_condition(errc::errc_t) _STDEX_NOEXCEPT_FUNCTION;
405 error_condition make_error_condition(io_errc) _STDEX_NOEXCEPT_FUNCTION;
406
407 class error_category;
408
409 const error_category& generic_category() _STDEX_NOEXCEPT_FUNCTION;
410 const error_category& iostream_category() _STDEX_NOEXCEPT_FUNCTION;
411 const error_category& system_category() _STDEX_NOEXCEPT_FUNCTION;
412
413} // namespace stdex
414
415// '_stdex_ADL' namespace is used for compilers that have bugged ADL:
416// like failing miserably to see other function overloads
417// with 'using' directive or functions in global namespace.
418//
419// Usage: we hide there wrapper functions that trigger ADL "properly".
420//
421// Looks ugly, pollutes global namespace with extra symbol but
422// g e t s j o b d o n e
423namespace _stdex_ADL
424{
425 template<class _Tp>
426 inline
427 static stdex::error_code _make_error_code(_Tp);
428
429 template<class _Tp>
430 inline
431 static stdex::error_condition _make_error_condition(_Tp);
432} // namespace _stdex_ADL
433
434namespace stdex
435{
436 class error_category
437 {
438 public:
439 error_category() _STDEX_NOEXCEPT_FUNCTION
440 {}
441
442 virtual ~error_category() _STDEX_NOEXCEPT_FUNCTION
443 {}
444
445 virtual const char* name() const _STDEX_NOEXCEPT_FUNCTION = 0;
446
447 // We need two different virtual functions here, one returning a
448 // COW string and one returning an SSO string. Their positions in the
449 // vtable must be consistent for dynamic dispatch to work, but which one
450 // the name "message()" finds depends on which ABI the caller is using.
451
452 virtual std::string message(int) const = 0;
453
454 public:
455 virtual error_condition default_error_condition(int val) const _STDEX_NOEXCEPT_FUNCTION;
456
457 virtual bool equivalent(int val, const error_condition &cond) const _STDEX_NOEXCEPT_FUNCTION;
458
459 virtual bool equivalent(const error_code& code, int) const _STDEX_NOEXCEPT_FUNCTION;
460
461 inline bool operator<(const error_category &other) const _STDEX_NOEXCEPT_FUNCTION
462 {
463 return std::less<const error_category*>()(this, &other);
464 }
465
466 inline bool operator==(const error_category &other) const _STDEX_NOEXCEPT_FUNCTION
467 {
468 return this == &other;
469 }
470
471 inline bool operator!=(const error_category &other) const _STDEX_NOEXCEPT_FUNCTION
472 {
473 return this != &other;
474 }
475
476 private:
477 error_category(const error_category&) _STDEX_DELETED_FUNCTION;
478 error_category& operator=(const error_category&) _STDEX_DELETED_FUNCTION;
479 };
480
481 namespace detail
482 {
483 struct _error_condition_compare
484 {
485 operator
486 const stdex::error_condition&() const{
487 return reinterpret_cast<const error_condition&>(*this);
488 }
489 };
490 }
491
492 class error_condition:
493 public detail::_error_condition_compare
494 {
495 private:
496 int _value;
497 const error_category *_cat;
498
499 typedef void(*unspecified_bool_type)();
500 static void unspecified_bool_true() {}
501
502 public:
503 error_condition() _STDEX_NOEXCEPT_FUNCTION:
504 _value(0),
505 _cat(&generic_category())
506 {}
507
508 error_condition(int val, const error_category &cat) _STDEX_NOEXCEPT_FUNCTION:
509 _value(val),
510 _cat(&cat)
511 {}
512
513 template<class _ErrorCondEnum>
514 error_condition(const _ErrorCondEnum& val) _STDEX_NOEXCEPT_FUNCTION
515 {
516 STATIC_ASSERT(bool(is_error_condition_enum<_ErrorCondEnum>::value == true), value_should_be_error_condition_enum);
517 *this = val;
518 }
519
520 void assign(int val, const error_category &cat) _STDEX_NOEXCEPT_FUNCTION
521 {
522 _value = val;
523 _cat = &cat;
524 }
525
526 template<class _ErrorCondEnum>
527 typename enable_if<detail::_or_<is_error_condition_enum<_ErrorCondEnum>, is_same<error_condition, _ErrorCondEnum> >::value, error_condition&>::type
528 operator=(const _ErrorCondEnum& val) _STDEX_NOEXCEPT_FUNCTION
529 {
530 return (*this = _stdex_ADL::_make_error_condition(val));
531 }
532
533 void clear() _STDEX_NOEXCEPT_FUNCTION
534 {
535 assign(0, generic_category());
536 }
537
538 int value() const _STDEX_NOEXCEPT_FUNCTION { return _value; }
539
540 const error_category& category() const _STDEX_NOEXCEPT_FUNCTION { return *_cat; }
541
542
543 std::string message() const
544 {
545 return category().message(value());
546 }
547
548 operator unspecified_bool_type() const _STDEX_NOEXCEPT_FUNCTION // true if error
549 {
550 return _value == 0 ? 0 : unspecified_bool_true;
551 }
552
553 bool operator!() const _STDEX_NOEXCEPT_FUNCTION // true if no error
554 {
555 return _value == 0;
556 }
557 };
558
559 namespace detail
560 {
561 struct _error_code_compare
562 {
563 operator
564 const stdex::error_code&() const {
565 return reinterpret_cast<const error_code&>(*this);
566 }
567 };
568 }
569
570 class error_code:
571 public detail::_error_code_compare
572 {
573 private:
574
575 int _value;
576 const error_category *_cat;
577
578 typedef void(*unspecified_bool_type)();
579 static void unspecified_bool_true() {}
580
581 public:
582 error_code() _STDEX_NOEXCEPT_FUNCTION:
583 _value(0),
584 _cat(&system_category())
585 { }
586
587 error_code(int val, const error_category& cat) _STDEX_NOEXCEPT_FUNCTION:
588 _value(val),
589 _cat(&cat)
590 { }
591
592 template<class _ErrorCodeEnum>
593 error_code(const _ErrorCodeEnum &val) _STDEX_NOEXCEPT_FUNCTION
594 {
595 STATIC_ASSERT(bool(is_error_code_enum<_ErrorCodeEnum>::value == true), value_should_be_error_code_enum);
596 *this = val;
597 }
598
599 void assign(int val, const error_category& cat) _STDEX_NOEXCEPT_FUNCTION
600 {
601 _value = val;
602 _cat = &cat;
603 }
604
605 void clear() _STDEX_NOEXCEPT_FUNCTION
606 {
607 assign(0, system_category());
608 }
609
610 template<class _ErrorCodeEnum>
611 typename enable_if<detail::_or_<is_error_code_enum<_ErrorCodeEnum>, is_same<error_code, _ErrorCodeEnum> >::value, error_code&>::type
612 operator=(const _ErrorCodeEnum& val) _STDEX_NOEXCEPT_FUNCTION
613 {
614 return (*this = _stdex_ADL::_make_error_code(val));
615 }
616
617 int value() const _STDEX_NOEXCEPT_FUNCTION { return _value; }
618
619 const error_category& category() const _STDEX_NOEXCEPT_FUNCTION { return *_cat; }
620
621 error_condition default_error_condition() const _STDEX_NOEXCEPT_FUNCTION;
622
623 std::string message() const
624 {
625 return category().message(value());
626 }
627
628 operator unspecified_bool_type() const _STDEX_NOEXCEPT_FUNCTION // true if error
629 {
630 return _value == 0 ? 0 : unspecified_bool_true;
631 }
632
633 bool operator!() const _STDEX_NOEXCEPT_FUNCTION // true if no error
634 {
635 return _value == 0;
636 }
637 };
638
639 class system_error :
640 public std::runtime_error
641 {
642 private:
643 error_code _code;
644
645 public:
646 system_error(error_code ecode = error_code()):
647 std::runtime_error(ecode.message()),
648 _code(ecode)
649 {}
650
651 system_error(error_code ecode, const std::string &what):
652 std::runtime_error(what + ": " + ecode.message()),
653 _code(ecode)
654 {}
655
656 system_error(error_code ecode, const char *what):
657 std::runtime_error(std::string(what) + (": " + ecode.message())),
658 _code(ecode)
659 {}
660
661 system_error(int val, const error_category &ecat, const char *what):
662 std::runtime_error(std::string(what) + (": " + error_code(val, ecat).message())),
663 _code(val, ecat)
664 {}
665
666 system_error(int val, const error_category &ecat):
667 std::runtime_error(error_code(val, ecat).message()),
668 _code(val, ecat)
669 {}
670
671 system_error(int val, const error_category &ecat, const std::string &what):
672 std::runtime_error(what + ": " + error_code(val, ecat).message()),
673 _code(val, ecat)
674 {}
675
676 const error_code& code() const _STDEX_NOEXCEPT_FUNCTION { return _code; }
677 };
678
679 namespace detail
680 {
681 template<class _Tp>
682 struct _is_error_code
683 {
684 static const bool value =
685 is_same<error_code,
686 typename remove_reference<
687 typename remove_cv<_Tp>::type>::type>::value == bool(true) ||
688 is_same<detail::_error_code_compare,
689 typename remove_reference<
690 typename remove_cv<_Tp>::type>::type>::value == bool(true);
691 };
692
693 template<class _Tp>
694 struct _is_not_error_code:
695 _not_<_is_error_code<_Tp>>
696 { };
697
698 template<class _Tp>
699 struct _is_error_condition
700 {
701 static const bool value =
702 is_same<error_condition,
703 typename remove_reference<
704 typename remove_cv<_Tp>::type>::type>::value == bool(true) ||
705 is_same<detail::_error_condition_compare,
706 typename remove_reference<
707 typename remove_cv<_Tp>::type>::type>::value == bool(true);
708 };
709
710 template<class _Tp>
711 struct _is_not_error_condition :
712 _not_<_is_error_condition<_Tp>>
713 { };
714
715 template<class _Tp>
716 struct _is_error_code_enum_or_class:
717 _or_<
718 is_error_code_enum<_Tp>,
719 _is_error_code<_Tp>
720 >
721 { };
722
723 template<class _Tp>
724 struct _is_error_code_enum_not_class:
725 _and_<
726 is_error_code_enum<_Tp>,
727 _is_not_error_code<_Tp>
728 >
729 { };
730
731 template<class _Tp>
732 struct _is_error_condition_enum_or_class:
733 _or_<
734 is_error_condition_enum<_Tp>,
735 _is_error_condition<_Tp>
736 >
737 { };
738
739 template<class _Tp>
740 struct _is_error_condition_enum_not_class:
741 _and_<
742 is_error_condition_enum<_Tp>,
743 _is_not_error_condition<_Tp>
744 >
745 { };
746
747 template<int>
748 class _disabled_system_error_operator;
749 }
750
751 template<class _LhsT>
752 inline // overload for enum values at left and classes
753 bool operator<(
754 const _LhsT& _lhs,
755 typename conditional<
756 bool( detail::_is_error_code_enum_or_class<_LhsT>::value == bool(true) ),
757 const detail::_error_code_compare&,
758 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
759 {
760 struct lambdas
761 {
762 static
763 bool compare(
764 const error_code& _lhs, const error_code& _rhs) _STDEX_NOEXCEPT_FUNCTION
765 {
766 return (_lhs.category() < _rhs.category()
767 || (_lhs.category() == _rhs.category()
768 && _lhs.value() < _rhs.value()));
769 }
770 };
771 return lambdas::compare(_lhs, _rhs);
772 }
773
774 template<class _RhsT>
775 inline // overload for enum values at right
776 bool operator<(
777 typename conditional<
778 bool( detail::_is_error_code_enum_not_class<_RhsT>::value == bool(true) ),
779 const detail::_error_code_compare&,
780 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
781 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
782 {
783 return stdex::operator<(_lhs, error_code(_rhs));
784 }
785
786 template<class _LhsT>
787 inline // overload for enum values at left and classes
788 bool operator<(
789 const _LhsT& _lhs,
790 typename conditional<
791 bool( detail::_is_error_condition_enum_or_class<_LhsT>::value == bool(true) ),
792 const detail::_error_condition_compare&,
793 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
794 {
795 struct lambdas
796 {
797 static
798 bool compare(
799 const error_condition& _lhs, const error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
800 {
801 return (_lhs.category() < _rhs.category()
802 || (_lhs.category() == _rhs.category()
803 && _lhs.value() < _rhs.value()));
804 }
805 };
806 return lambdas::compare(_lhs, _rhs);
807 }
808
809 template<class _RhsT>
810 inline // overload for enum values at right
811 bool operator<(
812 typename conditional<
813 bool( detail::_is_error_condition_enum_not_class<_RhsT>::value == bool(true) ),
814 const detail::_error_condition_compare&,
815 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
816 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
817 {
818 return stdex::operator<(_lhs, error_condition(_rhs));
819 }
820
821 /*inline
822 bool operator<(const stdex::error_condition& _lhs, const stdex::error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
823 {
824 if (_lhs.category() < _rhs.category())
825 return true;
826 if (_lhs.value() < _rhs.value())
827 return true;
828 return false;
829 }*/
830
831 // OPERATOR== FOR error_code/error_condition
832 template<class _LhsT>
833 inline
834 bool operator==(
835 const _LhsT& _lhs,
836 typename conditional<
837 bool( detail::_is_error_code_enum_or_class<_LhsT>::value == bool(true) ),
838 const detail::_error_code_compare&,
839 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
840 {
841 struct lambdas
842 {
843 static
844 bool compare(
845 const error_code& _lhs, const error_code& _rhs) _STDEX_NOEXCEPT_FUNCTION
846 {
847 return (_lhs.category() == _rhs.category()
848 && _lhs.value() == _rhs.value());
849 }
850 };
851 return lambdas::compare(_lhs, _rhs);
852 }
853
854 template<class _RhsT>
855 inline
856 bool operator==(
857 typename conditional<
858 bool( detail::_is_error_code_enum_not_class<_RhsT>::value == bool(true) ),
859 const detail::_error_code_compare&,
860 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
861 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
862 {
863 return stdex::operator==(_lhs, error_code(_rhs));
864 }
865
866 template<class _LhsT>
867 inline
868 bool operator==(
869 const _LhsT& _lhs,
870 typename conditional<
871 bool( detail::_is_error_code_enum_or_class<_LhsT>::value == bool(true) ),
872 const detail::_error_condition_compare&,
873 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
874 { // test errors for equality
875 struct lambdas
876 {
877 static
878 bool compare(
879 const error_code& _lhs, const error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
880 {
881 return (_lhs.category().equivalent(_lhs.value(), _rhs)
882 || _rhs.category().equivalent(_lhs, _rhs.value()));
883 }
884 };
885 return lambdas::compare(_lhs, _rhs);
886 }
887
888 template<class _RhsT>
889 inline
890 bool operator==(
891 typename conditional<
892 bool( detail::_is_error_condition_enum_not_class<_RhsT>::value == bool(true) ),
893 const detail::_error_code_compare&,
894 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
895 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
896 { // test errors for equality
897 return stdex::operator==(_lhs, error_condition(_rhs));
898 }
899
900 template<class _LhsT>
901 inline
902 bool operator==(
903 const _LhsT& _lhs,
904 typename conditional<
905 bool( detail::_is_error_condition_enum_or_class<_LhsT>::value == bool(true) ),
906 const detail::_error_code_compare&,
907 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
908 { // test errors for equality
909 struct lambdas
910 {
911 static
912 bool compare(
913 const error_condition& _lhs, const error_code& _rhs) _STDEX_NOEXCEPT_FUNCTION
914 {
915 return (_rhs.category().equivalent(_rhs.value(), _lhs)
916 || _lhs.category().equivalent(_rhs, _lhs.value()));
917 }
918 };
919 return lambdas::compare(_lhs, _rhs);
920 }
921
922 template<class _RhsT>
923 inline
924 bool operator==(
925 typename conditional<
926 bool( detail::_is_error_code_enum_not_class<_RhsT>::value == bool(true) ),
927 const detail::_error_condition_compare&,
928 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
929 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
930 { // test errors for equality
931 return stdex::operator==(_lhs, error_code(_rhs));
932 }
933
934
935
936 template<class _LhsT>
937 inline
938 bool operator==(
939 const _LhsT& _lhs,
940 typename conditional<
941 bool( detail::_is_error_condition_enum_or_class<_LhsT>::value == bool(true) ),
942 const detail::_error_condition_compare&,
943 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
944 {
945 struct lambdas
946 {
947 static
948 bool compare(
949 const error_condition& _lhs, const error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
950 {
951 return (_lhs.category() == _rhs.category()
952 && _lhs.value() == _rhs.value());
953 }
954 };
955 return lambdas::compare(_lhs, _rhs);
956 }
957
958 template<class _RhsT>
959 inline
960 bool operator==(
961 typename conditional<
962 bool( detail::_is_error_condition_enum_not_class<_RhsT>::value == bool(true) ),
963 const detail::_error_condition_compare&,
964 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
965 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
966 {
967 return stdex::operator==(_lhs, error_condition(_rhs));
968 }
969
970 //inline
971 //bool operator==(const stdex::error_condition& _lhs, const stdex::error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
972 //{
973 // return _lhs.category() == _rhs.category() && _lhs.value() == _rhs.value();
974 //}
975
976 // OPERATOR!= FOR error_code/error_condition
977 template<class _LhsT>
978 inline
979 bool operator!=(
980 const _LhsT& _lhs,
981 typename conditional<
982 bool( detail::_is_error_code_enum_or_class<_LhsT>::value == bool(true) ),
983 const detail::_error_code_compare&,
984 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
985 {
986 return !(_lhs == _rhs);
987 }
988
989 template<class _RhsT>
990 inline
991 bool operator!=(
992 typename conditional<
993 bool( detail::_is_error_code_enum_not_class<_RhsT>::value == bool(true) ),
994 const detail::_error_code_compare&,
995 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
996 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
997 {
998 return !(_lhs == _rhs);
999 }
1000
1001 template<class _LhsT>
1002 inline
1003 bool operator!=(
1004 const _LhsT& _lhs,
1005 typename conditional<
1006 bool( detail::_is_error_code_enum_or_class<_LhsT>::value == bool(true) ),
1007 const detail::_error_condition_compare&,
1008 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
1009 {
1010 return !(_lhs == _rhs);
1011 }
1012
1013 template<class _RhsT>
1014 inline
1015 bool operator!=(
1016 typename conditional<
1017 bool( detail::_is_error_condition_enum_not_class<_RhsT>::value == bool(true) ),
1018 const detail::_error_code_compare&,
1019 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
1020 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
1021 {
1022 return !(_lhs == _rhs);
1023 }
1024
1025 template<class _LhsT>
1026 inline
1027 bool operator!=(
1028 const _LhsT& _lhs,
1029 typename conditional<
1030 bool( detail::_is_error_condition_enum_or_class<_LhsT>::value == bool(true) ),
1031 const detail::_error_code_compare&,
1032 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
1033 {
1034 return !(_lhs == _rhs);
1035 }
1036
1037 template<class _RhsT>
1038 inline
1039 bool operator!=(
1040 typename conditional<
1041 bool( detail::_is_error_code_enum_not_class<_RhsT>::value == bool(true) ),
1042 const detail::_error_condition_compare&,
1043 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
1044 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
1045 {
1046 return !(_lhs == _rhs);
1047 }
1048
1049 template<class _LhsT>
1050 inline
1051 bool operator!=(
1052 const _LhsT& _lhs,
1053 typename conditional<
1054 bool( detail::_is_error_condition_enum_or_class<_LhsT>::value == bool(true) ),
1055 const detail::_error_condition_compare&,
1056 detail::_disabled_system_error_operator<__LINE__>>::type _rhs) _STDEX_NOEXCEPT_FUNCTION
1057 {
1058 return !(_lhs == _rhs);
1059 }
1060
1061 template<class _RhsT>
1062 inline
1063 bool operator!=(
1064 typename conditional<
1065 bool( detail::_is_error_condition_enum_not_class<_RhsT>::value == bool(true) ),
1066 const detail::_error_condition_compare&,
1067 detail::_disabled_system_error_operator<__LINE__>>::type _lhs,
1068 const _RhsT &_rhs) _STDEX_NOEXCEPT_FUNCTION
1069 {
1070 return !(_lhs == _rhs);
1071 }
1072
1073 //inline
1074 //bool operator!=(const stdex::error_condition& _lhs, const stdex::error_condition& _rhs) _STDEX_NOEXCEPT_FUNCTION
1075 //{
1076 // return !(_lhs == _rhs);
1077 //}
1078
1079
1080 // VIRTUALS FOR error_category
1081 inline error_condition
1082 error_category::default_error_condition(int _Errval) const _STDEX_NOEXCEPT_FUNCTION
1083 { // make error_condition for error code
1084 return (error_condition(_Errval, *this));
1085 }
1086
1087 inline bool
1088 error_category::equivalent(int _Errval,
1089 const error_condition& _Cond) const _STDEX_NOEXCEPT_FUNCTION
1090 { // test if error code same condition
1091 return (default_error_condition(_Errval) == _Cond);
1092 }
1093
1094 inline bool
1095 error_category::equivalent(const error_code& _Code,
1096 int _Errval) const _STDEX_NOEXCEPT_FUNCTION
1097 { // test if conditions same for this category
1098 return (*this == _Code.category() && _Code.value() == _Errval);
1099 }
1100
1101 // MEMBER FUNCTIONS for error_code
1102 inline error_condition error_code::default_error_condition() const _STDEX_NOEXCEPT_FUNCTION
1103 { // make error_condition for error code
1104 return (category().default_error_condition(value()));
1105 }
1106
1107 // FUNCTION make_error_code
1108 inline error_code make_error_code(errc::type _Errno) _STDEX_NOEXCEPT_FUNCTION
1109 { // make an error_code
1110 return (error_code((int) _Errno, generic_category()));
1111 }
1112
1113 inline error_code make_error_code(io_errc::type _Errno) _STDEX_NOEXCEPT_FUNCTION
1114 { // make an error_code
1115 return (error_code((int) _Errno, iostream_category()));
1116 }
1117
1118 // FUNCTION make_error_condition
1119 inline error_condition make_error_condition(errc::type _Errno) _STDEX_NOEXCEPT_FUNCTION
1120 { // make an error_condition
1121 return (error_condition((int) _Errno, generic_category()));
1122 }
1123
1124 inline error_condition make_error_condition(io_errc::type _Errno) _STDEX_NOEXCEPT_FUNCTION
1125 { // make an error_condition
1126 return (error_condition((int) _Errno, iostream_category()));
1127 }
1128
1129 namespace detail
1130 {
1131 namespace system_error_detail
1132 {
1133 template<bool, class>
1134 struct _has_conforming_strerror_s;
1135 struct _has_nonconforming_strerror_s;
1136 struct _has_conforming_strerrorlen_s;
1137
1138 class _strerror_s_arg;
1139
1140 class _strerrorlen_s_arg;
1141 } // namespace system_error_detail
1142 } // namespace detail
1143} // namespace stdex
1144
1145
1146// we need all this mess at global namespace
1147// to detect if following C11-functions are defined or not
1148stdex::detail::system_error_detail::_strerror_s_arg
1149strerror_s(
1150 stdex::detail::system_error_detail::_strerror_s_arg,
1151 stdex::detail::system_error_detail::_strerror_s_arg
1152);
1153stdex::detail::system_error_detail::_strerror_s_arg
1154strerror_s(
1155 stdex::detail::system_error_detail::_strerror_s_arg,
1156 stdex::detail::system_error_detail::_strerror_s_arg,
1157 stdex::detail::system_error_detail::_strerror_s_arg
1158);
1159stdex::detail::system_error_detail::_strerrorlen_s_arg
1160strerrorlen_s(
1161 stdex::detail::system_error_detail::_strerrorlen_s_arg
1162);
1163
1164namespace stdex
1165{
1166 namespace detail
1167 {
1168 namespace system_error_detail
1169 {
1170
1171 static const char* _unknown_error()
1172 {return "unknown error";}
1173
1174 template<bool, bool, class _DummyT>
1175 struct strerror_impl_helper
1176 {
1177 static std::string call(_DummyT _Errcode)
1178 {
1179 using namespace std;
1180
1181 const char *result =
1182 strerror(_Errcode); // if you are there U need to disable _CRT_SECURE_NO_WARNINGS bullshit
1183
1184 return result ? result : "";
1185 }
1186 };
1187
1188 template<class _DummyT>
1189 struct strerror_impl_helper<true, true, _DummyT>
1190 {
1191 static std::string call(_DummyT _Errcode)
1192 {
1193 using namespace std;
1194
1195 std::string result;
1196
1197 size_t len = strerrorlen_s(_Errcode);
1198 if (len)
1199 {
1200 struct _RAII{
1201 char *buf;
1202 _RAII() : buf(0) {}
1203 ~_RAII() {delete [] buf;}
1204 } _tmp;
1205
1206 _tmp.buf = new char[len + 1];
1207 if(0 == strerror_s(_tmp.buf, len + 1, _Errcode))
1208 result = _tmp.buf;
1209 }
1210 return result;
1211 }
1212 };
1213
1214 template<class _DummyT>
1215 struct strerror_impl_helper<true, false, _DummyT>
1216 { // MS specific
1217 static std::string call(_DummyT _Errcode)
1218 {
1219 std::string result;
1220
1221 char buf[2048] = {0};
1222
1223 if(0 == strerror_s(buf, _Errcode))
1224 result = buf;
1225 return result;
1226 }
1227 };
1228
1229 class _strerror_s_arg
1230 {
1231 typedef int return_type; // would be errno_t fo C
1232 char buf[sizeof(return_type) * 14];
1233 _strerror_s_arg(...);
1234 operator return_type();
1235
1236 template<bool, class>
1237 friend struct _has_conforming_strerror_s;
1238 friend struct _has_nonconforming_strerror_s;
1239 };
1240
1241 class _strerrorlen_s_arg
1242 {
1243 typedef std::size_t return_type;
1244 char buf[sizeof(return_type) * 12];
1245 _strerrorlen_s_arg(...);
1246 operator return_type();
1247
1248 friend struct _has_conforming_strerrorlen_s;
1249 };
1250
1251 struct _has_conforming_strerrorlen_s
1252 {
1253 static const bool value =
1254 sizeof(
1255 strerrorlen_s(*_declptr<int>())
1256 ) != sizeof(_strerrorlen_s_arg);
1257 };
1258
1259 template<bool, class _T>
1260 struct _has_conforming_strerror_s
1261 {
1262 static const bool value =
1263 sizeof(
1264 strerror_s(_declptr<_T>(), *_declptr<std::size_t>(), *_declptr<int>())
1265 ) != sizeof(_strerror_s_arg);
1266 };
1267
1268 template<class _T>
1269 struct _has_conforming_strerror_s<true, _T>
1270 : stdex::false_type {};
1271
1272 struct _has_nonconforming_strerror_s
1273 {
1274 static const bool value =
1275 sizeof(
1276 strerror_s(_declptr<_strerror_s_arg>()->buf, *_declptr<int>())
1277 ) != sizeof(_strerror_s_arg);
1278 };
1279
1280 typedef
1281 stdex::bool_constant<
1282 _has_conforming_strerror_s<_has_nonconforming_strerror_s::value, char>::value ||
1283 _has_nonconforming_strerror_s::value
1284 > _has_strerror_s;
1285
1286 struct strerror_impl:
1287 strerror_impl_helper<_has_strerror_s::value, _has_conforming_strerrorlen_s::value, int>
1288 { };
1289
1290 static inline std::string _strerror(int _errnum)
1291 {
1292 std::string result =
1293 strerror_impl::call(_errnum);
1294
1295 if(result.empty())
1296 return _unknown_error();
1297 return result;
1298 }
1299
1300 static inline bool _is_valid_errnum(int _errnum)
1301 {
1302 return
1303 !strerror_impl::call(_errnum).empty();
1304 }
1305 }
1306
1307 using system_error_detail::_strerror;
1308 using system_error_detail::_is_valid_errnum;
1309
1310
1311 class _generic_error_category
1312 : public error_category
1313 { // categorize a generic error
1314 public:
1315 _generic_error_category()
1316 { // default constructor
1317 }
1318
1319 virtual const char *name() const _STDEX_NOEXCEPT_FUNCTION
1320 { // get name of category
1321 return ("generic");
1322 }
1323
1324 virtual std::string message(int _Errcode) const
1325 { // convert to name of error
1326 return _strerror(_Errcode);
1327 }
1328 };
1329
1330 class _io_stream_error_category
1331 : public _generic_error_category
1332 { // categorize a Posix error
1333 public:
1334 _io_stream_error_category()
1335 { // default constructor
1336 }
1337
1338 virtual const char *name() const _STDEX_NOEXCEPT_FUNCTION
1339 { // get name of category
1340 return ("iostream");
1341 }
1342
1343 virtual std::string message(int _Errcode) const
1344 { // convert to name of error
1345 if (_Errcode == (int) io_errc::stream)
1346 return ("iostream stream error");
1347 else
1348 return (_generic_error_category::message(_Errcode));
1349 }
1350 };
1351
1352 class _system_error_category
1353 : public _generic_error_category
1354 { // categorize a generic error
1355 public:
1356 _system_error_category()
1357 { // default constructor
1358 }
1359
1360 virtual const char *name() const _STDEX_NOEXCEPT_FUNCTION
1361 { // get name of category
1362 return ("system");
1363 }
1364
1365 virtual std::string message(int _Errcode) const
1366 { // convert to name of error
1367 return _strerror(_Errcode);
1368 }
1369
1370 virtual error_condition
1371 default_error_condition(int _Errval) const _STDEX_NOEXCEPT_FUNCTION
1372 { // make error_condition for error code (generic if possible)
1373 if (_is_valid_errnum(_Errval))
1374 return (error_condition(_Errval, generic_category()));
1375 else
1376 return (error_condition(_Errval, system_category()));
1377 }
1378 };
1379
1380 template<class _Cat>
1381 struct _error_objects
1382 { // wraps category objects
1383 static _Cat &_object()
1384 {
1385 static _Cat &_obj = *(new _Cat());
1386 return _obj;
1387 }
1388 };
1389 }
1390
1391 inline const error_category& generic_category() _STDEX_NOEXCEPT_FUNCTION
1392 { // get generic_category
1393 return (detail::_error_objects<detail::_generic_error_category>::_object());
1394 }
1395
1396 inline const error_category& iostream_category() _STDEX_NOEXCEPT_FUNCTION
1397 { // get iostream_category
1398 return (detail::_error_objects<detail::_io_stream_error_category>::_object());
1399 }
1400
1401 inline const error_category& system_category() _STDEX_NOEXCEPT_FUNCTION
1402 { // get system_category
1403 return (detail::_error_objects<detail::_system_error_category>::_object());
1404 }
1405
1406} // namespace stdex
1407
1408namespace _stdex_ADL
1409{
1410 template<class _Tp>
1411 inline
1412 static stdex::error_code _make_error_code(_Tp _val)
1413 {
1414 return make_error_code(_val);
1415 }
1416
1417 template<class _Tp>
1418 inline
1419 static stdex::error_condition _make_error_condition(_Tp _val)
1420 {
1421 return make_error_condition(_val);
1422 }
1423} // namespace _stdex_ADL
1424
1425#undef _STDEX_DELETED_FUNCTION
1426#undef _STDEX_NOEXCEPT_FUNCTION
1427
1428#endif // _STDEX_SYSTEM_ERROR_H