Skip to content

Commit d5d0b1a

Browse files
hidmicnnmm
authored andcommitted
Implement copy function for C messages (ros2#650)
Signed-off-by: Michel Hidalgo <[email protected]>
1 parent deca082 commit d5d0b1a

File tree

12 files changed

+547
-3
lines changed

12 files changed

+547
-3
lines changed

rosidl_generator_c/resource/msg__functions.c.em

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,47 @@ bool
275275
return true;
276276
}
277277

278+
bool
279+
@(message_typename)__copy(
280+
const @(message_typename) * input,
281+
@(message_typename) * output)
282+
{
283+
if (!input || !output) {
284+
return false;
285+
}
286+
@[for member in message.structure.members]@
287+
// @(member.name)
288+
@[ if isinstance(member.type, Array)]@
289+
for (size_t i = 0; i < @(member.type.size); ++i) {
290+
@[ if isinstance(member.type.value_type, (AbstractGenericString, NamespacedType))]@
291+
if (!@(basetype_to_c(member.type.value_type))__copy(
292+
&(input->@(member.name)[i]), &(output->@(member.name)[i])))
293+
{
294+
return false;
295+
}
296+
@[ else]@
297+
output->@(member.name)[i] = input->@(member.name)[i];
298+
@[ end if]@
299+
}
300+
@[ elif isinstance(member.type, AbstractSequence)]@
301+
if (!@(idl_type_to_c(member.type))__copy(
302+
&(input->@(member.name)), &(output->@(member.name))))
303+
{
304+
return false;
305+
}
306+
@[ elif isinstance(member.type, (AbstractGenericString, NamespacedType))]@
307+
if (!@(basetype_to_c(member.type))__copy(
308+
&(input->@(member.name)), &(output->@(member.name))))
309+
{
310+
return false;
311+
}
312+
@[ else]@
313+
output->@(member.name) = input->@(member.name);
314+
@[ end if]@
315+
@[end for]@
316+
return true;
317+
}
318+
278319
@(message_typename) *
279320
@(message_typename)__create()
280321
{
@@ -403,3 +444,45 @@ bool
403444
}
404445
return true;
405446
}
447+
448+
bool
449+
@(array_typename)__copy(
450+
const @(array_typename) * input,
451+
@(array_typename) * output)
452+
{
453+
if (!input || !output) {
454+
return false;
455+
}
456+
if (output->capacity < input->size) {
457+
const size_t allocation_size =
458+
input->size * sizeof(@(message_typename));
459+
rcutils_allocator_t allocator = rcutils_get_default_allocator();
460+
@(message_typename) * data =
461+
(@(message_typename) *)allocator.reallocate(
462+
output->data, allocation_size, allocator.state);
463+
if (!data) {
464+
return false;
465+
}
466+
for (size_t i = output->capacity; i < input->size; ++i) {
467+
if (!@(message_typename)__init(&data[i])) {
468+
/* free currently allocated and return false */
469+
for (; i-- > output->capacity; ) {
470+
@(message_typename)__fini(&data[i]);
471+
}
472+
allocator.deallocate(data, allocator.state);
473+
return false;
474+
}
475+
}
476+
output->data = data;
477+
output->size = input->size;
478+
output->capacity = input->size;
479+
}
480+
for (size_t i = 0; i < input->size; ++i) {
481+
if (!@(message_typename)__copy(
482+
&(input->data[i]), &(output->data[i])))
483+
{
484+
return false;
485+
}
486+
}
487+
return true;
488+
}

