summaryrefslogtreecommitdiffstats
path: root/src/third-party/scnlib/include/scn/detail/error.h
blob: f79e7419cd5d2128629041d06f220ae68dfb6667 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2017 Elias Kosunen
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file is a part of scnlib:
//     https://github.com/eliaskosunen/scnlib

#ifndef SCN_DETAIL_ERROR_H
#define SCN_DETAIL_ERROR_H

#include "fwd.h"

namespace scn {
    SCN_BEGIN_NAMESPACE

    /**
     * Error class.
     * Used as a return value for functions without a success value.
     */
    class SCN_TRIVIAL_ABI error {
    public:
        /// Error code
        enum code : char {
            /// No error
            good = 0,
            /// EOF
            end_of_range,
            /// Format string was invalid
            invalid_format_string,
            /// Scanned value was invalid for given type.
            /// e.g. a period '.' when scanning for an int
            invalid_scanned_value,
            /// Stream does not support the performed operation
            invalid_operation,
            /// Scanned value was out of range for the desired type.
            /// (e.g. `>2^32` for an `uint32_t`)
            value_out_of_range,
            /// Invalid argument given to operation
            invalid_argument,
            /// Source range has invalid (utf-8 or utf-16) encoding
            invalid_encoding,
            /// This operation is only possible with exceptions enabled
            exceptions_required,
            /// The source range emitted an error.
            source_error,
            /// The source range emitted an error that cannot be recovered
            /// from. The stream is now unusable.
            unrecoverable_source_error,

            unrecoverable_internal_error,

            max_error
        };

        struct success_tag_t {
        };
        static constexpr success_tag_t success_tag() noexcept
        {
            return {};
        }

        constexpr error() noexcept = default;
        constexpr error(success_tag_t) noexcept : error() {}
        constexpr error(enum code c, const char* m) noexcept
            : m_msg(m), m_code(c)
        {
        }

        /// Evaluated to true if there was no error
        constexpr explicit operator bool() const noexcept
        {
            return m_code == good;
        }
        constexpr bool operator!() const noexcept
        {
            return !(operator bool());
        }

        constexpr operator enum code() const noexcept { return m_code; }

        /// Get error code
        SCN_NODISCARD constexpr enum code code() const noexcept
        {
            return m_code;
        }
        SCN_NODISCARD constexpr const char* msg() const noexcept
        {
            return m_msg;
        }

        /// Returns `true` if, after this error, the state of the given input
        /// range is consistent, and thus, the range can be used for new
        /// scanning operations.
        SCN_NODISCARD constexpr bool is_recoverable() const noexcept
        {
            return !(m_code == unrecoverable_source_error ||
                     m_code == unrecoverable_internal_error);
        }

    private:
        const char* m_msg{nullptr};
        enum code m_code { good };
    };

    constexpr inline bool operator==(error a, error b) noexcept
    {
        return a.code() == b.code();
    }
    constexpr inline bool operator!=(error a, error b) noexcept
    {
        return !(a == b);
    }

    namespace detail {
        struct error_handler {
            constexpr error_handler() = default;

            void on_error(error e);
            void on_error(const char* msg);
        };
    }  // namespace detail

    SCN_END_NAMESPACE
}  // namespace scn

#endif