AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
AStacktrace.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include <AUI/Common/AString.h>
15#include <AUI/Common/AVector.h>
16#include <variant>
17#include <optional>
18
19
28class API_AUI_CORE AStacktrace {
29public:
33 class Entry {
34 friend class AStacktrace;
35 private:
36 void* mPtr;
37 AOptional<AString> mFunctionName;
38 AOptional<AString> mFileName;
39 AOptional<unsigned> mLineNumber;
40
41 public:
42 explicit Entry(void* ptr) : mPtr(ptr), mFunctionName(std::nullopt) {}
43
47 const AOptional<AString>& functionName() const noexcept {
48 return mFunctionName;
49 }
50
54 const AOptional<AString>& fileName() const noexcept {
55 return mFileName;
56 }
57
62 return mLineNumber;
63 }
64
65 void* ptr() const noexcept {
66 return mPtr;
67 }
68 };
69
70 using iterator = AVector<Entry>::iterator;
71
72 AStacktrace(aui::range<iterator> range): mEntries(range.begin(), range.end()) {}
73
86 aui::range<iterator> stripBeforeFunctionCall(void* pFunction, int maxAllowedOffsetInBytes = 50);
87
88 AStacktrace(const AStacktrace&) = default;
89 AStacktrace(AStacktrace&&) noexcept = default;
90
96 void resolveSymbolsIfNeeded() const noexcept;
97
98 [[nodiscard]]
99 const AVector<Entry>& entries() const noexcept {
100 return mEntries;
101 }
102
103 [[nodiscard]]
104 auto begin() const noexcept {
105 return mEntries.begin();
106 }
107
108 [[nodiscard]]
109 auto end() const noexcept {
110 return mEntries.end();
111 }
112
113 [[nodiscard]]
114 auto rbegin() const noexcept {
115 return mEntries.rbegin();
116 }
117
118 [[nodiscard]]
119 auto rend() const noexcept {
120 return mEntries.rend();
121 }
122
130 static AStacktrace capture(unsigned skipFrames = 0, unsigned maxFrames = 128) noexcept;
131
132private:
133 mutable AVector<Entry> mEntries;
134 mutable bool mSymbolNamesResolved = false;
135
136 explicit AStacktrace(AVector<Entry> entries) : mEntries(std::move(entries)) {}
137};
138
139inline std::ostream& operator<<(std::ostream& o, const AStacktrace& stacktrace) noexcept {
140 stacktrace.resolveSymbolsIfNeeded();
141 for (const auto& entry : stacktrace) {
142 o << " - at " << entry.ptr();
143 if (auto name = entry.functionName()) {
144 o << " " << *name;
145 }
146 o << "(";
147
148 if (auto filename = entry.fileName()) {
149 o << *filename;
150 } else {
151 o << "?";
152 }
153 o << ":";
154 if (auto line = entry.lineNumber()) {
155 o << *line;
156 } else {
157 o << "?";
158 }
159
160 o << ")" << std::endl;
161 }
162 return o;
163}
164
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition: AOptional.h:32
Stacktrace entry.
Definition: AStacktrace.h:33
const AOptional< AString > & fileName() const noexcept
Definition: AStacktrace.h:54
const AOptional< AString > & functionName() const noexcept
Definition: AStacktrace.h:47
AOptional< unsigned > lineNumber() const noexcept
Definition: AStacktrace.h:61
Stacktrace consisting of a collection of stack function frames.
Definition: AStacktrace.h:28
aui::range< iterator > stripBeforeFunctionCall(void *pFunction, int maxAllowedOffsetInBytes=50)
Tries to find the function pointer in stacktrace and strips stacktrace until function frame.
Definition: AStacktrace.cpp:7
static AStacktrace capture(unsigned skipFrames=0, unsigned maxFrames=128) noexcept
Creates stacktrace of the current thread.
Definition: AStacktraceImpl.cpp:156
void resolveSymbolsIfNeeded() const noexcept
Invokes function name resolution with function pointers.
Definition: AStacktraceImpl.cpp:152
A std::vector with AUI extensions.
Definition: AVector.h:38
Definition: iterators.h:50