rosidl_generator_c/resource/msg__functions.h.em

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
6969
bool
7070
@(message_typename)__are_equal(const @(message_typename) * lhs, const @(message_typename) * rhs);
7171
72+
/// Copy a @(interface_path_to_string(interface_path)) message.
73+
/**
74+
* This functions performs a deep copy, as opposed to the shallow copy that
75+
* plain assignment yields.
76+
*
77+
* \param[in] input The source message pointer.
78+
* \param[out] output The target message pointer, which must
79+
* have been initialized before calling this function.
80+
* \return true if successful, or false if either pointer is null
81+
* or memory allocation fails.
82+
*/
83+
ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
84+
bool
85+
@(message_typename)__copy(
86+
const @(message_typename) * input,
87+
@(message_typename) * output);
88+
7289
@#######################################################################
7390
@# array functions
7491
@#######################################################################
@@ -131,3 +148,20 @@ void
131148
ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
132149
bool
133150
@(array_typename)__are_equal(const @(array_typename) * lhs, const @(array_typename) * rhs);
151+
152+
/// Copy an array of @(interface_path_to_string(interface_path)) messages.
153+
/**
154+
* This functions performs a deep copy, as opposed to the shallow copy that
155+
* plain assignment yields.
156+
*
157+
* \param[in] input The source array pointer.
158+
* \param[out] output The target array pointer, which must
159+
* have been initialized before calling this function.
160+
* \return true if successful, or false if either pointer
161+
* is null or memory allocation fails.
162+
*/
163+
ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
164+
bool
165+
@(array_typename)__copy(
166+
const @(array_typename) * input,
167+
@(array_typename) * output);

rosidl_generator_c/test/test_interfaces.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ int test_basic_types(void)
202202
EXPECT_FALSE(rosidl_generator_c__msg__BasicTypes__are_equal(NULL, basic));
203203
EXPECT_TRUE(rosidl_generator_c__msg__BasicTypes__are_equal(basic, basic));
204204

205+
rosidl_generator_c__msg__BasicTypes * basic_copy = NULL;
206+
basic_copy = rosidl_generator_c__msg__BasicTypes__create();
207+
EXPECT_NE(basic_copy, NULL);
208+
EXPECT_FALSE(rosidl_generator_c__msg__BasicTypes__are_equal(basic, basic_copy));
209+
EXPECT_TRUE(rosidl_generator_c__msg__BasicTypes__copy(basic, basic_copy));
210+
EXPECT_TRUE(rosidl_generator_c__msg__BasicTypes__are_equal(basic, basic_copy));
211+
rosidl_generator_c__msg__BasicTypes__destroy(basic_copy);
212+
205213
rosidl_generator_c__msg__BasicTypes__destroy(basic);
206214
return 0;
207215
}
@@ -250,6 +258,15 @@ int test_defaults()
250258
EXPECT_FALSE(rosidl_generator_c__msg__Defaults__are_equal(NULL, def));
251259
EXPECT_TRUE(rosidl_generator_c__msg__Defaults__are_equal(def, def));
252260

261+
rosidl_generator_c__msg__Defaults * def_copy = NULL;
262+
def_copy = rosidl_generator_c__msg__Defaults__create();
263+
EXPECT_NE(def_copy, NULL);
264+
def->bool_value = false; // mutate message to force a difference
265+
EXPECT_FALSE(rosidl_generator_c__msg__Defaults__are_equal(def, def_copy));
266+
EXPECT_TRUE(rosidl_generator_c__msg__Defaults__copy(def, def_copy));
267+
EXPECT_TRUE(rosidl_generator_c__msg__Defaults__are_equal(def, def_copy));
268+
rosidl_generator_c__msg__Defaults__destroy(def_copy);
269+
253270
rosidl_generator_c__msg__Defaults__destroy(def);
254271
return 0;
255272
}
@@ -470,6 +487,14 @@ int test_bounded_sequences()
470487
EXPECT_FALSE(rosidl_generator_c__msg__BoundedSequences__are_equal(NULL, seq));
471488
EXPECT_TRUE(rosidl_generator_c__msg__BoundedSequences__are_equal(seq, seq));
472489

490+
rosidl_generator_c__msg__BoundedSequences * seq_copy = NULL;
491+
seq_copy = rosidl_generator_c__msg__BoundedSequences__create();
492+
EXPECT_NE(seq_copy, NULL);
493+
EXPECT_FALSE(rosidl_generator_c__msg__BoundedSequences__are_equal(seq, seq_copy));
494+
EXPECT_TRUE(rosidl_generator_c__msg__BoundedSequences__copy(seq, seq_copy));
495+
EXPECT_TRUE(rosidl_generator_c__msg__BoundedSequences__are_equal(seq, seq_copy));
496+
rosidl_generator_c__msg__BoundedSequences__destroy(seq_copy);
497+
473498
rosidl_generator_c__msg__BoundedSequences__destroy(seq);
474499
return 0;
475500
}
@@ -691,6 +716,14 @@ int test_unbounded_sequences()
691716
EXPECT_FALSE(rosidl_generator_c__msg__UnboundedSequences__are_equal(NULL, seq));
692717
EXPECT_TRUE(rosidl_generator_c__msg__UnboundedSequences__are_equal(seq, seq));
693718

