ClassMemberInfoEntry.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
24#include "DataFieldsInfo.h"
25
27{
28
29 template <class CommonBaseT, class ClassT>
30 struct ClassMemberInfo;
31 template <class CommonBaseT, class ClassT>
33
34 template <class CommonBaseT>
36 {
37 public:
38 using CommonBaseType = CommonBaseT;
39
44
45 template <class ClassType, class MemberType>
46 ClassMemberInfoEntry(const std::string& memberName, MemberType ClassType::*ptr) :
47 className{GetTypeString<ClassType>()},
48 memberName{memberName},
49 memberTypeName{GetTypeString<MemberType>()},
50 numberOfFields{DataFieldsInfo<MemberType>::GetNumberOfFields()},
51 fieldToType{MakeFieldToTypeFunctors<ClassType>(numberOfFields, ptr)},
52 toVariants_{MakeToVariantsFunctor<ClassType>(ptr)}
53 {
54 ARMARX_CHECK_NOT_EQUAL(0, numberOfFields);
55 //field names
56 {
57 fieldNames.reserve(numberOfFields);
58 if (numberOfFields == 1)
59 {
60 fieldNames.emplace_back(memberName);
61 }
62 else
63 {
65 {
66 fieldNames.emplace_back(memberName + "." + std::move(name));
67 }
68 }
69 }
70 }
71
72 //general
73 const std::string&
75 {
76 return className;
77 }
78
79 const std::string&
81 {
82 return memberName;
83 }
84
85 const std::string&
87 {
88 return memberTypeName;
89 }
90
91 //fields
92 std::size_t
94 {
95 return numberOfFields;
96 }
97
98 const std::string&
99 getFieldName(std::size_t i) const
100 {
101 ARMARX_CHECK_LESS(i, numberOfFields);
102 return fieldNames.at(i);
103 }
104
105 void
106 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, bool& out) const
107 {
109 ARMARX_CHECK_LESS(i, numberOfFields);
110 return fieldToType.at(i).toBool(ptr, out);
111 }
112
113 void
114 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Byte& out) const
115 {
117 ARMARX_CHECK_LESS(i, numberOfFields);
118 return fieldToType.at(i).toByte(ptr, out);
119 }
120
121 void
122 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Short& out) const
123 {
125 ARMARX_CHECK_LESS(i, numberOfFields);
126 return fieldToType.at(i).toShort(ptr, out);
127 }
128
129 void
130 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Int& out) const
131 {
133 ARMARX_CHECK_LESS(i, numberOfFields);
134 return fieldToType.at(i).toInt(ptr, out);
135 }
136
137 void
138 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Long& out) const
139 {
141 ARMARX_CHECK_LESS(i, numberOfFields);
142 return fieldToType.at(i).toLong(ptr, out);
143 }
144
145 void
146 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Float& out) const
147 {
149 ARMARX_CHECK_LESS(i, numberOfFields);
150 return fieldToType.at(i).toFloat(ptr, out);
151 }
152
153 void
154 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, Ice::Double& out) const
155 {
157 ARMARX_CHECK_LESS(i, numberOfFields);
158 return fieldToType.at(i).toDouble(ptr, out);
159 }
160
161 void
162 getDataFieldAs(std::size_t i, const CommonBaseType* ptr, std::string& out) const
163 {
165 ARMARX_CHECK_LESS(i, numberOfFields);
166 return fieldToType.at(i).toString(ptr, out);
167 }
168
169 const std::type_info&
170 getFieldTypeId(std::size_t i) const
171 {
172 ARMARX_CHECK_LESS(i, numberOfFields);
173 return *fieldToType.at(i).typeId;
174 }
175
176 //variants
177 std::map<std::string, VariantBasePtr>
178 toVariants(const IceUtil::Time& timestamp, const CommonBaseType* ptr) const
179 {
180 return toVariants_(this, timestamp, ptr);
181 }
182
183 private:
184 using ToVariantsFunctorType =
185 std::function<std::map<std::string, VariantBasePtr>(const ClassMemberInfoEntry* thisptr,
186 const IceUtil::Time&,
187 const CommonBaseType*)>;
188
189 struct FieldToType
190 {
191 template <class T>
192 using FieldToFunctorType = std::function<void(const CommonBaseType*, T&)>;
193 FieldToFunctorType<bool> toBool;
194 FieldToFunctorType<Ice::Byte> toByte;
195 FieldToFunctorType<Ice::Short> toShort;
196 FieldToFunctorType<Ice::Int> toInt;
197 FieldToFunctorType<Ice::Long> toLong;
198 FieldToFunctorType<Ice::Float> toFloat;
199 FieldToFunctorType<Ice::Double> toDouble;
200 FieldToFunctorType<std::string> toString;
201 const std::type_info* typeId;
202 };
203
204 template <class ClassType, class MemberType, class MemberPtrClassType>
205 static std::vector<FieldToType>
206 MakeFieldToTypeFunctors(std::size_t numberOfFields, MemberType MemberPtrClassType::*ptr)
207 {
208 std::vector<FieldToType> result;
209 result.reserve(numberOfFields);
210 for (std::size_t i = 0; i < numberOfFields; ++i)
211 {
212 result.emplace_back();
213 auto& fieldData = result.back();
214
215#define make_getter(Type) \
216 [i, ptr](const CommonBaseType* ptrBase, Type& out) \
217 { \
218 const ClassType* cptr = dynamic_cast<const ClassType*>(ptrBase); \
219 ARMARX_CHECK_NOT_NULL(cptr); \
220 DataFieldsInfo<MemberType>::GetDataFieldAs(i, cptr->*ptr, out); \
221 }
222 fieldData.toBool = make_getter(bool);
223 fieldData.toByte = make_getter(Ice::Byte);
224 fieldData.toShort = make_getter(Ice::Short);
225 fieldData.toInt = make_getter(Ice::Int);
226 fieldData.toLong = make_getter(Ice::Long);
227 fieldData.toFloat = make_getter(Ice::Float);
228 fieldData.toDouble = make_getter(Ice::Double);
229 fieldData.toString = make_getter(std::string);
230#undef make_getter
231 fieldData.typeId = &DataFieldsInfo<MemberType>::GetDataFieldType(i);
232 }
233 return result;
234 }
235
236 template <class ClassType, class MemberType, class MemberPtrClassType>
237 static ToVariantsFunctorType
238 MakeToVariantsFunctor(MemberType MemberPtrClassType::*ptr)
239 {
240 return [ptr](const ClassMemberInfoEntry* thisptr,
241 const IceUtil::Time& timestamp,
242 const CommonBaseType* ptrBase)
243 {
244 const ClassType* cptr = dynamic_cast<const ClassType*>(ptrBase);
246 return DataFieldsInfo<MemberType>::ToVariants(cptr->*ptr,
247 thisptr->getMemberName(),
248 timestamp,
249 thisptr->variantReportFrame(),
250 thisptr->variantReportAgent());
251 };
252 }
253
254 template <class BaseType, class ClassT>
255 friend class ClassMemberInfo;
256 template <class BaseType, class ClassT>
258
259 const std::string className;
260 const std::string memberName;
261 const std::string memberTypeName;
262 //elementar subparts
263 const std::size_t numberOfFields;
264 const std::vector<FieldToType> fieldToType;
265 std::vector<std::string> fieldNames;
266 //variants
267 ToVariantsFunctorType toVariants_;
268 bool setVariantReportFrame_{false};
269 std::function<std::string()> variantReportFrame{[] { return ""; }};
270 std::function<std::string()> variantReportAgent{[] { return ""; }};
271 };
272
273 template <class CommonBaseT, class ClassT>
274 struct ClassMemberInfoEntryConfigurator
275 {
276 using ClassType = ClassT;
277 using CommonBaseType = CommonBaseT;
279
280 ClassMemberInfoEntryConfigurator&
281 setFieldNames(std::vector<std::string> fieldNames)
282 {
283 ARMARX_CHECK_EQUAL(fieldNames.size(), e.numberOfFields);
284 e.fieldNames = std::move(fieldNames);
285 return *this;
286 }
287
289 setVariantReportFrame(const std::string& agent, const std::string& frame)
290 {
291 e.setVariantReportFrame_ = true;
292 e.variantReportFrame = [frame] { return frame; };
293 e.variantReportAgent = [agent] { return agent; };
294 return *this;
295 }
296
298 setVariantReportFrame(const std::string& agent, std::function<std::string()> frame)
299 {
300 e.setVariantReportFrame_ = true;
301 e.variantReportFrame = std::move(frame);
302 e.variantReportAgent = [agent] { return agent; };
303 return *this;
304 }
305
307 setVariantReportFrame(std::function<std::string()> agent, const std::string& frame)
308 {
309 e.setVariantReportFrame_ = true;
310 e.variantReportFrame = [frame] { return frame; };
311 e.variantReportAgent = std::move(agent);
312 return *this;
313 }
314
316 setVariantReportFrame(std::function<std::string()> agent,
317 std::function<std::string()> frame)
318 {
319 e.setVariantReportFrame_ = true;
320 e.variantReportFrame = std::move(frame);
321 e.variantReportAgent = std::move(agent);
322 return *this;
323 }
324
327 std::function<std::map<std::string, VariantBasePtr>(const IceUtil::Time&,
328 const ClassType*)> f)
329 {
330 e.toVariants_ = [f](const ClassMemberInfoEntry<CommonBaseType>* thisptr,
331 const IceUtil::Time& timestamp,
332 const CommonBaseType* ptrBase)
333 {
334 const ClassType* ptr = dynamic_cast<const ClassType*>(ptrBase);
336 return f(timestamp, ptr);
337 };
338 return *this;
339 }
340
341 private:
343
345 {
346 }
347
348 Entry& e;
349 };
350} // namespace armarx::introspection
std::string timestamp()
#define make_getter(Type)
int toByte(float f)
#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...
#define ARMARX_CHECK_NOT_EQUAL(lhs, rhs)
This macro evaluates whether lhs is inequal (!=) rhs and if it turns out to be false it will throw an...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#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...
std::string GetTypeString(const std::type_info &tinf, bool withoutNamespaceSpecifier=false)
int toInt(const std::string &input)
float toFloat(const std::string &input)
Converts a string to float and uses always dot as seperator.
ClassMemberInfoEntryConfigurator & setVariantReportFrame(std::function< std::string()> agent, std::function< std::string()> frame)
ClassMemberInfoEntryConfigurator & setVariantReportFrame(const std::string &agent, const std::string &frame)
ClassMemberInfoEntryConfigurator & setFieldNames(std::vector< std::string > fieldNames)
ClassMemberInfoEntryConfigurator & setVariantReportFunction(std::function< std::map< std::string, VariantBasePtr >(const IceUtil::Time &, const ClassType *)> f)
ClassMemberInfoEntryConfigurator & setVariantReportFrame(std::function< std::string()> agent, const std::string &frame)
ClassMemberInfoEntryConfigurator & setVariantReportFrame(const std::string &agent, std::function< std::string()> frame)
ClassMemberInfoEntry & operator=(const ClassMemberInfoEntry &)=default
ClassMemberInfoEntry & operator=(ClassMemberInfoEntry &&)=default
const std::string & getFieldName(std::size_t i) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Short &out) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Int &out) const
ClassMemberInfoEntry(const std::string &memberName, MemberType ClassType::*ptr)
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, bool &out) const
ClassMemberInfoEntry(ClassMemberInfoEntry &&)=default
std::map< std::string, VariantBasePtr > toVariants(const IceUtil::Time &timestamp, const CommonBaseType *ptr) const
const std::type_info & getFieldTypeId(std::size_t i) const
ClassMemberInfoEntry(const ClassMemberInfoEntry &)=default
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Float &out) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Byte &out) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, std::string &out) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Double &out) const
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, Ice::Long &out) const