cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / cpp-common / bt2 / internal / comp-cls-bridge.hpp
1 /*
2 * Copyright (c) 2024 EfficiOS, Inc.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #ifndef BABELTRACE_CPP_COMMON_BT2_INTERNAL_COMP_CLS_BRIDGE_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_INTERNAL_COMP_CLS_BRIDGE_HPP
9
10 #include <babeltrace2/babeltrace.h>
11
12 #include "cpp-common/bt2c/c-string-view.hpp"
13 #include "logging/log-api.h"
14
15 #include "../integer-range-set.hpp"
16 #include "../logging.hpp"
17 #include "../private-query-executor.hpp"
18 #include "../self-component-class.hpp"
19 #include "../self-component-port.hpp"
20 #include "../self-message-iterator-configuration.hpp"
21 #include "../self-message-iterator.hpp"
22 #include "../value.hpp"
23
24 namespace bt2 {
25 namespace internal {
26
27 constexpr bt2c::CStringView unhandledExcLogStr() noexcept
28 {
29 return "Unhandled exception.";
30 }
31
32 constexpr bt2c::CStringView unhandledExcLogTag() noexcept
33 {
34 return "PLUGIN-DEV-HPP";
35 }
36
37 /*
38 * Base class of any component class bridge.
39 *
40 * `UserCompClsT` is the actual C++ user component class and `TypesT`
41 * is a structure offering the following specific types:
42 *
43 * `LibSelfCompCls`:
44 * Self component class library type.
45 *
46 * `LibSelfComp`:
47 * Self component library type.
48 *
49 * `LibSelfCompCfg`:
50 * Self component configuration library type.
51 *
52 * `SelfComp`:
53 * Self component type.
54 */
55 template <typename UserCompClsT, typename TypesT>
56 class CompClsBridge
57 {
58 private:
59 using _LibSelfCompPtr = typename TypesT::LibSelfComp *;
60
61 public:
62 static UserCompClsT& userCompFromLibSelfCompPtr(const _LibSelfCompPtr libSelfCompPtr) noexcept
63 {
64 return typename TypesT::SelfComp {libSelfCompPtr}.template data<UserCompClsT>();
65 }
66
67 static bt_component_class_initialize_method_status init(const _LibSelfCompPtr libSelfCompPtr,
68 typename TypesT::LibSelfCompCfg *,
69 const bt_value * const libParamsPtr,
70 void * const initData) noexcept
71 {
72 const auto selfComp = typename TypesT::SelfComp {libSelfCompPtr};
73
74 try {
75 const auto comp =
76 new UserCompClsT {selfComp, ConstMapValue {libParamsPtr},
77 static_cast<typename UserCompClsT::InitData *>(initData)};
78
79 selfComp.data(*comp);
80 } catch (const std::bad_alloc&) {
81 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
82 } catch (const Error&) {
83 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
84 } catch (...) {
85 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(selfComp.loggingLevel()),
86 unhandledExcLogTag(), unhandledExcLogStr());
87 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
88 }
89
90 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
91 }
92
93 static void finalize(const _LibSelfCompPtr libSelfCompPtr) noexcept
94 {
95 delete &userCompFromLibSelfCompPtr(libSelfCompPtr);
96 }
97
98 static bt_component_class_get_supported_mip_versions_method_status
99 getSupportedMipVersions(typename TypesT::LibSelfCompCls * const libSelfCompClsPtr,
100 const bt_value * const libParamsPtr, void *,
101 const bt_logging_level logLevel,
102 bt_integer_range_set_unsigned * const libSupportedVersionsPtr) noexcept
103 {
104 try {
105 UserCompClsT::getSupportedMipVersions(
106 SelfComponentClass {libSelfCompClsPtr}, ConstMapValue {libParamsPtr},
107 static_cast<LoggingLevel>(logLevel),
108 UnsignedIntegerRangeSet {libSupportedVersionsPtr});
109 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_OK;
110 } catch (const std::bad_alloc&) {
111 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_MEMORY_ERROR;
112 } catch (const Error&) {
113 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
114 } catch (...) {
115 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(logLevel), unhandledExcLogTag(),
116 unhandledExcLogStr());
117 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
118 }
119 }
120
121 static bt_component_class_query_method_status
122 query(typename TypesT::LibSelfCompCls * const libSelfCompClsPtr,
123 bt_private_query_executor * const libPrivQueryExecPtr, const char * const object,
124 const bt_value * const libParamsPtr, void * const data,
125 const bt_value ** const libResultPtr) noexcept
126 {
127 const auto privQueryExec = PrivateQueryExecutor {libPrivQueryExecPtr};
128
129 try {
130 auto result = UserCompClsT::query(
131 SelfComponentClass {libSelfCompClsPtr}, privQueryExec, object,
132 ConstValue {libParamsPtr}, static_cast<typename UserCompClsT::QueryData *>(data));
133
134 *libResultPtr = result.release().libObjPtr();
135 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
136 } catch (const TryAgain&) {
137 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
138 } catch (const UnknownObject&) {
139 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
140 } catch (const std::bad_alloc&) {
141 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
142 } catch (const Error&) {
143 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
144 } catch (...) {
145 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
146 unhandledExcLogTag(), unhandledExcLogStr());
147 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
148 }
149 }
150 };
151
152 template <typename SpecCompClsBridgeT, typename TypesT>
153 struct CompClsBridgeWithInputPorts
154 {
155 static bt_component_class_port_connected_method_status
156 inputPortConnected(typename TypesT::LibSelfComp * const libSelfCompPtr,
157 bt_self_component_port_input * const libSelfCompPortPtr,
158 const bt_port_output * const libOtherPortPtr) noexcept
159 {
160 try {
161 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
162 .inputPortConnected(SelfComponentInputPort {libSelfCompPortPtr},
163 ConstOutputPort {libOtherPortPtr});
164 } catch (const std::bad_alloc&) {
165 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
166 } catch (const Error&) {
167 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
168 } catch (...) {
169 BT_LOG_WRITE_CUR_LVL(
170 BT_LOG_WARNING,
171 static_cast<int>(typename TypesT::SelfComp {libSelfCompPtr}.loggingLevel()),
172 unhandledExcLogTag(), unhandledExcLogStr());
173 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
174 }
175
176 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
177 }
178 };
179
180 template <typename SpecCompClsBridgeT, typename TypesT>
181 struct CompClsBridgeWithOutputPorts
182 {
183 static bt_component_class_port_connected_method_status
184 outputPortConnected(typename TypesT::LibSelfComp * const libSelfCompPtr,
185 bt_self_component_port_output * const libSelfCompPortPtr,
186 const bt_port_input * const libOtherPortPtr) noexcept
187 {
188 try {
189 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
190 .outputPortConnected(SelfComponentOutputPort {libSelfCompPortPtr},
191 ConstInputPort {libOtherPortPtr});
192 } catch (const std::bad_alloc&) {
193 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
194 } catch (const Error&) {
195 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
196 } catch (...) {
197 BT_LOG_WRITE_CUR_LVL(
198 BT_LOG_WARNING,
199 static_cast<int>(typename TypesT::SelfComp {libSelfCompPtr}.loggingLevel()),
200 unhandledExcLogTag(), unhandledExcLogStr());
201 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
202 }
203
204 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
205 }
206 };
207
208 struct SrcCompClsTypes final
209 {
210 using LibSelfCompCls = bt_self_component_class_source;
211 using LibSelfComp = bt_self_component_source;
212 using LibSelfCompCfg = bt_self_component_source_configuration;
213 using SelfComp = SelfSourceComponent;
214 };
215
216 template <typename UserCompClsT>
217 class SrcCompClsBridge final :
218 public CompClsBridge<UserCompClsT, SrcCompClsTypes>,
219 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsTypes>
220 {
221 };
222
223 struct FltCompClsTypes final
224 {
225 using LibSelfCompCls = bt_self_component_class_filter;
226 using LibSelfComp = bt_self_component_filter;
227 using LibSelfCompCfg = bt_self_component_filter_configuration;
228 using SelfComp = SelfFilterComponent;
229 };
230
231 template <typename UserCompClsT>
232 class FltCompClsBridge final :
233 public CompClsBridge<UserCompClsT, FltCompClsTypes>,
234 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsTypes>,
235 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsTypes>
236 {
237 };
238
239 struct SinkCompClsTypes final
240 {
241 using LibSelfCompCls = bt_self_component_class_sink;
242 using LibSelfComp = bt_self_component_sink;
243 using LibSelfCompCfg = bt_self_component_sink_configuration;
244 using SelfComp = SelfSinkComponent;
245 };
246
247 template <typename UserCompClsT>
248 class SinkCompClsBridge final :
249 public CompClsBridge<UserCompClsT, SinkCompClsTypes>,
250 public CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsTypes>
251 {
252 public:
253 using CompClsBridge<UserCompClsT, SinkCompClsTypes>::userCompFromLibSelfCompPtr;
254
255 static bt_component_class_sink_consume_method_status
256 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
257 {
258 try {
259 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
260 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
261 } else {
262 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
263 }
264 } catch (const TryAgain&) {
265 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
266 } catch (const std::bad_alloc&) {
267 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
268 } catch (const Error&) {
269 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
270 } catch (...) {
271 BT_LOG_WRITE_CUR_LVL(
272 BT_LOG_WARNING, static_cast<int>(SelfSinkComponent {libSelfCompPtr}.loggingLevel()),
273 unhandledExcLogTag(), unhandledExcLogStr());
274 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
275 }
276 }
277
278 static bt_component_class_sink_graph_is_configured_method_status
279 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
280 {
281 try {
282 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
283 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK;
284 } catch (const std::bad_alloc&) {
285 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
286 } catch (const Error&) {
287 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
288 } catch (...) {
289 BT_LOG_WRITE_CUR_LVL(
290 BT_LOG_WARNING, static_cast<int>(SelfSinkComponent {libSelfCompPtr}.loggingLevel()),
291 unhandledExcLogTag(), unhandledExcLogStr());
292 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
293 }
294 }
295 };
296
297 template <typename UserMsgIterT>
298 class MsgIterClsBridge final
299 {
300 public:
301 static UserMsgIterT&
302 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
303 {
304 return SelfMessageIterator {libSelfMsgIterPtr}.data<UserMsgIterT>();
305 }
306
307 static bt_message_iterator_class_initialize_method_status
308 init(bt_self_message_iterator * const libSelfMsgIterPtr,
309 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
310 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
311 {
312 const auto selfMsgIter = SelfMessageIterator {libSelfMsgIterPtr};
313
314 try {
315 const auto msgIter = new UserMsgIterT {
316 selfMsgIter, SelfMessageIteratorConfiguration {libSelfMsgIterConfigPtr},
317 SelfComponentOutputPort {libSelfCompPortPtr}};
318
319 selfMsgIter.data(*msgIter);
320 } catch (const std::bad_alloc&) {
321 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
322 } catch (const Error&) {
323 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
324 } catch (...) {
325 BT_LOG_WRITE_CUR_LVL(
326 BT_LOG_WARNING,
327 static_cast<int>(
328 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
329 unhandledExcLogTag(), unhandledExcLogStr());
330 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
331 }
332
333 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
334 }
335
336 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
337 {
338 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
339 }
340
341 static bt_message_iterator_class_next_method_status
342 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
343 const uint64_t capacity, uint64_t * const count) noexcept
344 {
345 try {
346 auto msgArray = ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
347 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
348
349 msgIter.next(msgArray);
350 *count = msgArray.release();
351
352 if (G_LIKELY(*count > 0)) {
353 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
354 } else {
355 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
356 }
357 } catch (const TryAgain&) {
358 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
359 } catch (const std::bad_alloc&) {
360 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
361 } catch (const Error&) {
362 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
363 } catch (...) {
364 BT_LOG_WRITE_CUR_LVL(
365 BT_LOG_WARNING,
366 static_cast<int>(
367 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
368 unhandledExcLogTag(), unhandledExcLogStr());
369 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
370 }
371 }
372
373 static bt_message_iterator_class_can_seek_beginning_method_status
374 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
375 bt_bool * const canSeek) noexcept
376 {
377 try {
378 *canSeek = static_cast<bt_bool>(
379 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
380 } catch (const TryAgain&) {
381 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
382 } catch (const std::bad_alloc&) {
383 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
384 } catch (const Error&) {
385 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
386 } catch (...) {
387 BT_LOG_WRITE_CUR_LVL(
388 BT_LOG_WARNING,
389 static_cast<int>(
390 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
391 unhandledExcLogTag(), unhandledExcLogStr());
392 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
393 }
394
395 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
396 }
397
398 static bt_message_iterator_class_seek_beginning_method_status
399 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
400 {
401 try {
402 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
403 } catch (const TryAgain&) {
404 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
405 } catch (const std::bad_alloc&) {
406 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
407 } catch (const Error&) {
408 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
409 } catch (...) {
410 BT_LOG_WRITE_CUR_LVL(
411 BT_LOG_WARNING,
412 static_cast<int>(
413 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
414 unhandledExcLogTag(), unhandledExcLogStr());
415 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
416 }
417
418 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
419 }
420
421 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
422 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
423 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
424 {
425 try {
426 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
427 .canSeekNsFromOrigin(nsFromOrigin));
428 } catch (const TryAgain&) {
429 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
430 } catch (const std::bad_alloc&) {
431 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
432 } catch (const Error&) {
433 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
434 } catch (...) {
435 BT_LOG_WRITE_CUR_LVL(
436 BT_LOG_WARNING,
437 static_cast<int>(
438 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
439 unhandledExcLogTag(), unhandledExcLogStr());
440 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
441 }
442
443 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
444 }
445
446 static bt_message_iterator_class_seek_ns_from_origin_method_status
447 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
448 const std::int64_t nsFromOrigin) noexcept
449 {
450 try {
451 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
452 } catch (const TryAgain&) {
453 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
454 } catch (const std::bad_alloc&) {
455 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
456 } catch (const Error&) {
457 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
458 } catch (...) {
459 BT_LOG_WRITE_CUR_LVL(
460 BT_LOG_WARNING,
461 static_cast<int>(
462 SelfMessageIterator {libSelfMsgIterPtr}.component().loggingLevel()),
463 unhandledExcLogTag(), unhandledExcLogStr());
464 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
465 }
466
467 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
468 }
469 };
470
471 } /* namespace internal */
472 } /* namespace bt2 */
473
474 #endif /* BABELTRACE_CPP_COMMON_BT2_INTERNAL_COMP_CLS_BRIDGE_HPP */
This page took 0.038578 seconds and 4 git commands to generate.