719+
rosidl_generator_c__msg__UnboundedSequences * seq_copy = NULL;
720+
seq_copy = rosidl_generator_c__msg__UnboundedSequences__create();
721+
EXPECT_NE(seq_copy, NULL);
722+
EXPECT_FALSE(rosidl_generator_c__msg__UnboundedSequences__are_equal(seq, seq_copy));
723+
EXPECT_TRUE(rosidl_generator_c__msg__UnboundedSequences__copy(seq, seq_copy));
724+
EXPECT_TRUE(rosidl_generator_c__msg__UnboundedSequences__are_equal(seq, seq_copy));
725+
rosidl_generator_c__msg__UnboundedSequences__destroy(seq_copy);
726+
694727
rosidl_generator_c__msg__UnboundedSequences__destroy(seq);
695728
return 0;
696729
}
@@ -727,6 +760,14 @@ int test_strings()
727760
EXPECT_FALSE(rosidl_generator_c__msg__Strings__are_equal(NULL, str));
728761
EXPECT_TRUE(rosidl_generator_c__msg__Strings__are_equal(str, str));
729762

763+
rosidl_generator_c__msg__Strings * str_copy = NULL;
764+
str_copy = rosidl_generator_c__msg__Strings__create();
765+
EXPECT_NE(str_copy, NULL);
766+
EXPECT_FALSE(rosidl_generator_c__msg__Strings__are_equal(str, str_copy));
767+
EXPECT_TRUE(rosidl_generator_c__msg__Strings__copy(str, str_copy));
768+
EXPECT_TRUE(rosidl_generator_c__msg__Strings__are_equal(str, str_copy));
769+
rosidl_generator_c__msg__Strings__destroy(str_copy);
770+
730771
rosidl_generator_c__msg__Strings__destroy(str);
731772
return 0;
732773
}
@@ -770,6 +811,14 @@ int test_nested()
770811
EXPECT_FALSE(rosidl_generator_c__msg__Nested__are_equal(NULL, nested));
771812
EXPECT_TRUE(rosidl_generator_c__msg__Nested__are_equal(nested, nested));
772813

814+
rosidl_generator_c__msg__Nested * nested_copy = NULL;
815+
nested_copy = rosidl_generator_c__msg__Nested__create();
816+
EXPECT_NE(nested_copy, NULL);
817+
EXPECT_FALSE(rosidl_generator_c__msg__Nested__are_equal(nested, nested_copy));
818+
EXPECT_TRUE(rosidl_generator_c__msg__Nested__copy(nested, nested_copy));
819+
EXPECT_TRUE(rosidl_generator_c__msg__Nested__are_equal(nested, nested_copy));
820+
rosidl_generator_c__msg__Nested__destroy(nested_copy);
821+
773822
rosidl_generator_c__msg__Nested__destroy(nested);
774823
return 0;
775824
}
@@ -1014,6 +1063,14 @@ int test_multi_nested()
10141063
EXPECT_FALSE(rosidl_generator_c__msg__MultiNested__are_equal(NULL, msg));
10151064
EXPECT_TRUE(rosidl_generator_c__msg__MultiNested__are_equal(msg, msg));
10161065

1066+
rosidl_generator_c__msg__MultiNested * msg_copy = NULL;
1067+
msg_copy = rosidl_generator_c__msg__MultiNested__create();
1068+
EXPECT_NE(msg_copy, NULL);
1069+
EXPECT_FALSE(rosidl_generator_c__msg__MultiNested__are_equal(msg, msg_copy));
1070+
EXPECT_TRUE(rosidl_generator_c__msg__MultiNested__copy(msg, msg_copy));
1071+
EXPECT_TRUE(rosidl_generator_c__msg__MultiNested__are_equal(msg, msg_copy));
1072+
rosidl_generator_c__msg__MultiNested__destroy(msg_copy);
1073+
10171074
rosidl_generator_c__msg__MultiNested__destroy(msg);
10181075
return 0;
10191076
}
@@ -1230,6 +1287,14 @@ int test_arrays()
12301287
EXPECT_FALSE(rosidl_generator_c__msg__Arrays__are_equal(NULL, arr));
12311288
EXPECT_TRUE(rosidl_generator_c__msg__Arrays__are_equal(arr, arr));
12321289

1290+
rosidl_generator_c__msg__Arrays * arr_copy = NULL;
1291+
arr_copy = rosidl_generator_c__msg__Arrays__create();
1292+
EXPECT_NE(arr_copy, NULL);
1293+
EXPECT_FALSE(rosidl_generator_c__msg__Arrays__are_equal(arr, arr_copy));
1294+
EXPECT_TRUE(rosidl_generator_c__msg__Arrays__copy(arr, arr_copy));
1295+
EXPECT_TRUE(rosidl_generator_c__msg__Arrays__are_equal(arr, arr_copy));
1296+
rosidl_generator_c__msg__Arrays__destroy(arr_copy);
1297+
12331298
rosidl_generator_c__msg__Arrays__destroy(arr);
12341299
return 0;
12351300
}

rosidl_runtime_c/include/rosidl_runtime_c/primitives_sequence_functions.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,36 @@ extern "C"
7676
const rosidl_runtime_c__ ## STRUCT_NAME ## __Sequence * lhs, \
7777
const rosidl_runtime_c__ ## STRUCT_NAME ## __Sequence * rhs);
7878

79+
/**
80+
* \def ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(STRUCT_NAME)
81+
*
82+
* \brief Copy the sequence.
83+
*
84+
* param input a pointer to the sequence to copy from
85+
* param output a pointer to an initialized sequence to copy to
86+
* return true if successful, false if either pointer is null or memory
87+
* allocation fails.
88+
*/
89+
#define ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(STRUCT_NAME) \
90+
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(STRUCT_NAME) */ \
91+
ROSIDL_GENERATOR_C_PUBLIC \
92+
bool rosidl_runtime_c__ ## STRUCT_NAME ## __Sequence__copy( \
93+
const rosidl_runtime_c__ ## STRUCT_NAME ## __Sequence * input, \
94+
rosidl_runtime_c__ ## STRUCT_NAME ## __Sequence * output);
95+
7996
/**
8097
* \def ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_FUNCTIONS(STRUCT_NAME)
8198
*
8299
* \brief See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_INIT(STRUCT_NAME),
83-
* #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_FINI(STRUCT_NAME), and
84-
* #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_EQ(STRUCT_NAME).
100+
* #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_FINI(STRUCT_NAME),
101+
* #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_EQ(STRUCT_NAME), and
102+
* #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(STRUCT_NAME).
85103
*/
86104
#define ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_FUNCTIONS(STRUCT_NAME) \
87105
ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_INIT(STRUCT_NAME) \
88106
ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_FINI(STRUCT_NAME) \
89-
ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_EQ(STRUCT_NAME)
107+
ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_EQ(STRUCT_NAME) \
108+
ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(STRUCT_NAME)
90109

91110
/**
92111
* \defgroup primitives_sequence_functions__basic_types Sequence functions for all basic types.
@@ -126,6 +145,11 @@ ROSIDL_GENERATOR_C_PUBLIC
126145
bool rosidl_runtime_c__bool__Sequence__are_equal(
127146
const rosidl_runtime_c__boolean__Sequence * lhs,
128147
const rosidl_runtime_c__boolean__Sequence * rhs);
148+
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(bool) */
149+
ROSIDL_GENERATOR_C_PUBLIC
150+
bool rosidl_runtime_c__bool__Sequence__copy(
151+
const rosidl_runtime_c__boolean__Sequence * input,
152+
rosidl_runtime_c__boolean__Sequence * output);
129153

130154
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_INIT(byte) */
131155
ROSIDL_GENERATOR_C_PUBLIC
@@ -140,6 +164,11 @@ ROSIDL_GENERATOR_C_PUBLIC
140164
bool rosidl_runtime_c__byte__Sequence__are_equal(
141165
const rosidl_runtime_c__octet__Sequence * lhs,
142166
const rosidl_runtime_c__octet__Sequence * rhs);
167+
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(byte) */
168+
ROSIDL_GENERATOR_C_PUBLIC
169+
bool rosidl_runtime_c__byte__Sequence__copy(
170+
const rosidl_runtime_c__octet__Sequence * input,
171+
rosidl_runtime_c__octet__Sequence * output);
143172

