From 8e56c51e89df384c270514d3f905ea7225dcd084 Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Fri, 20 Sep 2019 18:15:14 -0300 Subject: [PATCH] Enable incremental parameter yaml file parsing. Signed-off-by: Michel Hidalgo --- rcl_yaml_param_parser/src/parser.c | 49 +++++++++---------- rcl_yaml_param_parser/test/overlay.yaml | 13 +++++ .../test/test_parse_yaml.cpp | 33 +++++++++++-- 3 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 rcl_yaml_param_parser/test/overlay.yaml diff --git a/rcl_yaml_param_parser/src/parser.c b/rcl_yaml_param_parser/src/parser.c index 4fdbe7110..379d3b75b 100644 --- a/rcl_yaml_param_parser/src/parser.c +++ b/rcl_yaml_param_parser/src/parser.c @@ -137,6 +137,8 @@ static rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, + size_t * node_idx, + size_t * parameter_idx, namespace_tracker_t * ns_tracker, rcl_params_t * params_st); @@ -1295,6 +1297,8 @@ static rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, + size_t * node_idx, + size_t * parameter_idx, namespace_tracker_t * ns_tracker, rcl_params_t * params_st) { @@ -1323,11 +1327,6 @@ static rcutils_ret_t parse_key( } } - size_t node_idx = 0U; - size_t num_nodes = params_st->num_nodes; - if (num_nodes > 0U) { - node_idx = num_nodes - 1U; - } rcutils_ret_t ret = RCUTILS_RET_OK; switch (*map_level) { case MAP_UNINIT_LVL: @@ -1359,21 +1358,18 @@ static rcutils_ret_t parse_key( ret = RCUTILS_RET_BAD_ALLOC; break; } - params_st->node_names[num_nodes] = node_name_ns; - ret = rem_name_from_ns(ns_tracker, NS_TYPE_NODE, allocator); + ret = find_node(node_name_ns, params_st, node_idx); if (RCUTILS_RET_OK != ret) { - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( - "Internal error adding node namespace at line %d", line_num); break; } - ret = node_params_init(&(params_st->params[num_nodes]), allocator); + + ret = rem_name_from_ns(ns_tracker, NS_TYPE_NODE, allocator); if (RCUTILS_RET_OK != ret) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( - "Error creating node parameter at line %d", line_num); + "Internal error adding node namespace at line %d", line_num); break; } - params_st->num_nodes++; /// Bump the map level to PARAMS (*map_level)++; } @@ -1381,15 +1377,12 @@ static rcutils_ret_t parse_key( break; case MAP_PARAMS_LVL: { - size_t parameter_idx; char * parameter_ns; char * param_name; /// If it is a new map, the previous key is param namespace if (true == *is_new_map) { - params_st->params[node_idx].num_params--; - parameter_idx = params_st->params[node_idx].num_params; - parameter_ns = params_st->params[node_idx].parameter_names[parameter_idx]; + parameter_ns = params_st->params[*node_idx].parameter_names[*parameter_idx]; if (NULL == parameter_ns) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Internal error creating param namespace at line %d", line_num); @@ -1408,7 +1401,7 @@ static rcutils_ret_t parse_key( } // Guard against adding more than the maximum allowed parameters - if (params_st->params[node_idx].num_params >= MAX_NUM_PARAMS_PER_NODE) { + if (params_st->params[*node_idx].num_params >= MAX_NUM_PARAMS_PER_NODE) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Exceeded maximum allowed number of parameters for a node (%d)", MAX_NUM_PARAMS_PER_NODE); @@ -1417,15 +1410,18 @@ static rcutils_ret_t parse_key( } /// Add a parameter name into the node parameters - parameter_idx = params_st->params[node_idx].num_params; parameter_ns = ns_tracker->parameter_ns; if (NULL == parameter_ns) { - param_name = rcutils_strdup(value, allocator); - if (NULL == param_name) { - ret = RCUTILS_RET_BAD_ALLOC; + ret = find_parameter(*node_idx, value, params_st, parameter_idx); + if (ret != RCUTILS_RET_OK) { break; } } else { + ret = find_parameter(*node_idx, parameter_ns, params_st, parameter_idx); + if (ret != RCUTILS_RET_OK) { + break; + } + const size_t params_ns_len = strlen(parameter_ns); const size_t param_name_len = strlen(value); const size_t tot_len = (params_ns_len + param_name_len + 2U); @@ -1447,9 +1443,9 @@ static rcutils_ret_t parse_key( param_name[params_ns_len] = '.'; memmove((param_name + params_ns_len + 1U), value, param_name_len); param_name[tot_len - 1U] = '\0'; + + params_st->params[*node_idx].parameter_names[*parameter_idx] = param_name; } - params_st->params[node_idx].parameter_names[parameter_idx] = param_name; - params_st->params[node_idx].num_params++; } break; default: @@ -1484,6 +1480,8 @@ static rcutils_ret_t parse_file_events( &allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT); yaml_event_t event; + size_t node_idx = 0; + size_t parameter_idx = 0; rcutils_ret_t ret = RCUTILS_RET_OK; while (0 == done_parsing) { if (RCUTILS_RET_OK != ret) { @@ -1506,7 +1504,8 @@ static rcutils_ret_t parse_file_events( { /// Need to toggle between key and value at params level if (true == is_key) { - ret = parse_key(event, &map_level, &is_new_map, ns_tracker, params_st); + ret = parse_key( + event, &map_level, &is_new_map, &node_idx, ¶meter_idx, ns_tracker, params_st); if (RCUTILS_RET_OK != ret) { break; } @@ -1525,14 +1524,12 @@ static rcutils_ret_t parse_file_events( yaml_event_delete(&event); return RCUTILS_RET_ERROR; } - const size_t node_idx = (params_st->num_nodes - 1U); if (0U == params_st->params[node_idx].num_params) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Cannot have a value before %s at line %d", PARAMS_KEY, line_num); yaml_event_delete(&event); return RCUTILS_RET_ERROR; } - const size_t parameter_idx = (params_st->params[node_idx].num_params - 1U); ret = parse_value(event, is_seq, node_idx, parameter_idx, &seq_data_type, params_st); if (RCUTILS_RET_OK != ret) { break; diff --git a/rcl_yaml_param_parser/test/overlay.yaml b/rcl_yaml_param_parser/test/overlay.yaml new file mode 100644 index 000000000..fa822ed12 --- /dev/null +++ b/rcl_yaml_param_parser/test/overlay.yaml @@ -0,0 +1,13 @@ +# config/test_yaml +--- + +lidar_ns: + lidar_2: + ros__parameters: + is_back: true +camera: + ros__parameters: + loc: back +intel: + ros__parameters: + num_cores: 12 diff --git a/rcl_yaml_param_parser/test/test_parse_yaml.cpp b/rcl_yaml_param_parser/test/test_parse_yaml.cpp index 25706a75c..6d593c27d 100644 --- a/rcl_yaml_param_parser/test/test_parse_yaml.cpp +++ b/rcl_yaml_param_parser/test/test_parse_yaml.cpp @@ -48,6 +48,15 @@ TEST(test_parser, correct_syntax) { bool res = rcl_parse_yaml_file(path, params_hdl); ASSERT_TRUE(res) << rcutils_get_error_string().str; + char * another_path = rcutils_join_path(test_path, "overlay.yaml", allocator); + ASSERT_TRUE(NULL != another_path) << rcutils_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + allocator.deallocate(another_path, allocator.state); + }); + ASSERT_TRUE(rcutils_exists(another_path)) << "No test YAML file found at " << another_path; + res = rcl_parse_yaml_file(another_path, params_hdl); + ASSERT_TRUE(res) << rcutils_get_error_string().str; + rcl_params_t * copy_of_params_hdl = rcl_yaml_node_struct_copy(params_hdl); ASSERT_TRUE(NULL != copy_of_params_hdl) << rcutils_get_error_string().str; OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ @@ -59,11 +68,11 @@ TEST(test_parser, correct_syntax) { rcl_variant_t * param_value = rcl_yaml_node_struct_get("lidar_ns/lidar_2", "is_back", params); ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; ASSERT_TRUE(NULL != param_value->bool_value); - EXPECT_FALSE(*param_value->bool_value); - res = rcl_parse_yaml_value("lidar_ns/lidar_2", "is_back", "true", params); + EXPECT_TRUE(*param_value->bool_value); + res = rcl_parse_yaml_value("lidar_ns/lidar_2", "is_back", "false", params); EXPECT_TRUE(res) << rcutils_get_error_string().str; ASSERT_TRUE(NULL != param_value->bool_value); - EXPECT_TRUE(*param_value->bool_value); + EXPECT_FALSE(*param_value->bool_value); param_value = rcl_yaml_node_struct_get("lidar_ns/lidar_2", "id", params); ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; @@ -74,6 +83,15 @@ TEST(test_parser, correct_syntax) { ASSERT_TRUE(NULL != param_value->integer_value); EXPECT_EQ(12, *param_value->integer_value); + param_value = rcl_yaml_node_struct_get("camera", "loc", params); + ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; + ASSERT_TRUE(NULL != param_value->string_value); + EXPECT_STREQ("back", param_value->string_value); + res = rcl_parse_yaml_value("camera", "loc", "front", params); + EXPECT_TRUE(res) << rcutils_get_error_string().str; + ASSERT_TRUE(NULL != param_value->string_value); + EXPECT_STREQ("front", param_value->string_value); + param_value = rcl_yaml_node_struct_get("camera", "cam_spec.angle", params); ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; ASSERT_TRUE(NULL != param_value->double_value); @@ -83,6 +101,15 @@ TEST(test_parser, correct_syntax) { ASSERT_TRUE(NULL != param_value->double_value); EXPECT_DOUBLE_EQ(2.2, *param_value->double_value); + param_value = rcl_yaml_node_struct_get("intel", "num_cores", params); + ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; + ASSERT_TRUE(NULL != param_value->integer_value); + EXPECT_EQ(12, *param_value->integer_value); + res = rcl_parse_yaml_value("intel", "num_cores", "8", params); + EXPECT_TRUE(res) << rcutils_get_error_string().str; + ASSERT_TRUE(NULL != param_value->integer_value); + EXPECT_EQ(8, *param_value->integer_value); + param_value = rcl_yaml_node_struct_get("intel", "arch", params); ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str; ASSERT_TRUE(NULL != param_value->string_value);