|
42 | 42 | * It is needed to avoid name conflicts between the structure and the wrapper class. |
43 | 43 | */ |
44 | 44 | namespace lcs { |
| 45 | +/** |
| 46 | + * @brief A wrapper class around the `struct callstack`. |
| 47 | + * |
| 48 | + * It provides the usual constructors and operator overloads. Additionally, it contains the |
| 49 | + * possibility to implicitly cast an object of this class to a pointer to the C structure. |
| 50 | + */ |
| 51 | +class callstack { |
| 52 | + /** A `typedef` for convenience. */ |
| 53 | + typedef ::callstack struct_callstack; |
| 54 | + /** The original C structure. */ |
| 55 | + struct_callstack self; |
| 56 | + |
45 | 57 | /** |
46 | | - * @brief A wrapper class around the `struct callstack`. |
| 58 | + * @brief Helper function to throw the appropriate exception. |
47 | 59 | * |
48 | | - * It provides the usual constructors and operator overloads. Additionally, it contains the |
49 | | - * possibility to implicitly cast an object of this class to a pointer to the C structure. |
| 60 | + * @throws A `system_error` if compiled using C++11 or newer, a runtime error otherwise. |
50 | 61 | */ |
51 | | - class callstack { |
52 | | - /** A `typedef` for convenience. */ |
53 | | - typedef ::callstack struct_callstack; |
54 | | - /** The original C structure. */ |
55 | | - struct_callstack self; |
56 | | - |
57 | | - /** |
58 | | - * @brief Helper function to throw the appropriate exception. |
59 | | - * |
60 | | - * @throws A `system_error` if compiled using C++11 or newer, a runtime error otherwise. |
61 | | - */ |
62 | | - inline static void error() { |
| 62 | + inline static void error() { |
63 | 63 | #if __cplusplus >= 201103 |
64 | | - throw std::system_error(errno, std::generic_category()); |
| 64 | + throw std::system_error(errno, std::generic_category()); |
65 | 65 | #else |
66 | | - throw std::runtime_error("Backtrace invalid"); |
| 66 | + throw std::runtime_error("Backtrace invalid"); |
67 | 67 | #endif |
68 | | - } |
69 | | - |
70 | | - public: |
71 | | - /** |
72 | | - * @brief A trivial default constructor. |
73 | | - * |
74 | | - * Zero-initializes the underlying C structure. If the given boolean value is `true`, |
75 | | - * it is initialized using the function `callstack_emplace()`. |
76 | | - * Throws a `runtime_error` or a `system_error` if compiled using C++11 or newer if |
77 | | - * `emplace` is set to `true` and the backtrace could not be created. |
78 | | - * |
79 | | - * @param emplace Whether to call `callstack_emplace()`. |
80 | | - */ |
81 | | - inline explicit callstack(bool emplace = true) { |
82 | | - if (emplace) { |
83 | | - if (!callstack_emplace(*this)) { |
84 | | - error(); |
85 | | - } |
86 | | - } else { |
87 | | - callstack_create(*this); |
88 | | - } |
89 | | - } |
90 | | - |
91 | | - /** |
92 | | - * @brief Constructs this object using the given stack address. |
93 | | - * |
94 | | - * Initializes the underlying C structure using the function `callstack_emplaceWithAddress()`. |
95 | | - * Throws a `runtime_error` or a `system_error` if compiled using C++11 or newer if |
96 | | - * the backtrace could not be created. |
97 | | - * |
98 | | - * @param address The stack address after which frames are ignored. |
99 | | - */ |
100 | | - inline explicit callstack(void* address) { |
101 | | - if (!callstack_emplaceWithAddress(*this, address)) { |
102 | | - error(); |
103 | | - } |
104 | | - } |
105 | | - |
106 | | - /** |
107 | | - * @brief Constructs the underlying C structure with the given backtrace. |
108 | | - * |
109 | | - * if the given trace length is smaller than zero, a `runtime_error` or a `system_error` |
110 | | - * if compiled using C++11 or newer is thrown. |
111 | | - * |
112 | | - * @param trace The backtrace. |
113 | | - * @param length The length of the given backtrace. |
114 | | - */ |
115 | | - inline callstack(void** trace, int length) { |
116 | | - if (!callstack_emplaceWithBacktrace(*this, trace, length)) { |
| 68 | + } |
| 69 | + |
| 70 | +public: |
| 71 | + /** |
| 72 | + * @brief A trivial default constructor. |
| 73 | + * |
| 74 | + * Zero-initializes the underlying C structure. If the given boolean value is `true`, |
| 75 | + * it is initialized using the function `callstack_emplace()`. |
| 76 | + * Throws a `runtime_error` or a `system_error` if compiled using C++11 or newer if |
| 77 | + * `emplace` is set to `true` and the backtrace could not be created. |
| 78 | + * |
| 79 | + * @param emplace Whether to call `callstack_emplace()`. |
| 80 | + */ |
| 81 | + inline explicit callstack(bool emplace = true) { |
| 82 | + if (emplace) { |
| 83 | + if (!callstack_emplace(*this)) { |
117 | 84 | error(); |
118 | 85 | } |
119 | | - } |
120 | | - |
121 | | - inline callstack(const callstack& other) LCS_NOEXCEPT { |
122 | | - callstack_create(*this); |
123 | | - callstack_copy(*this, other); |
124 | | - } |
125 | | - |
126 | | - /** |
127 | | - * @brief Constructs a callstack object from the given C structure. |
128 | | - * |
129 | | - * @param cCallstack The C structure to be copied. |
130 | | - */ |
131 | | - inline explicit callstack(const struct_callstack* cCallstack) LCS_NOEXCEPT { |
| 86 | + } else { |
132 | 87 | callstack_create(*this); |
133 | | - callstack_copy(*this, cCallstack); |
134 | | - } |
135 | | - |
136 | | - inline ~callstack() LCS_NOEXCEPT { |
137 | | - callstack_destroy(*this); |
138 | | - } |
139 | | - |
140 | | - inline callstack& operator=(const callstack& other) LCS_NOEXCEPT { |
141 | | - if (&other != this) { |
142 | | - callstack_copy(*this, other); |
143 | | - } |
144 | | - return *this; |
145 | 88 | } |
146 | | - |
147 | | - #if __cplusplus >= 201103 |
148 | | - inline callstack(callstack&& other) noexcept |
149 | | - : self(std::move(other.self)) { |
150 | | - callstack_create(other); |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * @brief Constructs this object using the given stack address. |
| 93 | + * |
| 94 | + * Initializes the underlying C structure using the function `callstack_emplaceWithAddress()`. |
| 95 | + * Throws a `runtime_error` or a `system_error` if compiled using C++11 or newer if |
| 96 | + * the backtrace could not be created. |
| 97 | + * |
| 98 | + * @param address The stack address after which frames are ignored. |
| 99 | + */ |
| 100 | + inline explicit callstack(void* address) { |
| 101 | + if (!callstack_emplaceWithAddress(*this, address)) { |
| 102 | + error(); |
151 | 103 | } |
152 | | - |
153 | | - inline auto operator=(callstack&& other) noexcept -> callstack& { |
154 | | - callstack_destroy(*this); |
155 | | - self = std::move(other.self); |
156 | | - callstack_create(other); |
157 | | - return *this; |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * @brief Constructs the underlying C structure with the given backtrace. |
| 108 | + * |
| 109 | + * if the given trace length is smaller than zero, a `runtime_error` or a `system_error` |
| 110 | + * if compiled using C++11 or newer is thrown. |
| 111 | + * |
| 112 | + * @param trace The backtrace. |
| 113 | + * @param length The length of the given backtrace. |
| 114 | + */ |
| 115 | + inline callstack(void** trace, int length) { |
| 116 | + if (!callstack_emplaceWithBacktrace(*this, trace, length)) { |
| 117 | + error(); |
158 | 118 | } |
159 | | - #endif |
| 119 | + } |
160 | 120 |
|
161 | | - inline callstack& translate(bool onlyBinaries = false) { |
162 | | - if (onlyBinaries) { |
163 | | - if (callstack_getBinaries(*this) == LCS_NULL) { |
164 | | - throw std::runtime_error("LCS: Failed to translate the callstack (binaries only)"); |
165 | | - } |
166 | | - } else { |
167 | | - if (callstack_toArray(*this) == LCS_NULL) { |
168 | | - throw std::runtime_error("LCS: Failed to translate the callstack"); |
169 | | - } |
170 | | - } |
171 | | - return *this; |
| 121 | + inline callstack(const callstack& other) LCS_NOEXCEPT { |
| 122 | + callstack_create(*this); |
| 123 | + callstack_copy(*this, other); |
| 124 | + } |
| 125 | + |
| 126 | + /** |
| 127 | + * @brief Constructs a callstack object from the given C structure. |
| 128 | + * |
| 129 | + * @param cCallstack The C structure to be copied. |
| 130 | + */ |
| 131 | + inline explicit callstack(const struct_callstack* cCallstack) LCS_NOEXCEPT { |
| 132 | + callstack_create(*this); |
| 133 | + callstack_copy(*this, cCallstack); |
| 134 | + } |
| 135 | + |
| 136 | + inline ~callstack() LCS_NOEXCEPT { |
| 137 | + callstack_destroy(*this); |
| 138 | + } |
| 139 | + |
| 140 | + inline callstack& operator=(const callstack& other) LCS_NOEXCEPT { |
| 141 | + if (&other != this) { |
| 142 | + callstack_copy(*this, other); |
172 | 143 | } |
| 144 | + return *this; |
| 145 | + } |
| 146 | + |
| 147 | +#if __cplusplus >= 201103 |
| 148 | + inline callstack(callstack&& other) noexcept |
| 149 | + : self(std::move(other.self)) { |
| 150 | + callstack_create(other); |
| 151 | + } |
173 | 152 |
|
174 | | - #ifdef LCS_USE_UNSAFE_OPTIMIZATION |
175 | | - inline callstack& translateBinariesCached() { |
176 | | - if (callstack_getBinariesCached(*this) == LCS_NULL) { |
177 | | - throw std::runtime_error("LCS: Failed to translate the callstack (cached binaries)"); |
| 153 | + inline auto operator=(callstack&& other) noexcept -> callstack& { |
| 154 | + callstack_destroy(*this); |
| 155 | + self = std::move(other.self); |
| 156 | + callstack_create(other); |
| 157 | + return *this; |
| 158 | + } |
| 159 | +#endif |
| 160 | + |
| 161 | + /** |
| 162 | + * Translates this callstack object. |
| 163 | + * |
| 164 | + * @param onlyBinaries whether to only deduct the names of the runtime images |
| 165 | + * @return @c this |
| 166 | + * @throws an exception when the translation failed |
| 167 | + */ |
| 168 | + inline callstack& translate(bool onlyBinaries = false) { |
| 169 | + if (onlyBinaries) { |
| 170 | + if (callstack_getBinaries(*this) == LCS_NULL) { |
| 171 | + throw std::runtime_error("LCS: Failed to translate the callstack (binaries only)"); |
| 172 | + } |
| 173 | + } else { |
| 174 | + if (callstack_toArray(*this) == LCS_NULL) { |
| 175 | + throw std::runtime_error("LCS: Failed to translate the callstack"); |
178 | 176 | } |
179 | | - return *this; |
180 | 177 | } |
181 | | - #endif |
| 178 | + return *this; |
| 179 | + } |
182 | 180 |
|
183 | | - LCS_CONSTEXPR inline const callstack_frame* begin() const LCS_NOEXCEPT { |
184 | | - return self.frames; |
| 181 | +#ifdef LCS_USE_UNSAFE_OPTIMIZATION |
| 182 | + /** |
| 183 | + * @brief Translates this callstack object. |
| 184 | + * |
| 185 | + * Only the names of the runtime images are deducted. They are backed by |
| 186 | + * the cache of the library and only valid as long as the cache is. |
| 187 | + * |
| 188 | + * @return @c this |
| 189 | + * @throws an exception if the translation failed |
| 190 | + */ |
| 191 | + inline callstack& translateBinariesCached() { |
| 192 | + if (callstack_getBinariesCached(*this) == LCS_NULL) { |
| 193 | + throw std::runtime_error("LCS: Failed to translate the callstack (cached binaries)"); |
185 | 194 | } |
| 195 | + return *this; |
| 196 | + } |
| 197 | +#endif |
186 | 198 |
|
187 | | - LCS_CONSTEXPR inline const callstack_frame* end() const LCS_NOEXCEPT { |
188 | | - return self.frames + self.frameCount; |
189 | | - } |
| 199 | + LCS_CONSTEXPR inline const callstack_frame* begin() const LCS_NOEXCEPT { |
| 200 | + return self.frames; |
| 201 | + } |
| 202 | + |
| 203 | + LCS_CONSTEXPR inline const callstack_frame* end() const LCS_NOEXCEPT { |
| 204 | + return self.frames + self.frameCount; |
| 205 | + } |
190 | 206 |
|
191 | | - inline operator struct_callstack*() LCS_NOEXCEPT { return &self; } |
192 | | - inline operator const struct_callstack*() const LCS_NOEXCEPT { return &self; } |
| 207 | + inline operator struct_callstack*() LCS_NOEXCEPT { return &self; } |
| 208 | + inline operator const struct_callstack*() const LCS_NOEXCEPT { return &self; } |
193 | 209 |
|
194 | | - inline struct_callstack* operator->() LCS_NOEXCEPT { return &self; } |
195 | | - inline const struct_callstack* operator->() const LCS_NOEXCEPT { return &self; } |
196 | | - }; |
| 210 | + inline struct_callstack* operator->() LCS_NOEXCEPT { return &self; } |
| 211 | + inline const struct_callstack* operator->() const LCS_NOEXCEPT { return &self; } |
| 212 | +}; |
197 | 213 | } |
198 | 214 |
|
199 | 215 | #endif /* __lcs_callstack_hpp */ |
|
0 commit comments