.. _program_listing_file__tmp_ws_src_smacc2_smacc2_include_smacc2_introspection_introspection.hpp: Program Listing for File introspection.hpp ========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/smacc2/smacc2/include/smacc2/introspection/introspection.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2021 RobosoftAI Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /***************************************************************************************************************** * * Authors: Pablo Inigo Blasco, Brett Aldrich * ******************************************************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include "smacc2_msgs/msg/smacc_transition.hpp" namespace sc = boost::statechart; namespace smacc2 { namespace introspection { using namespace boost; using namespace smacc2::default_transition_tags; void transitionInfoToMsg( const SmaccTransitionInfo & transition, smacc2_msgs::msg::SmaccTransition & transitionMsg); typedef std::allocator SmaccAllocator; template auto optionalNodeHandle(std::shared_ptr & obj) -> T * { //return obj->getNode(); return obj.get; } template auto optionalNodeHandle(boost::intrusive_ptr & obj) -> T * { //return obj->getNode(); return obj.get(); } template auto optionalNodeHandle(T * obj) -> T * { return obj; } inline std::string demangleSymbol(const std::string & name) { return demangleSymbol(name.c_str()); } inline std::string demangleSymbol(const char * name) { #if (__GNUC__ && __cplusplus && __GNUC__ >= 3) int status; char * res = abi::__cxa_demangle(name, 0, 0, &status); if (res) { const std::string demangled_name(res); std::free(res); return demangled_name; } // Demangling failed, fallback to mangled name return std::string(name); #else return std::string(name); #endif } template inline std::string demangleSymbol() { return demangleSymbol(typeid(T).name()); } template inline std::string demangledTypeName() { return demangleSymbol(typeid(T).name()); } inline std::string demangleType(const std::type_info * tinfo) { return demangleSymbol(tinfo->name()); } inline std::string demangleType(const std::type_info & tinfo) { return demangleSymbol(tinfo.name()); } template struct typelist { }; //------------------------------------------------------------------------- template class HasEventLabel { private: typedef char YesType[1]; typedef char NoType[2]; template static YesType & test(decltype(&C::getEventLabel)); template static NoType & test(...); public: enum { value = sizeof(test(0)) == sizeof(YesType) }; }; template typename std::enable_if::value, void>::type EventLabel(std::string & label) { label = T::getEventLabel(); } template typename std::enable_if::value, void>::type EventLabel(std::string & label) { label = ""; } //----------------------------------------------------------------------- template class HasAutomaticTransitionTag { private: typedef char YesType[1]; typedef char NoType[2]; template static YesType & test(decltype(&C::getDefaultTransitionTag)); template static NoType & test(...); public: enum { value = sizeof(test(0)) == sizeof(YesType) }; }; template typename std::enable_if::value, void>::type automaticTransitionTag( std::string & transition_name) { transition_name = T::getDefaultTransitionTag(); } template typename std::enable_if::value, void>::type automaticTransitionTag( std::string & transition_name) { transition_name = ""; } //------------------------------------------------- template class HasAutomaticTransitionType { private: typedef char YesType[1]; typedef char NoType[2]; template static YesType & test(decltype(&C::getDefaultTransitionType)); template static NoType & test(...); public: enum { value = sizeof(test(0)) == sizeof(YesType) }; }; template typename std::enable_if::value, void>::type automaticTransitionType( std::string & transition_type) { transition_type = T::getDefaultTransitionType(); } template typename std::enable_if::value, void>::type automaticTransitionType( std::string & transition_type) { transition_type = demangledTypeName(); } // there are many ways to implement this, for instance adding static methods to the types typedef boost::mpl::list DEFAULT_TRANSITION_TYPES; //-------------------------------- template struct type_ { using type = T; }; //--------------------------------------------- template struct add_type_wrapper { using type = type_; }; template struct CheckType { CheckType(std::string * transitionTypeName) { this->transitionTypeName = transitionTypeName; } std::string * transitionTypeName; template void operator()(T) { //RCLCPP_INFO_STREAM(nh_->get_logger(),"comparing.."<< demangleSymbol() <<" vs " << demangleSymbol() ); if (std::is_base_of::value || std::is_same::value) { *(this->transitionTypeName) = demangledTypeName(); //RCLCPP_INFO(nh_->get_logger(),"YESS!"); } } }; template static std::string getTransitionType() { std::string output; CheckType op(&output); using boost::mpl::_1; using wrappedList = typename boost::mpl::transform::type; boost::mpl::for_each(op); return output; } // // BASE CASE // template // static void walkStateReactorsSources(SmaccStateReactorInfo &sbinfo, typelist) // { // auto sourceType = TypeInfo::getFromStdTypeInfo(typeid(T)); // auto evinfo = std::make_shared(sourceType); // EventLabel(evinfo->label); // sbinfo.sourceEventTypes.push_back(evinfo); // RCLCPP_INFO_STREAM(nh_->get_logger(),"event: " << sourceType->getFullName()); // RCLCPP_INFO_STREAM(nh_->get_logger(),"event parameters: " << sourceType->templateParameters.size()); // } // // RECURSIVE CASE // template // static void walkStateReactorsSources(SmaccStateReactorInfo &sbinfo, typelist) // { // auto sourceType = TypeInfo::getFromStdTypeInfo(typeid(TEvHead)); // auto evinfo = std::make_shared(sourceType); // EventLabel(evinfo->label); // sbinfo.sourceEventTypes.push_back(evinfo); // RCLCPP_INFO_STREAM(nh_->get_logger(),"event: " << sourceType->getFullName()); // RCLCPP_INFO_STREAM(nh_->get_logger(),"event parameters: " << sourceType->templateParameters.size()); // walkStateReactorsSources(sbinfo, typelist()); // } } // namespace introspection } // namespace smacc2 #include