ClassMemberInfo.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package RobotAPI::RobotUnit
17  * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18  * @date 2017
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 #pragma once
23 
25 
26 #include "ClassMemberInfoEntry.h"
27 
29 {
30  /**
31  * @brief
32  */
33  template <class CommonBaseT, class ClassT>
35  {
36  using ClassType = ClassT;
37  using CommonBaseType = CommonBaseT;
39  "The class has to inherit the common base class");
41  template <class T>
42  using EntryConfigurator =
44 
46 
47  /// @brief add a member variable of the current class
48  template <class MemberType>
50  const std::string& name);
51 
52  /// @brief add all variables of a base class of the current class
53  template <class BaseClassType>
54  void addBaseClass();
55 
56  /// @brief Get the name of the current class
57  static const std::string& GetClassName();
58  /// @brief Get all entries for member variables
60  static std::size_t GetNumberOfDataFields();
61  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, bool& out);
62  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Byte& out);
63  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Short& out);
64  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Int& out);
65  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Long& out);
66  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Float& out);
67  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Double& out);
68  static void GetDataFieldAs(const ClassType* ptr, std::size_t i, std::string& out);
69  static const std::type_info& GetDataFieldType(std::size_t i);
70  static std::vector<std::string> GetDataFieldNames();
71 
72  static std::map<std::string, VariantBasePtr> ToVariants(const IceUtil::Time& timestamp,
73  const CommonBaseT* ptr);
74 
75  private:
76  template <class T>
77  static auto
78  MakeConverter()
79  {
81  std::vector<std::function<void(const ClassType*, T&)>> functions;
82 
83  for (std::size_t idxEntr = 0; idxEntr < GetEntries().size(); ++idxEntr)
84  {
85  for (std::size_t idxField = 0;
86  idxField < GetEntries().at(idxEntr).getNumberOfFields();
87  ++idxField)
88  {
89  functions.emplace_back(
90  [idxEntr, idxField](const ClassType* classptr, T& out)
91  {
92  const Entry& e = GetEntries().at(idxEntr);
93  e.getDataFieldAs(idxField, classptr, out);
94  });
95  }
96  }
97  ARMARX_CHECK_EQUAL(functions.size(), GetNumberOfDataFields());
98  return functions;
99  }
100 
101  private:
102  KeyValueVector<std::string, Entry> entries;
103  std::set<std::string> addedBases;
104  };
105 } // namespace armarx::introspection
106 
107 //implementation
108 namespace armarx::introspection
109 {
110  template <class CommonBaseT, class ClassT>
111  template <class MemberType>
112  typename ClassMemberInfo<CommonBaseT, ClassT>::template EntryConfigurator<ClassT>
114  const std::string& name)
115  {
116  ARMARX_TRACE;
117  ARMARX_CHECK_EQUAL(entries.count(name), 0) << name;
118  entries.add(name, Entry(name, ptr));
119  return entries.at(name);
120  }
121 
122  template <class CommonBaseT, class ClassT>
123  template <class BaseClassType>
124  void
126  {
127  ARMARX_TRACE;
129  {
130  return;
131  }
133  "The base class has to inherit the common base class");
135  "The base class has to be a base class");
137  "The base class has must not be the class");
138 
139  std::set<std::string> basesAddedInCall;
141  {
142  return;
143  }
145  {
146  if (!addedBases.count(e.getClassName()))
147  {
148  ARMARX_CHECK_EXPRESSION(!entries.count(e.getMemberName()))
149  << "Adding the base class '" << GetTypeString<BaseClassType>()
150  << "' adds an entry for the member '" << e.getMemberName()
151  << "' which already was added by class '"
152  << entries.at(e.getMemberName()).getClassName() << "'";
153  basesAddedInCall.emplace(e.getClassName());
154  entries.add(e.getMemberName(), e);
155  }
156  }
157  addedBases.insert(basesAddedInCall.begin(), basesAddedInCall.end());
158  }
159 
160  template <class CommonBaseT, class ClassT>
161  std::vector<std::string>
163  {
164  ARMARX_TRACE;
165  std::vector<std::string> dataFieldNames;
166  dataFieldNames.reserve(GetNumberOfDataFields());
167  for (const Entry& e : GetEntries().values())
168  {
169  for (std::size_t i = 0; i < e.getNumberOfFields(); ++i)
170  {
171  dataFieldNames.emplace_back(e.getFieldName(i));
172  }
173  }
174  ARMARX_CHECK_EQUAL(GetNumberOfDataFields(), dataFieldNames.size());
175  return dataFieldNames;
176  }
177 
178  template <class CommonBaseT, class ClassT>
179  std::map<std::string, VariantBasePtr>
181  const CommonBaseT* ptr)
182  {
183  ARMARX_TRACE;
184  std::map<std::string, VariantBasePtr> result;
185  for (const auto& e : GetEntries().values())
186  {
187  auto newMap = e.toVariants(timestamp, ptr);
188  for (auto& elem : newMap)
189  {
190  if (result.count(elem.first))
191  {
192  throw std::invalid_argument{
193  "mergeMaps: newMap would override values from oldMap"};
194  }
195  }
196  for (auto& elem : newMap)
197  {
198  result[elem.first] = elem.second;
199  }
200  //mergeMaps(result, , MergeMapsMode::OverrideNoValues);
201  }
202  return result;
203  }
204 
205  template <class CommonBaseT, class ClassT>
208  {
209  static const ClassMemberInfo<CommonBaseT, ClassT> i = ClassT::GetClassMemberInfo();
210  return i;
211  }
212 
213  template <class CommonBaseT, class ClassT>
214  const std::string&
216  {
217  return GetTypeString<ClassType>();
218  }
219 
220  template <class CommonBaseT, class ClassT>
223  {
224  return GetInstance().entries;
225  }
226 
227  template <class CommonBaseT, class ClassT>
228  std::size_t
230  {
231  ARMARX_TRACE;
232  static const std::size_t numberOfDataFields = []
233  {
234  std::size_t n = 0;
235  for (const Entry& e : GetEntries().values())
236  {
237  n += e.getNumberOfFields();
238  }
239  return n;
240  }();
241  return numberOfDataFields;
242  }
243 
244  template <class CommonBaseT, class ClassT>
245  void
247  std::size_t i,
248  bool& out)
249  {
250  ARMARX_TRACE;
251  static const auto convert = MakeConverter<bool>();
252  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
253  convert.at(i)(ptr, out);
254  }
255 
256  template <class CommonBaseT, class ClassT>
257  void
259  std::size_t i,
260  Ice::Byte& out)
261  {
262  ARMARX_TRACE;
263  static const auto convert = MakeConverter<Ice::Byte>();
264  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
265  convert.at(i)(ptr, out);
266  }
267 
268  template <class CommonBaseT, class ClassT>
269  void
271  std::size_t i,
272  Ice::Short& out)
273  {
274  ARMARX_TRACE;
275  static const auto convert = MakeConverter<Ice::Short>();
276  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
277  convert.at(i)(ptr, out);
278  }
279 
280  template <class CommonBaseT, class ClassT>
281  void
283  std::size_t i,
284  Ice::Int& out)
285  {
286  ARMARX_TRACE;
287  static const auto convert = MakeConverter<Ice::Int>();
288  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
289  convert.at(i)(ptr, out);
290  }
291 
292  template <class CommonBaseT, class ClassT>
293  void
295  std::size_t i,
296  Ice::Long& out)
297  {
298  ARMARX_TRACE;
299  static const auto convert = MakeConverter<Ice::Long>();
300  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
301  convert.at(i)(ptr, out);
302  }
303 
304  template <class CommonBaseT, class ClassT>
305  void
307  std::size_t i,
308  Ice::Float& out)
309  {
310  ARMARX_TRACE;
311  static const auto convert = MakeConverter<Ice::Float>();
312  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
313  convert.at(i)(ptr, out);
314  }
315 
316  template <class CommonBaseT, class ClassT>
317  void
319  std::size_t i,
320  Ice::Double& out)
321  {
322  ARMARX_TRACE;
323  static const auto convert = MakeConverter<Ice::Double>();
324  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
325  convert.at(i)(ptr, out);
326  }
327 
328  template <class CommonBaseT, class ClassT>
329  void
331  std::size_t i,
332  std::string& out)
333  {
334  ARMARX_TRACE;
335  static const auto convert = MakeConverter<std::string>();
336  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
337  convert.at(i)(ptr, out);
338  }
339 
340  template <class CommonBaseT, class ClassT>
341  const std::type_info&
343  {
344  ARMARX_TRACE;
345  static const auto convert = []
346  {
347  std::vector<const std::type_info*> data;
348 
349  for (std::size_t idxEntr = 0; idxEntr < GetEntries().size(); ++idxEntr)
350  {
351  const Entry& e = GetEntries().at(idxEntr);
352  for (std::size_t idxField = 0;
353  idxField < GetEntries().at(idxEntr).getNumberOfFields();
354  ++idxField)
355  {
356  data.emplace_back(&e.getFieldTypeId(idxField));
357  }
358  }
359  ARMARX_CHECK_EQUAL(data.size(), GetNumberOfDataFields());
360  return data;
361  }();
362  ARMARX_CHECK_LESS(i, GetNumberOfDataFields());
363  return *convert.at(i);
364  }
365 } // namespace armarx::introspection
armarx::introspection::ClassMemberInfo::GetNumberOfDataFields
static std::size_t GetNumberOfDataFields()
Definition: ClassMemberInfo.h:229
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:918
armarx::introspection::ClassMemberInfo::GetClassName
static const std::string & GetClassName()
Get the name of the current class.
Definition: ClassMemberInfo.h:215
armarx::introspection::ClassMemberInfo::GetDataFieldAs
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, bool &out)
Definition: ClassMemberInfo.h:246
ProsthesisInterface.values
values
Definition: ProsthesisInterface.py:190
ARMARX_CHECK_LESS
#define ARMARX_CHECK_LESS(lhs, rhs)
This macro evaluates whether lhs is less (<) than rhs and if it turns out to be false it will throw a...
Definition: ExpressionException.h:102
armarx::introspection::ClassMemberInfo::addBaseClass
void addBaseClass()
add all variables of a base class of the current class
Definition: ClassMemberInfo.h:125
armarx::introspection::ClassMemberInfo
Definition: ClassMemberInfo.h:34
armarx::convert
armem::articulated_object::ArticulatedObject convert(const VirtualRobot::Robot &obj, const armem::Time &timestamp)
Definition: ArticulatedObjectLocalizerDynamicSimulation.cpp:194
armarx::introspection::ClassMemberInfo::ToVariants
static std::map< std::string, VariantBasePtr > ToVariants(const IceUtil::Time &timestamp, const CommonBaseT *ptr)
Definition: ClassMemberInfo.h:180
KeyValueVector.h
armarx::introspection::ClassMemberInfoEntry::getDataFieldAs
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, bool &out) const
Definition: ClassMemberInfoEntry.h:106
armarx::VariantType::Double
const VariantTypeId Double
Definition: Variant.h:919
armarx::introspection::ClassMemberInfoEntry
Definition: ClassMemberInfoEntry.h:35
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::introspection::ClassMemberInfoEntry::getFieldTypeId
const std::type_info & getFieldTypeId(std::size_t i) const
Definition: ClassMemberInfoEntry.h:170
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::introspection::ClassMemberInfo::GetEntries
static const KeyValueVector< std::string, Entry > & GetEntries()
Get all entries for member variables.
Definition: ClassMemberInfo.h:222
armarx::introspection::ClassMemberInfo::CommonBaseType
CommonBaseT CommonBaseType
Definition: ClassMemberInfo.h:37
armarx::introspection::ClassMemberInfo::addMemberVariable
EntryConfigurator< ClassType > addMemberVariable(MemberType ClassType::*ptr, const std::string &name)
add a member variable of the current class
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
armarx::introspection::ClassMemberInfoEntryConfigurator
Definition: ClassMemberInfoEntry.h:32
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::introspection::ClassMemberInfo::ClassType
ClassT ClassType
Definition: ClassMemberInfo.h:36
armarx::KeyValueVector
This class is pretty much similar to a map.
Definition: KeyValueVector.h:43
ClassMemberInfoEntry.h
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::introspection::ClassMemberInfo::GetInstance
static const ClassMemberInfo< CommonBaseT, ClassT > & GetInstance()
Definition: ClassMemberInfo.h:207
armarx::introspection::ClassMemberInfo::GetDataFieldNames
static std::vector< std::string > GetDataFieldNames()
Definition: ClassMemberInfo.h:162
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx::introspection::ClassMemberInfo::GetDataFieldType
static const std::type_info & GetDataFieldType(std::size_t i)
Definition: ClassMemberInfo.h:342
armarx::introspection
Definition: ClassMemberInfo.h:28