• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

refvalue / cpp-essence / 12077418855

29 Nov 2024 01:18AM UTC coverage: 37.802% (+0.03%) from 37.774%
12077418855

push

github

refvalue
Simplified source_code_aware_runtime_error, without outputting the source-code location but storing it.

0 of 1 new or added line in 1 file covered. (0.0%)

19 existing lines in 2 files now uncovered.

1001 of 2648 relevant lines covered (37.8%)

42.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/exception.cpp
1
/*
2
 * Copyright (c) 2024 The RefValue Project
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to deal
6
 * in the Software without restriction, including without limitation the rights
7
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
 * copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
 * THE SOFTWARE.
21
 */
22

23
#include "exception.hpp"
24

25
#include "char8_t_remediation.hpp"
26
#include "format_remediation.hpp"
27
#include "functional.hpp"
28

29
#include <stdexcept>
30
#include <string>
31
#include <tuple>
32

33
#include <spdlog/spdlog.h>
34

35
namespace essence {
36
    namespace {
37
        template <invocable<const std::exception&> ExceptionCallback>
38
        void unwind_exception_ptr(const std::exception_ptr& ex, ExceptionCallback&& exception_callback) {
×
39
            if (ex) {
×
40
                try {
41
                    std::rethrow_exception(ex);
×
42
                } catch (const std::exception& inner_ex) {
×
43
                    invoke_optional(std::forward<ExceptionCallback>(exception_callback), inner_ex);
×
44
                } catch (...) {
×
45
                    invoke_optional(
×
46
                        std::forward<ExceptionCallback>(exception_callback), std::runtime_error{U8("Unknown error.")});
47
                }
48
            }
49
        }
50

51
        template <nullptr_or_invocable<std::exception_ptr> LevelCallback = std::nullptr_t,
52
            nullptr_or_invocable<abi::string&> CompleteCallback          = std::nullptr_t>
53
        void flatten_nested_exceptions(const std::exception_ptr& root, std::int32_t indent,
×
54
            LevelCallback&& level_callback = nullptr, CompleteCallback&& complete_callback = nullptr) {
55
            abi::string result;
×
56

57
            auto level_tuple           = std::forward_as_tuple(std::forward<LevelCallback>(level_callback));
58
            auto invoke_level_callback = [&](const std::exception_ptr& ex) {
×
59
                invoke_optional(std::get<0>(std::move(level_tuple)), ex);
×
60
            };
61

62
            auto complete_tuple           = std::forward_as_tuple(std::forward<CompleteCallback>(complete_callback));
63
            auto invoke_complete_callback = [&] { invoke_optional(std::get<0>(std::move(complete_tuple)), result); };
×
64

65
            auto appender = [&]<typename Callable>(
×
66
                                Callable&& self, const std::exception_ptr& current, std::int32_t level = 0) -> void {
67
                bool recursive{};
×
68
                auto tuple = std::forward_as_tuple(std::forward<Callable>(self));
69

70
                unwind_exception_ptr(current, [&](const std::exception& ex) {
×
71
                    if (const auto aggregate = dynamic_cast<const aggregate_error*>(&ex)) {
×
72
                        for (auto&& item : *aggregate) {
×
73
                            invoke_level_callback(item);
×
74
                        }
75
                    } else {
76
                        invoke_level_callback(current);
×
77
                    }
78

79
                    result.append(format(
×
NEW
80
                        U8("{} {}\n"), std::string(static_cast<std::size_t>(indent) * level, U8('-')), ex.what()));
×
81

82
                    try {
83
                        std::rethrow_if_nested(ex);
×
84
                    } catch (const std::exception&) {
×
85
                        recursive = true;
×
86

87
                        return std::apply(
×
88
                            [&level]<typename InnerCallable>(InnerCallable&& self) {
×
89
                                return std::forward<InnerCallable>(self)(
×
90
                                    std::forward<InnerCallable>(self), std::current_exception(), level + 1);
×
91
                            },
92
                            std::move(tuple));
93

94
                    } catch (...) {
×
95
                        spdlog::info(U8("Unknown error."));
96
                    }
97
                });
98

99
                if (!recursive) {
×
100
                    // Removes the redundant '\n'.
101
                    if (!result.empty()) {
×
102
                        result.pop_back();
103
                    }
104

UNCOV
105
                    invoke_complete_callback();
×
106
                }
107
            };
108

UNCOV
109
            appender(appender, root);
×
110
        }
111
    } // namespace
112

113
    aggregate_error::iterator aggregate_error::begin() const noexcept {
×
UNCOV
114
        return exceptions_.data();
×
115
    }
116

117
    aggregate_error::iterator aggregate_error::end() const noexcept {
×
UNCOV
118
        return exceptions_.data() + exceptions_.size();
×
119
    }
120

121
    aggregate_error::reverse_iterator aggregate_error::rbegin() const noexcept {
×
UNCOV
122
        return reverse_iterator{begin() + size()};
×
123
    }
124

125
    aggregate_error::reverse_iterator aggregate_error::rend() const noexcept {
×
UNCOV
126
        return reverse_iterator{begin()};
×
127
    }
128

129
    bool aggregate_error::empty() const noexcept {
×
UNCOV
130
        return exceptions_.empty();
×
131
    }
132

133
    std::size_t aggregate_error::size() const noexcept {
×
UNCOV
134
        return exceptions_.size();
×
135
    }
136

UNCOV
137
    void aggregate_error::flatten_and_throw(const std::exception_ptr& root, std::int32_t indent) {
×
138
        abi::vector<std::exception_ptr> exceptions;
139

140
        flatten_nested_exceptions(
×
141
            root, indent, [&](const std::exception_ptr& ex) { exceptions.emplace_back(ex); },
×
142
            [&](const abi::string& result) { throw aggregate_error{std::move(exceptions), result}; });
×
143

UNCOV
144
        throw;
×
145
    }
146

UNCOV
147
    aggregate_error::aggregate_error(abi::vector<value_type>&& exceptions, std::string_view what)
×
148
        : runtime_error{std::string{what}}, exceptions_{std::move(exceptions)} {}
×
149

UNCOV
150
    abi::string serialize_nested_exceptions(const std::exception_ptr& root, std::int32_t indent) {
×
151
        abi::string result;
×
152

UNCOV
153
        flatten_nested_exceptions(root, indent, nullptr, [&](abi::string& inner) { result = std::move(inner); });
×
154

UNCOV
155
        return result;
×
156
    }
157
} // namespace essence
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc