Skip to content

Commit 8a90f74

Browse files
Chen LihuiChen Lihui
authored andcommitted
Name remapping specific to a fully-qualified node's name
Not to support __node and __ns that will break API Signed-off-by: Chen Lihui <[email protected]>
1 parent 8a495c0 commit 8a90f74

File tree

6 files changed

+173
-20
lines changed

6 files changed

+173
-20
lines changed

rcl/include/rcl/lexer_lookahead.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,28 @@ rcl_lexer_lookahead2_peek2(
170170
rcl_lexeme_t * next_type1,
171171
rcl_lexeme_t * next_type2);
172172

173+
/// Look ahead to check if buffer contains colon prefix.
174+
/**
175+
* <hr>
176+
* Attribute | Adherence
177+
* ------------------ | -------------
178+
* Allocates Memory | Yes [1]
179+
* Thread-Safe | No
180+
* Uses Atomics | No
181+
* Lock-Free | Yes
182+
* <i>[1] Only allocates if an argument is invalid or an internal bug is detected.</i>
183+
*
184+
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
185+
* \return `RCL_RET_OK` if peeking was successfull, or
186+
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
187+
* \return `RCL_RET_ERROR` if an unspecified error occurs.
188+
*/
189+
RCL_PUBLIC
190+
RCL_WARN_UNUSED
191+
rcl_ret_t
192+
rcl_lexer_lookahead2_peek_colon_prefix(
193+
rcl_lexer_lookahead2_t * buffer);
194+
173195
/// Accept a lexeme and advance analysis.
174196
/**
175197
* A token must have been peeked before it can be accepted.

rcl/src/rcl/arguments.c

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,36 +1504,74 @@ _rcl_parse_remap_nodename_replacement(
15041504
return RCL_RET_OK;
15051505
}
15061506

1507-
/// Parse a nodename prefix including trailing colon (ex: `node_name:`).
1507+
/// Parse a nodename prefix including trailing colon (ex: `node_name:` or `/ns/node_name:`).
15081508
RCL_LOCAL
15091509
rcl_ret_t
15101510
_rcl_parse_nodename_prefix(
15111511
rcl_lexer_lookahead2_t * lex_lookahead,
15121512
rcl_allocator_t allocator,
15131513
char ** node_name)
15141514
{
1515-
size_t length = 0;
1516-
const char * token = NULL;
1517-
15181515
// Check arguments sanity
15191516
assert(NULL != lex_lookahead);
15201517
assert(rcutils_allocator_is_valid(&allocator));
15211518
assert(NULL != node_name);
15221519
assert(NULL == *node_name);
15231520

1524-
// Expect a token and a colon
1525-
rcl_ret_t ret =
1526-
rcl_lexer_lookahead2_expect(lex_lookahead, RCL_LEXEME_TOKEN, &token, &length);
1521+
rcl_ret_t ret;
1522+
const char * name_start = rcl_lexer_lookahead2_get_text(lex_lookahead);
1523+
if (NULL == name_start) {
1524+
RCL_SET_ERROR_MSG("failed to get start of node name");
1525+
return RCL_RET_ERROR;
1526+
}
1527+
1528+
rcl_lexeme_t next_type;
1529+
ret = rcl_lexer_lookahead2_peek(lex_lookahead, &next_type);
15271530
if (RCL_RET_OK != ret) {
15281531
return ret;
15291532
}
1533+
1534+
if (RCL_LEXEME_FORWARD_SLASH == next_type) {
1535+
// repeated slashes and tokens until a colon
1536+
do {
1537+
ret = rcl_lexer_lookahead2_expect(lex_lookahead, RCL_LEXEME_FORWARD_SLASH, NULL, NULL);
1538+
if (RCL_RET_WRONG_LEXEME == ret) {
1539+
rcl_reset_error();
1540+
break;
1541+
}
1542+
1543+
ret = rcl_lexer_lookahead2_expect(lex_lookahead, RCL_LEXEME_TOKEN, NULL, NULL);
1544+
if (RCL_RET_WRONG_LEXEME == ret) {
1545+
if (RCL_RET_OK == ret) {
1546+
rcl_reset_error();
1547+
break;
1548+
}
1549+
}
1550+
1551+
ret = rcl_lexer_lookahead2_peek(lex_lookahead, &next_type);
1552+
if (RCL_RET_OK != ret) {
1553+
return ret;
1554+
}
1555+
if (RCL_LEXEME_COLON == next_type) {
1556+
break;
1557+
}
1558+
} while (true);
1559+
} else {
1560+
ret =
1561+
rcl_lexer_lookahead2_expect(lex_lookahead, RCL_LEXEME_TOKEN, NULL, NULL);
1562+
if (RCL_RET_OK != ret) {
1563+
return ret;
1564+
}
1565+
}
1566+
1567+
const char * name_end = rcl_lexer_lookahead2_get_text(lex_lookahead);
15301568
ret = rcl_lexer_lookahead2_expect(lex_lookahead, RCL_LEXEME_COLON, NULL, NULL);
15311569
if (RCL_RET_OK != ret) {
15321570
return ret;
15331571
}
1534-
1572+
const size_t length = (size_t)(name_end - name_start);
15351573
// Copy the node name
1536-
*node_name = rcutils_strndup(token, length, allocator);
1574+
*node_name = rcutils_strndup(name_start, length, allocator);
15371575
if (NULL == *node_name) {
15381576
RCL_SET_ERROR_MSG("failed to allocate node name");
15391577
return RCL_RET_BAD_ALLOC;
@@ -1582,18 +1620,14 @@ _rcl_parse_remap_begin_remap_rule(
15821620
{
15831621
rcl_ret_t ret;
15841622
rcl_lexeme_t lexeme1;
1585-
rcl_lexeme_t lexeme2;
15861623

15871624
// Check arguments sanity
15881625
assert(NULL != lex_lookahead);
15891626
assert(NULL != rule);
15901627

15911628
// Check for optional nodename prefix
1592-
ret = rcl_lexer_lookahead2_peek2(lex_lookahead, &lexeme1, &lexeme2);
1593-
if (RCL_RET_OK != ret) {
1594-
return ret;
1595-
}
1596-
if (RCL_LEXEME_TOKEN == lexeme1 && RCL_LEXEME_COLON == lexeme2) {
1629+
ret = rcl_lexer_lookahead2_peek_colon_prefix(lex_lookahead);
1630+
if (RCL_RET_OK == ret) {
15971631
ret = _rcl_parse_remap_nodename_prefix(lex_lookahead, rule);
15981632
if (RCL_RET_OK != ret) {
15991633
return ret;

rcl/src/rcl/lexer_lookahead.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,42 @@ rcl_lexer_lookahead2_peek2(
162162
return RCL_RET_OK;
163163
}
164164

165+
rcl_ret_t
166+
rcl_lexer_lookahead2_peek_colon_prefix(
167+
rcl_lexer_lookahead2_t * buffer)
168+
{
169+
RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
170+
171+
RCL_CHECK_ARGUMENT_FOR_NULL(buffer, RCL_RET_INVALID_ARGUMENT);
172+
RCL_CHECK_FOR_NULL_WITH_MSG(
173+
buffer->impl, "buffer not initialized", return RCL_RET_INVALID_ARGUMENT);
174+
RCL_CHECK_FOR_NULL_WITH_MSG(
175+
buffer->impl->text, "buffer text not initialized", return RCL_RET_INVALID_ARGUMENT);
176+
177+
rcl_lexeme_t lexeme = RCL_LEXEME_NONE;
178+
rcl_ret_t ret;
179+
size_t length;
180+
const char * ptext = buffer->impl->text;
181+
while (ptext) {
182+
if (*ptext == '\0') {
183+
ret = RCL_RET_ERROR;
184+
break;
185+
}
186+
ret = rcl_lexer_analyze(ptext, &lexeme, &length);
187+
if (RCL_RET_OK != ret) {
188+
break;
189+
}
190+
191+
if (lexeme == RCL_LEXEME_COLON) {
192+
ret = RCL_RET_OK;
193+
break;
194+
}
195+
196+
ptext += length;
197+
}
198+
return ret;
199+
}
200+
165201
rcl_ret_t
166202
rcl_lexer_lookahead2_accept(
167203
rcl_lexer_lookahead2_t * buffer,

rcl/src/rcl/remap.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "rcl/error_handling.h"
2020
#include "rcl/expand_topic_name.h"
2121
#include "rcutils/allocator.h"
22+
#include "rcutils/format_string.h"
2223
#include "rcutils/macros.h"
2324
#include "rcutils/strdup.h"
2425
#include "rcutils/types/string_map.h"
@@ -113,15 +114,34 @@ rcl_remap_first_match(
113114
rcl_remap_t ** output_rule)
114115
{
115116
*output_rule = NULL;
117+
118+
char * full_qualified_name = NULL;
119+
if (node_namespace && node_name) {
120+
const char * fmt = (strlen(node_namespace) == 1) ? "%s%s" : "%s/%s";
121+
full_qualified_name =
122+
rcutils_format_string(allocator, fmt, node_namespace, node_name);
123+
if (NULL == full_qualified_name) {
124+
RCL_SET_ERROR_MSG("failed to allocate memory for full node name");
125+
return RCL_RET_BAD_ALLOC;
126+
}
127+
}
128+
116129
for (int i = 0; i < num_rules; ++i) {
117130
rcl_remap_t * rule = &(remap_rules[i]);
118131
if (!(rule->impl->type & type_bitmask)) {
119132
// Not the type of remap rule we're looking fore
120133
continue;
121134
}
122-
if (rule->impl->node_name != NULL && 0 != strcmp(rule->impl->node_name, node_name)) {
123-
// Rule has a node name prefix and the supplied node name didn't match
124-
continue;
135+
if (rule->impl->node_name != NULL) {
136+
if (rule->impl->node_name[0] == '/' && full_qualified_name) {
137+
if (0 != strcmp(rule->impl->node_name, full_qualified_name)) {
138+
// Rule has a full qualified name and the supplied node name didn't match
139+
continue;
140+
}
141+
} else if (0 != strcmp(rule->impl->node_name, node_name)) {
142+
// Rule has a node name prefix and the supplied node name didn't match
143+
continue;
144+
}
125145
}
126146
bool matched = false;
127147
if (rule->impl->type & (RCL_TOPIC_REMAP | RCL_SERVICE_REMAP)) {
@@ -138,6 +158,7 @@ rcl_remap_first_match(
138158
RCL_RET_BAD_ALLOC == ret)
139159
{
140160
// these are probably going to happen again. Stop processing rules
161+
allocator.deallocate(full_qualified_name, allocator.state);
141162
return ret;
142163
}
143164
continue;
@@ -153,6 +174,7 @@ rcl_remap_first_match(
153174
break;
154175
}
155176
}
177+
allocator.deallocate(full_qualified_name, allocator.state);
156178
return RCL_RET_OK;
157179
}
158180

rcl/test/rcl/test_arguments.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ TEST_F(CLASSNAME(TestArgumentsFixture, RMW_IMPLEMENTATION), check_known_vs_unkno
143143
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "foo:=/bar"}));
144144
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "/foo123:=/bar123"}));
145145
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "node:/foo123:=/bar123"}));
146+
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "node:foo123:=/bar123"}));
147+
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "/node:foo123:=/bar123"}));
148+
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "/ns1/node:foo123:=/bar123"}));
146149
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "rostopic:=/foo/bar"}));
147150
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "rosservice:=baz"}));
148151
EXPECT_TRUE(are_known_ros_args({"--ros-args", "-r", "rostopic://rostopic:=rosservice"}));

rcl/test/rcl/test_remap.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,9 @@ TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), nodename_prefix_topic_re
194194
"--ros-args",
195195
"-r", "Node1:/foo:=/foo/bar",
196196
"-r", "Node2:/foo:=/this_one",
197-
"-r", "Node3:/foo:=/bar/foo");
197+
"-r", "Node3:/foo:=/bar/foo",
198+
"-r", "/Node4:/foo:=/bar/foo",
199+
"-r", "/ns1/Node5:/foo:=/bar/foo");
198200

199201
{
200202
char * output = NULL;
@@ -220,6 +222,22 @@ TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), nodename_prefix_topic_re
220222
EXPECT_STREQ("/bar/foo", output);
221223
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
222224
}
225+
{
226+
char * output = NULL;
227+
ret = rcl_remap_topic_name(
228+
NULL, &global_arguments, "/foo", "Node4", "/", rcl_get_default_allocator(), &output);
229+
EXPECT_EQ(RCL_RET_OK, ret);
230+
EXPECT_STREQ("/bar/foo", output);
231+
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
232+
}
233+
{
234+
char * output = NULL;
235+
ret = rcl_remap_topic_name(
236+
NULL, &global_arguments, "/foo", "Node5", "/ns1", rcl_get_default_allocator(), &output);
237+
EXPECT_EQ(RCL_RET_OK, ret);
238+
EXPECT_STREQ("/bar/foo", output);
239+
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
240+
}
223241
}
224242

225243
TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), no_use_global_topic_name_replacement) {
@@ -326,7 +344,9 @@ TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), nodename_prefix_service_
326344
"--ros-args",
327345
"-r", "Node1:/foo:=/foo/bar",
328346
"-r", "Node2:/foo:=/this_one",
329-
"-r", "Node3:/foo:=/bar/foo");
347+
"-r", "Node3:/foo:=/bar/foo",
348+
"-r", "/Node4:/foo:=/bar/foo",
349+
"-r", "/ns1/Node5:/foo:=/bar/foo");
330350

331351
{
332352
char * output = NULL;
@@ -352,6 +372,22 @@ TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), nodename_prefix_service_
352372
EXPECT_STREQ("/bar/foo", output);
353373
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
354374
}
375+
{
376+
char * output = NULL;
377+
ret = rcl_remap_service_name(
378+
NULL, &global_arguments, "/foo", "Node4", "/", rcl_get_default_allocator(), &output);
379+
EXPECT_EQ(RCL_RET_OK, ret);
380+
EXPECT_STREQ("/bar/foo", output);
381+
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
382+
}
383+
{
384+
char * output = NULL;
385+
ret = rcl_remap_service_name(
386+
NULL, &global_arguments, "/foo", "Node5", "/ns1", rcl_get_default_allocator(), &output);
387+
EXPECT_EQ(RCL_RET_OK, ret);
388+
EXPECT_STREQ("/bar/foo", output);
389+
rcl_get_default_allocator().deallocate(output, rcl_get_default_allocator().state);
390+
}
355391
}
356392

357393
TEST_F(CLASSNAME(TestRemapFixture, RMW_IMPLEMENTATION), no_use_global_service_name_replacement) {

0 commit comments

Comments
 (0)