-
Notifications
You must be signed in to change notification settings - Fork 133
/
Copy pathmsg__struct.hpp.em
384 lines (360 loc) · 14.2 KB
/
msg__struct.hpp.em
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
@# Included from rosidl_generator_cpp/resource/idl__struct.hpp.em
@{
from rosidl_generator_cpp import create_init_alloc_and_member_lists
from rosidl_generator_cpp import escape_string
from rosidl_generator_cpp import escape_wstring
from rosidl_generator_cpp import msg_type_to_cpp
from rosidl_generator_cpp import MSG_TYPE_TO_CPP
from rosidl_parser.definition import AbstractNestedType
from rosidl_parser.definition import AbstractString
from rosidl_parser.definition import AbstractWString
from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX
from rosidl_parser.definition import ACTION_GOAL_SUFFIX
from rosidl_parser.definition import ACTION_RESULT_SUFFIX
from rosidl_parser.definition import BasicType
from rosidl_parser.definition import BOOLEAN_TYPE
from rosidl_parser.definition import CHARACTER_TYPES
from rosidl_parser.definition import EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME
from rosidl_parser.definition import INTEGER_TYPES
from rosidl_parser.definition import NamespacedType
from rosidl_parser.definition import OCTET_TYPE
from rosidl_parser.definition import UNSIGNED_INTEGER_TYPES
message_typename = '::'.join(message.structure.namespaced_type.namespaced_name())
# Common Windows macros that may interfere with user defined constants
msvc_common_macros = ('DELETE', 'ERROR', 'NO_ERROR')
}@
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Collect necessary include directives for all members
@{
from collections import OrderedDict
from rosidl_cmake import convert_camel_case_to_lower_case_underscore
includes = OrderedDict()
for member in message.structure.members:
type_ = member.type
if isinstance(type_, AbstractNestedType):
type_ = type_.value_type
if isinstance(type_, NamespacedType):
if (
type_.name.endswith(ACTION_GOAL_SUFFIX) or
type_.name.endswith(ACTION_RESULT_SUFFIX) or
type_.name.endswith(ACTION_FEEDBACK_SUFFIX)
):
typename = type_.name.rsplit('_', 1)[0]
else:
typename = type_.name
member_names = includes.setdefault(
'/'.join((type_.namespaces + ['detail', convert_camel_case_to_lower_case_underscore(typename)])) + '__struct.hpp', [])
member_names.append(member.name)
}@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@[if includes]@
// Include directives for member types
@[ for header_file, member_names in includes.items()]@
@[ for member_name in member_names]@
// Member '@(member_name)'
@[ end for]@
@[ if header_file in include_directives]@
// already included above
// @
@[ else]@
@{include_directives.add(header_file)}@
@[ end if]@
#include "@(header_file)"
@[ end for]@
@[end if]@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@{
deprecated_macro_name = \
'__'.join(['DEPRECATED', package_name] + list(interface_path.parents[0].parts) + [message.structure.namespaced_type.name])
}@
#ifndef _WIN32
# define @(deprecated_macro_name) __attribute__((deprecated))
#else
# define @(deprecated_macro_name) __declspec(deprecated)
#endif
@[for ns in message.structure.namespaced_type.namespaces]@
namespace @(ns)
{
@[end for]@
// message struct
template<class ContainerAllocator>
struct @(message.structure.namespaced_type.name)_
{
using Type = @(message.structure.namespaced_type.name)_<ContainerAllocator>;
@{
# The creation of the constructors for messages is a bit complicated. The goal
# is to have a constructor where the user can control how the fields of the
# message get initialized via the _init parameter to the constructor. See
# http://design.ros2.org/articles/generated_interfaces_cpp.html#constructors
# for a detailed explanation of the different _init parameters.
init_list, alloc_list, member_list = create_init_alloc_and_member_lists(message)
def generate_default_string(membset):
from rosidl_generator_cpp import msg_type_only_to_cpp
from rosidl_generator_cpp import msg_type_to_cpp
strlist = []
for member in membset.members:
if member.default_value is not None:
if member.num_prealloc > 0:
strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
if isinstance(member.default_value, list):
if all(v == member.default_value[0] for v in member.default_value):
# Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
# For more info, see https://github.com/ros2/rosidl/issues/309
# TODO(jacobperron): Investigate reason for build warnings on Windows
# TODO(jacobperron): Write test case for this path of execution
strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.default_value[0]))
else:
for index, val in enumerate(member.default_value):
strlist.append('this->%s[%d] = %s;' % (member.name, index, val))
else:
strlist.append('this->%s = %s;' % (member.name, member.default_value))
return strlist
def generate_zero_string(membset, fill_args):
from rosidl_generator_cpp import msg_type_only_to_cpp
from rosidl_generator_cpp import msg_type_to_cpp
strlist = []
for member in membset.members:
if isinstance(member.zero_value, list):
if member.num_prealloc > 0:
strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
if member.zero_need_array_override:
strlist.append('this->%s.fill(%s{%s});' % (member.name, msg_type_only_to_cpp(member.type), fill_args))
else:
# Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
# For more info, see https://github.com/ros2/rosidl/issues/309
# TODO(jacobperron): Investigate reason for build warnings on Windows
strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.zero_value[0]))
else:
strlist.append('this->%s = %s;' % (member.name, member.zero_value))
return strlist
}@
explicit @(message.structure.namespaced_type.name)_(rosidl_runtime_cpp::MessageInitialization _init = rosidl_runtime_cpp::MessageInitialization::ALL)
@[if init_list]@
: @(',\n '.join(init_list))
@[end if]@
{
@[if not member_list]@
(void)_init;
@[end if]@
@{
default_value_members = [m for m in member_list if m.members[0].default_value]
zero_value_members = [m for m in member_list if m.members[0].zero_value]
non_defaulted_zero_initialized_members = [
m for m in member_list
if (m.members[0].zero_value or m.members[0].zero_need_array_override) and not m.members[0].default_value
]
}@
@[if default_value_members]@
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
{
@[ for membset in default_value_members]@
@[ for line in generate_default_string(membset)]@
@(line)
@[ end for]@
@[ end for]@
@[ if zero_value_members]@
} else if (rosidl_runtime_cpp::MessageInitialization::ZERO == _init) {
@[ for membset in zero_value_members]@
@[ for line in generate_zero_string(membset, '_init')]@
@(line)
@[ end for]@
@[ end for]@
@[ end if]@
}
@[ end if]@
@[ if non_defaulted_zero_initialized_members]@
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::ZERO == _init)
{
@[ for membset in non_defaulted_zero_initialized_members]@
@[ for line in generate_zero_string(membset, '_init')]@
@[ if line]@
@(line)
@[ end if]@
@[ end for]@
@[ end for]@
}
@[end if]@
}
explicit @(message.structure.namespaced_type.name)_(const ContainerAllocator & _alloc, rosidl_runtime_cpp::MessageInitialization _init = rosidl_runtime_cpp::MessageInitialization::ALL)
@[if alloc_list]@
: @(',\n '.join(alloc_list))
@[end if]@
{
@[if not member_list]@
(void)_init;
@[end if]@
@[if not alloc_list]@
(void)_alloc;
@[end if]@
@[if default_value_members]@
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
{
@[ for membset in default_value_members]@
@[ for line in generate_default_string(membset)]@
@(line)
@[ end for]@
@[ end for]@
@[ if zero_value_members]@
} else if (rosidl_runtime_cpp::MessageInitialization::ZERO == _init) {
@[ for membset in zero_value_members]@
@[ for line in generate_zero_string(membset, '_alloc, _init')]@
@(line)
@[ end for]@
@[ end for]@
@[ end if]@
}
@[end if]@
@[if non_defaulted_zero_initialized_members]@
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::ZERO == _init)
{
@[ for membset in non_defaulted_zero_initialized_members]@
@[ for line in generate_zero_string(membset, '_alloc, _init')]@
@(line)
@[ end for]@
@[ end for]@
}
@[end if]@
}
// field types and members
@[for member in message.structure.members]@
using _@(member.name)_type =
@(msg_type_to_cpp(member.type));
_@(member.name)_type @(member.name);
@[end for]@
@[if len(message.structure.members) != 1 or message.structure.members[0].name != EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
// setters for named parameter idiom
@[ for member in message.structure.members]@
Type & set__@(member.name)(
const @(msg_type_to_cpp(member.type)) & _arg)
{
this->@(member.name) = _arg;
return *this;
}
@[ end for]@
@[end if]@
// constant declarations
@[for constant in message.constants]@
@[ if constant.name in msvc_common_macros]@
// guard against '@(constant.name)' being predefined by MSVC by temporarily undefining it
#if defined(_WIN32)
# if defined(@(constant.name))
# pragma push_macro("@(constant.name)")
# undef @(constant.name)
# endif
#endif
@[ end if]@
@[ if isinstance(constant.type, AbstractString)]@
static const @(MSG_TYPE_TO_CPP['string']) @(constant.name);
@[ elif isinstance(constant.type, AbstractWString)]@
static const @(MSG_TYPE_TO_CPP['wstring']) @(constant.name);
@[ else]@
static constexpr @(MSG_TYPE_TO_CPP[constant.type.typename]) @(constant.name) =
@[ if isinstance(constant.type, BasicType) and constant.type.typename in (*INTEGER_TYPES, *CHARACTER_TYPES, BOOLEAN_TYPE, OCTET_TYPE)]@
@(int(constant.value))@
@[ if constant.type.typename in UNSIGNED_INTEGER_TYPES]@
u@
@[ end if];
@[ else]@
@(constant.value);
@[ end if]@
@[ end if]@
@[ if constant.name in msvc_common_macros]@
#if defined(_WIN32)
# pragma warning(suppress : 4602)
# pragma pop_macro("@(constant.name)")
#endif
@[ end if]@
@[end for]@
// pointer types
using RawPtr =
@(message_typename)_<ContainerAllocator> *;
using ConstRawPtr =
const @(message_typename)_<ContainerAllocator> *;
using SharedPtr =
std::shared_ptr<@(message_typename)_<ContainerAllocator>>;
using ConstSharedPtr =
std::shared_ptr<@(message_typename)_<ContainerAllocator> const>;
template<typename Deleter = std::default_delete<
@(message_typename)_<ContainerAllocator>>>
using UniquePtrWithDeleter =
std::unique_ptr<@(message_typename)_<ContainerAllocator>, Deleter>;
using UniquePtr = UniquePtrWithDeleter<>;
template<typename Deleter = std::default_delete<
@(message_typename)_<ContainerAllocator>>>
using ConstUniquePtrWithDeleter =
std::unique_ptr<@(message_typename)_<ContainerAllocator> const, Deleter>;
using ConstUniquePtr = ConstUniquePtrWithDeleter<>;
using WeakPtr =
std::weak_ptr<@(message_typename)_<ContainerAllocator>>;
using ConstWeakPtr =
std::weak_ptr<@(message_typename)_<ContainerAllocator> const>;
// pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
// NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
typedef @(deprecated_macro_name)
std::shared_ptr<@(message_typename)_<ContainerAllocator>>
Ptr;
typedef @(deprecated_macro_name)
std::shared_ptr<@(message_typename)_<ContainerAllocator> const>
ConstPtr;
// comparison operators
bool operator==(const @(message.structure.namespaced_type.name)_ & other) const
{
@[if not message.structure.members]@
(void)other;
@[end if]@
@[for member in message.structure.members]@
if (this->@(member.name) != other.@(member.name)) {
return false;
}
@[end for]@
return true;
}
bool operator!=(const @(message.structure.namespaced_type.name)_ & other) const
{
return !this->operator==(other);
}
}; // struct @(message.structure.namespaced_type.name)_
// alias to use template instance with default allocator
using @(message.structure.namespaced_type.name) =
@(message_typename)_<std::allocator<void>>;
// constant definitions
@[for c in message.constants]@
@[ if c.name in msvc_common_macros]@
// guard against '@(c.name)' being predefined by MSVC by temporarily undefining it
#if defined(_WIN32)
# if defined(@(c.name))
# pragma push_macro("@(c.name)")
# undef @(c.name)
# endif
#endif
@[ end if]@
@[ if isinstance(c.type, AbstractString)]@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP['string'])
@(message.structure.namespaced_type.name)_<ContainerAllocator>::@(c.name) = "@(escape_string(c.value))";
@[ elif isinstance(c.type, AbstractWString)]@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP['wstring'])
@(message.structure.namespaced_type.name)_<ContainerAllocator>::@(c.name) = u"@(escape_wstring(c.value))";
@[ else ]@
template<typename ContainerAllocator>
constexpr @(MSG_TYPE_TO_CPP[c.type.typename]) @(message.structure.namespaced_type.name)_<ContainerAllocator>::@(c.name);
@[ end if]@
@[ if c.name in msvc_common_macros]@
#if defined(_WIN32)
# pragma warning(suppress : 4602)
# pragma pop_macro("@(c.name)")
#endif
@[ end if]@
@[end for]@
@
@[for ns in reversed(message.structure.namespaced_type.namespaces)]@
} // namespace @(ns)
@[end for]@