|
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