source: finroc_plugins_composite_ports/internal/tInterfaceTypeInfo.cpp @ 28:0d9e9fd957de

Last change on this file since 28:0d9e9fd957de was 25:677b14542f29, checked in by Max Reichardt <mreichardt@…>, 22 months ago

Makes partial port composite interfaces always interconnectible with full interfaces (bugfix)

File size: 7.1 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/composite_ports/internal/tInterfaceTypeInfo.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2020-02-07
27 *
28 */
29//----------------------------------------------------------------------
30#include "plugins/composite_ports/internal/tInterfaceTypeInfo.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include "core/port/tPortFactory.h"
36#include "core/tFrameworkElementTags.h"
37
38//----------------------------------------------------------------------
39// Internal includes with ""
40//----------------------------------------------------------------------
41#include "plugins/composite_ports/interface_types.h"
42
43//----------------------------------------------------------------------
44// Debugging
45//----------------------------------------------------------------------
46#include <cassert>
47
48//----------------------------------------------------------------------
49// Namespace usage
50//----------------------------------------------------------------------
51
52//----------------------------------------------------------------------
53// Namespace declaration
54//----------------------------------------------------------------------
55namespace finroc
56{
57namespace composite_ports
58{
59namespace internal
60{
61
62//----------------------------------------------------------------------
63// Forward declarations / typedefs / enums
64//----------------------------------------------------------------------
65
66//----------------------------------------------------------------------
67// Const values
68//----------------------------------------------------------------------
69
70//----------------------------------------------------------------------
71// Implementation
72//----------------------------------------------------------------------
73
74namespace
75{
76
77core::tEdgeAggregator* GetAggregator(core::tFrameworkElement& element)
78{
79  return static_cast<core::tEdgeAggregator*>(element.GetFlag(core::tFrameworkElementFlag::EDGE_AGGREGATOR) ? &element : element.GetParentWithFlags(core::tFrameworkElementFlag::EDGE_AGGREGATOR));
80}
81
82}
83
84class tInterfaceFactory : public core::tPortFactory
85{
86  virtual core::tAbstractPort& CreatePortImplementation(const std::string& port_name, core::tFrameworkElement& parent, const rrlib::rtti::tType& type, core::tFrameworkElement::tFlags flags) override
87  {
88    core::tEdgeAggregator* parent_interface = GetAggregator(parent);
89    if ((!parent_interface) || (!IsComponent(parent_interface->GetParent())) || (!parent_interface->GetFlag(core::tFrameworkElementFlag::INTERFACE)))
90    {
91      throw std::runtime_error("Port composite interfaces can only be created for components");
92    }
93
94    auto& interface_type_info = static_cast<const tInterfaceTypeInfo&>(type.SharedTypeInfo());
95    tInterfaceTypeInfo::tCreateFunction create_function = interface_type_info.CreateFunction();
96    if (!create_function)
97    {
98      throw std::runtime_error("No create action registered for interface type (typically done in rtti.cpp)");
99    }
100
101    tInterfaceBase::tScopedExtraConstructorParameters extra_contructor_parameters;
102    if (interface_type_info.GetFullType() != type)
103    {
104      extra_contructor_parameters = tInterfaceBase::tScopedExtraConstructorParameters::Get();
105      extra_contructor_parameters->partial_interface = true;
106    }
107
108    tInterfaceBase result = (*create_function)(port_name, static_cast<core::tPortGroup*>(parent_interface));
109    if (flags.Get(core::tFrameworkElementFlag::FINSTRUCTED))
110    {
111      result.Backend()->SetFlag(core::tFrameworkElementFlag::FINSTRUCTED);
112    }
113    return *result.GetWrapped();
114  }
115
116  virtual bool HandlesDataType(const rrlib::rtti::tType& type) override
117  {
118    return IsInterfaceType(type);
119  }
120};
121
122tInterfaceFactory default_port_composite_interface_factory;
123
124bool IsComponent(const core::tFrameworkElement* element)
125{
126  return element && (core::tFrameworkElementTags::IsTagged(*element, "module") || core::tFrameworkElementTags::IsTagged(*element, "group"));
127}
128
129tInterfaceTypeInfo::tInterfaceTypeInfo(const rrlib::rtti::detail::tTypeInfo* type_info, tCreateFunction create_function, int auto_registered, bool create_partial_type, const std::type_info& partial_type_info) :
130  tSharedInfo(type_info, GenerateName(type_info->std_type_info.name()), nullptr, 0),
131  create_function(create_function)
132{
133  this->type_info_full = type_info;
134  if (create_partial_type)
135  {
136    this->type_info_partial = new rrlib::rtti::detail::tTypeInfo(partial_type_info, type_info->type_traits | (rrlib::rtti::trait_flags::cHAS_UNDERLYING_TYPE | rrlib::rtti::trait_flags::cIS_CAST_TO_UNDERLYING_TYPE_IMPLICIT | rrlib::rtti::trait_flags::cIS_REINTERPRET_CAST_FROM_UNDERLYING_TYPE_VALID | rrlib::rtti::trait_flags::cIS_CAST_FROM_UNDERLYING_TYPE_IMPLICIT), type_info, type_info->element_type, nullptr, type_info->size);
137    auto partial_shared_info = new tInterfaceTypeInfo(this->type_info_partial, create_function, rrlib::util::tManagedConstCharPointer((rrlib::rtti::tType(type_info).GetName() + " (partial)").c_str(), true));
138    this->type_info_partial->shared_info = partial_shared_info;
139    partial_shared_info->type_info_full = type_info;
140    partial_shared_info->type_info_partial = this->type_info_partial;
141    assert(GetPartialType().GetHandle() == GetFullType().GetHandle() + 1);
142  }
143}
144
145tInterfaceTypeInfo::~tInterfaceTypeInfo()
146{
147  if (this->type_info_partial && this->type_info_full->shared_info == this)
148  {
149    tInterfaceTypeInfo* shared_info_partial = static_cast<tInterfaceTypeInfo*>(this->type_info_partial->shared_info);
150    delete shared_info_partial;
151    delete this->type_info_partial;
152  }
153}
154
155rrlib::util::tManagedConstCharPointer tInterfaceTypeInfo::GenerateName(const char* rtti_name)
156{
157  auto from_rrlib_rtti = rrlib::rtti::detail::tTypeInfo::GetDefaultTypeNameFromRttiName(rtti_name);
158  std::string rrlib_rtti_string(from_rrlib_rtti.Get());
159  auto index = rrlib_rtti_string.find("<");
160  if (index == std::string::npos)
161  {
162    return from_rrlib_rtti;
163  }
164  rrlib_rtti_string = rrlib_rtti_string.substr(0, index);
165  return rrlib::util::tManagedConstCharPointer(rrlib_rtti_string.c_str(), true);
166}
167
168//----------------------------------------------------------------------
169// End of namespace declaration
170//----------------------------------------------------------------------
171}
172}
173}
Note: See TracBrowser for help on using the repository browser.