144173
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_INIT(float32) */
145174
ROSIDL_GENERATOR_C_PUBLIC
@@ -154,6 +183,11 @@ ROSIDL_GENERATOR_C_PUBLIC
154183
bool rosidl_runtime_c__float32__Sequence__are_equal(
155184
const rosidl_runtime_c__float__Sequence * lhs,
156185
const rosidl_runtime_c__float__Sequence * rhs);
186+
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(float32) */
187+
ROSIDL_GENERATOR_C_PUBLIC
188+
bool rosidl_runtime_c__float32__Sequence__copy(
189+
const rosidl_runtime_c__float__Sequence * input,
190+
rosidl_runtime_c__float__Sequence * output);
157191

158192
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_INIT(float64) */
159193
ROSIDL_GENERATOR_C_PUBLIC
@@ -168,6 +202,11 @@ ROSIDL_GENERATOR_C_PUBLIC
168202
bool rosidl_runtime_c__float64__Sequence__are_equal(
169203
const rosidl_runtime_c__double__Sequence * lhs,
170204
const rosidl_runtime_c__double__Sequence * rhs);
205+
/** See #ROSIDL_RUNTIME_C__DECLARE_PRIMITIVE_SEQUENCE_COPY(float64) */
206+
ROSIDL_GENERATOR_C_PUBLIC
207+
bool rosidl_runtime_c__float64__Sequence__copy(
208+
const rosidl_runtime_c__double__Sequence * input,
209+
rosidl_runtime_c__double__Sequence * output);
171210
/**@}*/
172211

173212
#ifdef __cplusplus

rosidl_runtime_c/include/rosidl_runtime_c/string_functions.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ ROSIDL_GENERATOR_C_PUBLIC
5555
void
5656
rosidl_runtime_c__String__fini(rosidl_runtime_c__String * str);
5757

58+
/// Copy rosidl_runtime_c__String structure content.
59+
/**
60+
* This functions performs a deep copy, as opposed to the shallow copy that
61+
* plain assignment yields.
62+
*
63+
* \param[in] input a pointer to a rosidl_runtime_c__String structure
64+
* to copy from.
65+
* \param[out] output a pointer to an initialized rosidl_runtime_c__String
66+
* structure to copy into.
67+
* \return true if successful, false if either pointer is null or memory
68+
* allocation fails.
69+
*/
70+
ROSIDL_GENERATOR_C_PUBLIC
71+
bool
72+
rosidl_runtime_c__String__copy(
73+
const rosidl_runtime_c__String * input,
74+
rosidl_runtime_c__String * output);
75+
5876
/// Check for rosidl_runtime_c__String structure equality.
5977
/**
6078
* \param[in] lhs a pointer to the left hand side of the equality operator.
@@ -142,6 +160,24 @@ rosidl_runtime_c__String__Sequence__are_equal(
142160
const rosidl_runtime_c__String__Sequence * lhs,
143161
const rosidl_runtime_c__String__Sequence * rhs);
144162

163+
/// Copy rosidl_runtime_c__String__Sequence structure content.
164+
/**
165+
* This functions performs a deep copy, as opposed to the shallow copy
166+
* that plain assignment yields.
167+
*
168+
* \param[in] input a pointer to a rosidl_runtime_c__String__Sequence
169+
* structure to copy from.
170+
* \param[out] output a pointer to an initialized rosidl_runtime_c__String__Sequence
171+
* structure to copy into.
172+
* \return true if successful, false if either pointer is null or memory
173+
* allocation fails.
174+
*/
175+
ROSIDL_GENERATOR_C_PUBLIC
176+
bool
177+
rosidl_runtime_c__String__Sequence__copy(
178+
const rosidl_runtime_c__String__Sequence * input,
179+
rosidl_runtime_c__String__Sequence * output);
180+
145181
/// Create a rosidl_runtime_c__String__Sequence structure with a specific size.
146182
/*
147183
* The string sequence initially has size and capacity equal to the size argument passed to the

0 commit comments

Comments
 (0)