From 245dfe41e59bfffc0c6efb8e4efd04a679d0d54f Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Tue, 22 Jul 2025 20:13:56 -0700 Subject: [PATCH 01/18] feat: Add `write_structured_parameter_to_string` function and integrate it into the YAML parser Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 9 ++ rcl_yaml_param_parser/src/parse.c | 124 +++++++++++++++++++++++++ 2 files changed, 133 insertions(+) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 99f5d28e7..465ef0ad6 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -49,6 +49,15 @@ rcutils_ret_t parse_value( data_types_t * seq_data_type, rcl_params_t * params_st); +RCL_YAML_PARAM_PARSER_PUBLIC +RCUTILS_WARN_UNUSED +rcutils_ret_t write_structured_parameter_to_string( + yaml_parser_t * parser, + yaml_event_t * current_event, + uint32_t * map_depth, + size_t * parameter_index, + rcl_params_t * params_st); + RCL_YAML_PARAM_PARSER_PUBLIC RCUTILS_WARN_UNUSED rcutils_ret_t parse_key( diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 63d162a1c..d7e33577d 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -746,6 +746,112 @@ rcutils_ret_t parse_key( return ret; } +rcutils_ret_t write_structured_parameter_to_string( + yaml_parser_t * parser, + yaml_event_t * current_event, + uint32_t * map_depth, + size_t * parameter_index, + rcl_params_t * params_st) +{ + rcutils_ret_t ret; + + size_t nest_depth = *map_depth; + + //TODO: Move string length to a macro + size_t max_string_length = 100000; + static unsigned char nested_param_string_allocator[100000]; + + yaml_emitter_t emitter; + yaml_emitter_initialize(&emitter); + + // Reset output buffer + size_t written_size = 0; + yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, &written_size); + + // Set initial events + yaml_event_t event; + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); + if (!yaml_emitter_emit(&emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + } + + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); + if (!yaml_emitter_emit(&emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + } + + if (!yaml_emitter_emit(&emitter, current_event)) + { + ret = RCUTILS_RET_ERROR; + } + + + uint32_t line_num = 0; + // Parse the yaml here till our current map depth less than the depth at which we discovered the nesting + while (*map_depth >= nest_depth) + { + int success = yaml_parser_parse(parser, &event); + + if (0 == success) { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( + "Error parsing a event near line %d", line_num); + ret = RCUTILS_RET_ERROR; + break; + } + + line_num = ((uint32_t)(event.start_mark.line) + 1U); + if (!yaml_emitter_emit(&emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( + "Error emitting structured yaml event near line %d", line_num); + break; + } + + switch (event.type) + { + case YAML_MAPPING_START_EVENT: + (*map_depth)++; + /* code */ + break; + + case YAML_MAPPING_END_EVENT: + (*map_depth)--; + break; + + default: + break; + } + printf("Map depth: %lu\n", *map_depth); + printf("Nest depth: %lu\n", nest_depth); + + } + + yaml_document_end_event_initialize(&event, 0); + if (!yaml_emitter_emit(&emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + } + + yaml_stream_end_event_initialize(&event); + if (!yaml_emitter_emit(&emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + } + + yaml_emitter_delete(&emitter); + printf("OUT_STRING:\n"); + printf("%s\n", nested_param_string_allocator); + + // Clear the buffer for the next run + memset((void*) nested_param_string_allocator, 0U, written_size); + return ret; +} + + + /// /// Get events from parsing a parameter YAML file and process them /// @@ -756,6 +862,7 @@ rcutils_ret_t parse_file_events( { int32_t done_parsing = 0; bool is_key = true; + bool is_key_value_pair_found = true; bool is_seq = false; uint32_t line_num = 0; data_types_t seq_data_type = DATA_TYPE_UNKNOWN; @@ -794,6 +901,10 @@ rcutils_ret_t parse_file_events( { /// Need to toggle between key and value at params level if (is_key) { + // If we're at the parameter level, set this flag to denote a value for the key has not been found yet + if (map_level == MAP_PARAMS_LVL) { + is_key_value_pair_found = false; + } ret = parse_key( event, &map_level, &is_new_map, &node_idx, ¶meter_idx, ns_tracker, params_st); if (RCUTILS_RET_OK != ret) { @@ -821,6 +932,8 @@ rcutils_ret_t parse_file_events( return RCUTILS_RET_ERROR; } ret = parse_value(event, is_seq, node_idx, parameter_idx, &seq_data_type, params_st); + is_key_value_pair_found = true; + if (RCUTILS_RET_OK != ret) { break; } @@ -860,6 +973,17 @@ rcutils_ret_t parse_file_events( { is_new_map = false; } + // If we're at the param level + if (map_level == MAP_PARAMS_LVL) { + // If a value has not been found for the previous key, and we get a new mapping event, + // In theory, this means we have a nested yaml struct + if (is_key_value_pair_found == false) { + printf("Nested key at line %u with map depth %u\n", line_num, map_depth); + write_structured_parameter_to_string(parser, &event, &map_depth, ¶meter_idx, params_st); + is_key_value_pair_found = true; + is_key = true; + } + } break; case YAML_MAPPING_END_EVENT: if (MAP_PARAMS_LVL == map_level) { From f9a58d25e0b38a7150fdec2ee17542abc70586c2 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 23 Jul 2025 09:59:15 -0700 Subject: [PATCH 02/18] chore: Adjust `write_structured_parameter` args Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 3 ++- rcl_yaml_param_parser/src/parse.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 465ef0ad6..5c65900fd 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -55,7 +55,8 @@ rcutils_ret_t write_structured_parameter_to_string( yaml_parser_t * parser, yaml_event_t * current_event, uint32_t * map_depth, - size_t * parameter_index, + const size_t node_index, + const size_t parameter_index, rcl_params_t * params_st); RCL_YAML_PARAM_PARSER_PUBLIC diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index d7e33577d..8e7b25603 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -750,7 +750,8 @@ rcutils_ret_t write_structured_parameter_to_string( yaml_parser_t * parser, yaml_event_t * current_event, uint32_t * map_depth, - size_t * parameter_index, + const size_t node_index, + const size_t parameter_index, rcl_params_t * params_st) { rcutils_ret_t ret; From 9dc0ca6635e33ad0bddcc76239a6c95ec67ff086 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 23 Jul 2025 09:59:48 -0700 Subject: [PATCH 03/18] chore: Add yaml type Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h b/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h index e0e4b5f1c..5ff4b9109 100644 --- a/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h +++ b/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h @@ -76,6 +76,7 @@ typedef struct rcl_variant_s int64_t * integer_value; ///< If integer, gets stored here double * double_value; ///< If double, gets stored here char * string_value; ///< If string, gets stored here + char * yaml_value; //< If structured YAML, gets stored here -> Is this right? rcl_byte_array_t * byte_array_value; ///< If array of bytes rcl_bool_array_t * bool_array_value; ///< If array of bool's rcl_int64_array_t * integer_array_value; ///< If array of integers From 5a91f64657338c434566d6f155df16cceabd6345 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 23 Jul 2025 10:01:10 -0700 Subject: [PATCH 04/18] chore: Add allocator and allocations to `write_structured_parameter_to_string` Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 8e7b25603..1bd026d8e 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -757,6 +757,7 @@ rcutils_ret_t write_structured_parameter_to_string( rcutils_ret_t ret; size_t nest_depth = *map_depth; + rcutils_allocator_t allocator = params_st->allocator; //TODO: Move string length to a macro size_t max_string_length = 100000; @@ -821,6 +822,11 @@ rcutils_ret_t write_structured_parameter_to_string( case YAML_MAPPING_END_EVENT: (*map_depth)--; break; + RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); + + rcutils_allocator_t allocator = params_st->allocator; + RCUTILS_CHECK_ALLOCATOR_WITH_MSG( + &allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT); default: break; @@ -846,6 +852,16 @@ rcutils_ret_t write_structured_parameter_to_string( printf("OUT_STRING:\n"); printf("%s\n", nested_param_string_allocator); + char* copied_yaml = rcutils_strdup(nested_param_string_allocator, allocator); + + rcl_variant_t * param_value = &(params_st->params[node_index].parameter_values[parameter_index]); + + if (param_value->yaml_value != NULL) + { + // Overwriting, deallocate original + allocator.deallocate(param_value->yaml_value, allocator.state); + } + param_value->string_value = (char *) copied_yaml; // Clear the buffer for the next run memset((void*) nested_param_string_allocator, 0U, written_size); return ret; From 88fa00f1418f65e152281afe068f98de208e18f4 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Sat, 2 Aug 2025 16:21:38 -0700 Subject: [PATCH 05/18] chore: Clean up `parse.c` a bit. Other refactors still pending (see TODOs) Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 34 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 1bd026d8e..458769963 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -274,6 +274,7 @@ rcutils_ret_t parse_value( return RCUTILS_RET_ERROR; } + // TODO (karahul209@gmail.com): Combine this with the parameter allocation part of `write_structured_parameter_to_string` and put everything in a seperate function rcutils_ret_t ret = RCUTILS_RET_OK; switch (val_type) { case DATA_TYPE_UNKNOWN: @@ -754,14 +755,19 @@ rcutils_ret_t write_structured_parameter_to_string( const size_t parameter_index, rcl_params_t * params_st) { - rcutils_ret_t ret; + //TODO (karahul209@gmail.com): Add RCLUTILS null pointer checks to all pointers in function params + rcutils_ret_t ret = RCUTILS_RET_OK; + RCUTILS_CHECK_ARGUMENT_FOR_NULL(parser, RCUTILS_RET_INVALID_ARGUMENT); + RCUTILS_CHECK_ARGUMENT_FOR_NULL(current_event, RCUTILS_RET_INVALID_ARGUMENT); + RCUTILS_CHECK_ARGUMENT_FOR_NULL(map_depth, RCUTILS_RET_INVALID_ARGUMENT); + RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); size_t nest_depth = *map_depth; rcutils_allocator_t allocator = params_st->allocator; - //TODO: Move string length to a macro + //TODO (karahul209@gmail.com): Move string length to a macro size_t max_string_length = 100000; - static unsigned char nested_param_string_allocator[100000]; + unsigned char nested_param_string_allocator[100000]; yaml_emitter_t emitter; yaml_emitter_initialize(&emitter); @@ -831,8 +837,6 @@ rcutils_ret_t write_structured_parameter_to_string( default: break; } - printf("Map depth: %lu\n", *map_depth); - printf("Nest depth: %lu\n", nest_depth); } @@ -849,10 +853,10 @@ rcutils_ret_t write_structured_parameter_to_string( } yaml_emitter_delete(&emitter); - printf("OUT_STRING:\n"); - printf("%s\n", nested_param_string_allocator); - char* copied_yaml = rcutils_strdup(nested_param_string_allocator, allocator); + // TODO (karahul209@gmail.com): Combine this with the parameter allocation part of `parse_value` and put everything in a seperate function + char* copied_yaml = rcutils_strndup((char *)nested_param_string_allocator, written_size, allocator); + RCUTILS_CHECK_ARGUMENT_FOR_NULL(copied_yaml, RCUTILS_RET_BAD_ALLOC); rcl_variant_t * param_value = &(params_st->params[node_index].parameter_values[parameter_index]); @@ -861,7 +865,7 @@ rcutils_ret_t write_structured_parameter_to_string( // Overwriting, deallocate original allocator.deallocate(param_value->yaml_value, allocator.state); } - param_value->string_value = (char *) copied_yaml; + param_value->yaml_value = copied_yaml; // Clear the buffer for the next run memset((void*) nested_param_string_allocator, 0U, written_size); return ret; @@ -990,13 +994,19 @@ rcutils_ret_t parse_file_events( { is_new_map = false; } - // If we're at the param level + // Parsing nested (structured) YAML parameters + // If we're at the param level inside the YAML if (map_level == MAP_PARAMS_LVL) { // If a value has not been found for the previous key, and we get a new mapping event, // In theory, this means we have a nested yaml struct if (is_key_value_pair_found == false) { - printf("Nested key at line %u with map depth %u\n", line_num, map_depth); - write_structured_parameter_to_string(parser, &event, &map_depth, ¶meter_idx, params_st); + // printf("Nested key at line %u with map depth %u\n", line_num, map_depth); + ret = write_structured_parameter_to_string(parser, &event, &map_depth, node_idx, parameter_idx, params_st); + if (RCUTILS_RET_OK != ret) { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( + "Internal error while parsing structured yaml parameter at line %d\n", line_num); + break; + } is_key_value_pair_found = true; is_key = true; } From 663eb4e46803a161d4101dacaf81391c61fd45fc Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Sat, 2 Aug 2025 16:22:50 -0700 Subject: [PATCH 06/18] chore: Add copy and deallocation operations for the YAML field of `rcl_variant_t` Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/yaml_variant.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rcl_yaml_param_parser/src/yaml_variant.c b/rcl_yaml_param_parser/src/yaml_variant.c index d1db3cab6..9be0f3cc3 100644 --- a/rcl_yaml_param_parser/src/yaml_variant.c +++ b/rcl_yaml_param_parser/src/yaml_variant.c @@ -80,6 +80,9 @@ void rcl_yaml_variant_fini( } else if (NULL != param_var->string_value) { allocator.deallocate(param_var->string_value, allocator.state); param_var->string_value = NULL; + } else if (NULL != param_var->yaml_value) { + allocator.deallocate(param_var->yaml_value, allocator.state); + param_var->yaml_value = NULL; } else if (NULL != param_var->bool_array_value) { if (NULL != param_var->bool_array_value->values) { allocator.deallocate(param_var->bool_array_value->values, allocator.state); @@ -132,6 +135,13 @@ bool rcl_yaml_variant_copy( RCUTILS_SAFE_FWRITE_TO_STDERR("Error allocating variant mem when copying string_value\n"); return false; } + } else if (NULL != param_var->yaml_value) { + out_param_var->yaml_value = + rcutils_strdup(param_var->yaml_value, allocator); + if (NULL == out_param_var->yaml_value) { + RCUTILS_SAFE_FWRITE_TO_STDERR("Error allocating variant mem when copying yaml_value\n"); + return false; + } } else if (NULL != param_var->bool_array_value) { RCL_YAML_VARIANT_COPY_ARRAY_VALUE( out_param_var->bool_array_value, param_var->bool_array_value, allocator, From 446b4432a12476662627be2e02f98ab7b4c26c2e Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Sat, 2 Aug 2025 16:23:57 -0700 Subject: [PATCH 07/18] chore: Remove redundant `memset` Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 458769963..79ad55299 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -866,8 +866,6 @@ rcutils_ret_t write_structured_parameter_to_string( allocator.deallocate(param_value->yaml_value, allocator.state); } param_value->yaml_value = copied_yaml; - // Clear the buffer for the next run - memset((void*) nested_param_string_allocator, 0U, written_size); return ret; } From 786a71198221fdbbb9ac076bbb765011e47be511 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Sun, 3 Aug 2025 10:22:11 -0700 Subject: [PATCH 08/18] chore: Refactor TODOs Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 79ad55299..c914aaf3f 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -230,6 +230,7 @@ rcutils_ret_t parse_value( data_types_t * seq_data_type, rcl_params_t * params_st) { + // printf("parse_value:: Parsing value!"); RCUTILS_CHECK_ARGUMENT_FOR_NULL(seq_data_type, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); @@ -274,7 +275,7 @@ rcutils_ret_t parse_value( return RCUTILS_RET_ERROR; } - // TODO (karahul209@gmail.com): Combine this with the parameter allocation part of `write_structured_parameter_to_string` and put everything in a seperate function + // rahul-k-a: TODO Combine this with the parameter allocation part of `write_structured_parameter_to_string` and put everything in a seperate function rcutils_ret_t ret = RCUTILS_RET_OK; switch (val_type) { case DATA_TYPE_UNKNOWN: @@ -603,6 +604,7 @@ rcutils_ret_t parse_key( namespace_tracker_t * ns_tracker, rcl_params_t * params_st) { + // printf("parse_key:: Entering!\n"); RCUTILS_CHECK_ARGUMENT_FOR_NULL(map_level, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); rcutils_allocator_t allocator = params_st->allocator; @@ -612,6 +614,7 @@ rcutils_ret_t parse_key( const size_t val_size = event.data.scalar.length; const char * value = (char *)event.data.scalar.value; const uint32_t line_num = ((uint32_t)(event.start_mark.line) + 1U); + // printf("parse_key:: Key is %s with map level %u\n", value, *map_level); RCUTILS_CHECK_FOR_NULL_WITH_MSG( value, "event argument has no value", return RCUTILS_RET_INVALID_ARGUMENT); @@ -624,12 +627,14 @@ rcutils_ret_t parse_key( rcutils_ret_t ret = RCUTILS_RET_OK; switch (*map_level) { case MAP_UNINIT_LVL: + // printf("Event: MAP_UNINIT_LVL\n"); RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Unintialized map level at line %d", line_num); ret = RCUTILS_RET_ERROR; break; case MAP_NODE_NAME_LVL: { + // printf("Event: MAP_NODE_NAME_LVL\n"); /// Till we get PARAMS_KEY, keep adding to node namespace if (0 != strncmp(PARAMS_KEY, value, strlen(PARAMS_KEY))) { ret = add_name_to_ns(ns_tracker, value, NS_TYPE_NODE, allocator); @@ -678,6 +683,7 @@ rcutils_ret_t parse_key( break; case MAP_PARAMS_LVL: { + // printf("Event: MAP_PARAMS_LVL\n"); char * parameter_ns = NULL; char * param_name = NULL; @@ -755,7 +761,6 @@ rcutils_ret_t write_structured_parameter_to_string( const size_t parameter_index, rcl_params_t * params_st) { - //TODO (karahul209@gmail.com): Add RCLUTILS null pointer checks to all pointers in function params rcutils_ret_t ret = RCUTILS_RET_OK; RCUTILS_CHECK_ARGUMENT_FOR_NULL(parser, RCUTILS_RET_INVALID_ARGUMENT); @@ -765,7 +770,7 @@ rcutils_ret_t write_structured_parameter_to_string( size_t nest_depth = *map_depth; rcutils_allocator_t allocator = params_st->allocator; - //TODO (karahul209@gmail.com): Move string length to a macro + //rahul-k-a: TODO Move string length to a macro size_t max_string_length = 100000; unsigned char nested_param_string_allocator[100000]; @@ -854,7 +859,7 @@ rcutils_ret_t write_structured_parameter_to_string( yaml_emitter_delete(&emitter); - // TODO (karahul209@gmail.com): Combine this with the parameter allocation part of `parse_value` and put everything in a seperate function + // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function char* copied_yaml = rcutils_strndup((char *)nested_param_string_allocator, written_size, allocator); RCUTILS_CHECK_ARGUMENT_FOR_NULL(copied_yaml, RCUTILS_RET_BAD_ALLOC); @@ -911,6 +916,12 @@ rcutils_ret_t parse_file_events( break; } line_num = ((uint32_t)(event.start_mark.line) + 1U); + // printf("\n\n"); + // printf("parse_file_events:: At start of while loop, map level is %u\n", map_level); + // printf("parse_file_events:: At start of while loop, map depth is %u\n", map_depth); + // printf("parse_file_events:: At start of while loop, map line is %u\n", line_num); + // printf("parse_file_events:: Number of node namespaces is %u\n\n", ns_tracker->num_node_ns); + switch (event.type) { case YAML_STREAM_END_EVENT: done_parsing = 1; @@ -963,6 +974,8 @@ rcutils_ret_t parse_file_events( } break; case YAML_SEQUENCE_START_EVENT: + // printf("YAML_SEQUENCE_START_EVENT!\n"); + if (is_key) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Sequences cannot be key at line %d", line_num); @@ -979,10 +992,12 @@ rcutils_ret_t parse_file_events( seq_data_type = DATA_TYPE_UNKNOWN; break; case YAML_SEQUENCE_END_EVENT: + // printf("YAML_SEQUENCE_END_EVENT!\n"); is_seq = false; is_key = true; break; case YAML_MAPPING_START_EVENT: + // printf("YAML_MAPPING_START_EVENT!\n"); map_depth++; is_new_map = true; is_key = true; @@ -1021,6 +1036,7 @@ rcutils_ret_t parse_file_events( break; } } else { + // printf("parse_file_events 2 ::Map level is %u\n", map_level); map_level--; } } else { @@ -1044,12 +1060,16 @@ rcutils_ret_t parse_file_events( ret = RCUTILS_RET_ERROR; break; case YAML_STREAM_START_EVENT: + // printf("STREAm_START_EVENT!\n"); break; case YAML_DOCUMENT_START_EVENT: + // printf("YAML_DOCUMENT_START_EVENT!\n"); break; case YAML_DOCUMENT_END_EVENT: + // printf("YAML_DOCUMENT_END_EVENT!\n"); break; case YAML_NO_EVENT: + // printf("YAML_NO_EVENT!\n"); RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Received an empty event at line %d", line_num); ret = RCUTILS_RET_ERROR; From cecd979635218ca22ce5d935f4a97d7cb4265b8e Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 15:58:09 -0400 Subject: [PATCH 09/18] Add function to copy and emit events Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 5 ++ rcl_yaml_param_parser/src/parse.c | 69 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 5c65900fd..1dc925e5e 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -77,6 +77,11 @@ rcutils_ret_t parse_file_events( namespace_tracker_t * ns_tracker, rcl_params_t * params_st); +rcutils_ret_t write_event_to_emitter( + yaml_emitter_t * emitter, + yaml_event_t * event +); + RCL_YAML_PARAM_PARSER_PUBLIC RCUTILS_WARN_UNUSED rcutils_ret_t parse_value_events( diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index c914aaf3f..2def00516 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -592,6 +592,75 @@ _validate_name(const char * name, rcutils_allocator_t allocator) return ret; } +/// +/// Makes a copy of an event and writes the copy to the emitter +/// +rcutils_ret_t write_event_to_emitter( + yaml_emitter_t * emitter, + yaml_event_t * event +) +{ + + RCUTILS_CHECK_ARGUMENT_FOR_NULL(emitter, RCUTILS_RET_INVALID_ARGUMENT); + RCUTILS_CHECK_ARGUMENT_FOR_NULL(event, RCUTILS_RET_INVALID_ARGUMENT); + rcutils_ret_t ret = RCUTILS_RET_OK; + // The emitter deletes the event after writing + // So we need to make a copy of it and pass the copy to the emitter + yaml_event_t event_copy; + int success; + switch (event->type) + { + /** A SCALAR event. */ + case YAML_SCALAR_EVENT: + { + success = yaml_scalar_event_initialize(&event_copy, event->data.scalar.anchor,event->data.scalar.tag, event->data.scalar.value, event->data.scalar.length, event->data.scalar.plain_implicit, event->data.scalar.quoted_implicit, event->data.scalar.style ); + break; + } + + /** A SEQUENCE-START event. */ + case YAML_SEQUENCE_START_EVENT: + { + success = yaml_sequence_start_event_initialize(&event_copy, event->data.sequence_start.anchor,event->data.sequence_start.tag, event->data.sequence_start.implicit, event->data.sequence_start.style ); + break; + } + /** A SEQUENCE-END event. */ + case YAML_SEQUENCE_END_EVENT: + { + success = yaml_sequence_end_event_initialize(&event_copy); + break; + } + + /** A MAPPING-START event. */ + case YAML_MAPPING_START_EVENT: + { + success = yaml_mapping_start_event_initialize(&event_copy, event->data.mapping_start.anchor, event->data.mapping_start.tag, event->data.mapping_start.implicit, event->data.mapping_start.style); + break; + } + /** A MAPPING-END event. */ + case YAML_MAPPING_END_EVENT: + { + success = yaml_mapping_end_event_initialize(&event_copy); + break; + } + default: + { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unexpected YAML token of type %d", (int) event->type); + ret = RCUTILS_RET_ERROR; + break; + } + } + + if (success == 0) + { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unable to duplicate YAML token of type %d", (int) event->type); + return RCUTILS_RET_ERROR; + } + yaml_emitter_emit(emitter, &event_copy); + return ret; + +} + + /// /// Parse the key part of the pair /// From 7d5ca80468a10a064d4074bff16b44903e79ab40 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 16:07:05 -0400 Subject: [PATCH 10/18] chore: Remove unused printf Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 2def00516..9afce552a 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -696,14 +696,12 @@ rcutils_ret_t parse_key( rcutils_ret_t ret = RCUTILS_RET_OK; switch (*map_level) { case MAP_UNINIT_LVL: - // printf("Event: MAP_UNINIT_LVL\n"); RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Unintialized map level at line %d", line_num); ret = RCUTILS_RET_ERROR; break; case MAP_NODE_NAME_LVL: { - // printf("Event: MAP_NODE_NAME_LVL\n"); /// Till we get PARAMS_KEY, keep adding to node namespace if (0 != strncmp(PARAMS_KEY, value, strlen(PARAMS_KEY))) { ret = add_name_to_ns(ns_tracker, value, NS_TYPE_NODE, allocator); @@ -789,7 +787,6 @@ rcutils_ret_t parse_key( 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); @@ -1105,7 +1102,6 @@ rcutils_ret_t parse_file_events( break; } } else { - // printf("parse_file_events 2 ::Map level is %u\n", map_level); map_level--; } } else { @@ -1129,16 +1125,12 @@ rcutils_ret_t parse_file_events( ret = RCUTILS_RET_ERROR; break; case YAML_STREAM_START_EVENT: - // printf("STREAm_START_EVENT!\n"); break; case YAML_DOCUMENT_START_EVENT: - // printf("YAML_DOCUMENT_START_EVENT!\n"); break; case YAML_DOCUMENT_END_EVENT: - // printf("YAML_DOCUMENT_END_EVENT!\n"); break; case YAML_NO_EVENT: - // printf("YAML_NO_EVENT!\n"); RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Received an empty event at line %d", line_num); ret = RCUTILS_RET_ERROR; From 88612f002a0319a18a59465d8b56941b5d8ebc21 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 20:00:12 -0400 Subject: [PATCH 11/18] chore: Add new functions to begin and end string Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 10 +++ rcl_yaml_param_parser/src/parse.c | 91 ++++---------------------- 2 files changed, 24 insertions(+), 77 deletions(-) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 1dc925e5e..4ab923be2 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -49,6 +49,16 @@ rcutils_ret_t parse_value( data_types_t * seq_data_type, rcl_params_t * params_st); +RCL_YAML_PARAM_PARSER_PUBLIC +RCUTILS_WARN_UNUSED +rcutils_ret_t initialize_emitter_string( + yaml_emitter_t * emitter); + +RCL_YAML_PARAM_PARSER_PUBLIC +RCUTILS_WARN_UNUSED +rcutils_ret_t end_emitter_string( + yaml_emitter_t * emitter); + RCL_YAML_PARAM_PARSER_PUBLIC RCUTILS_WARN_UNUSED rcutils_ret_t write_structured_parameter_to_string( diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 9afce552a..af6027807 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -230,7 +230,6 @@ rcutils_ret_t parse_value( data_types_t * seq_data_type, rcl_params_t * params_st) { - // printf("parse_value:: Parsing value!"); RCUTILS_CHECK_ARGUMENT_FOR_NULL(seq_data_type, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); @@ -819,111 +818,49 @@ rcutils_ret_t parse_key( return ret; } -rcutils_ret_t write_structured_parameter_to_string( - yaml_parser_t * parser, - yaml_event_t * current_event, - uint32_t * map_depth, - const size_t node_index, - const size_t parameter_index, - rcl_params_t * params_st) +rcutils_ret_t initialize_emitter_string( + yaml_emitter_t * emitter) { rcutils_ret_t ret = RCUTILS_RET_OK; - RCUTILS_CHECK_ARGUMENT_FOR_NULL(parser, RCUTILS_RET_INVALID_ARGUMENT); - RCUTILS_CHECK_ARGUMENT_FOR_NULL(current_event, RCUTILS_RET_INVALID_ARGUMENT); - RCUTILS_CHECK_ARGUMENT_FOR_NULL(map_depth, RCUTILS_RET_INVALID_ARGUMENT); - RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); - size_t nest_depth = *map_depth; - rcutils_allocator_t allocator = params_st->allocator; - - //rahul-k-a: TODO Move string length to a macro - size_t max_string_length = 100000; - unsigned char nested_param_string_allocator[100000]; - - yaml_emitter_t emitter; - yaml_emitter_initialize(&emitter); - - // Reset output buffer - size_t written_size = 0; - yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, &written_size); - // Set initial events yaml_event_t event; yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); - if (!yaml_emitter_emit(&emitter, &event)) + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); - if (!yaml_emitter_emit(&emitter, &event)) + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } - if (!yaml_emitter_emit(&emitter, current_event)) - { - ret = RCUTILS_RET_ERROR; + return ret; } - - uint32_t line_num = 0; - // Parse the yaml here till our current map depth less than the depth at which we discovered the nesting - while (*map_depth >= nest_depth) - { - int success = yaml_parser_parse(parser, &event); - - if (0 == success) { - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( - "Error parsing a event near line %d", line_num); - ret = RCUTILS_RET_ERROR; - break; - } - - line_num = ((uint32_t)(event.start_mark.line) + 1U); - if (!yaml_emitter_emit(&emitter, &event)) +rcutils_ret_t end_emitter_string( + yaml_emitter_t * emitter) { - ret = RCUTILS_RET_ERROR; - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( - "Error emitting structured yaml event near line %d", line_num); - break; - } - - switch (event.type) - { - case YAML_MAPPING_START_EVENT: - (*map_depth)++; - /* code */ - break; - - case YAML_MAPPING_END_EVENT: - (*map_depth)--; - break; - RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); - - rcutils_allocator_t allocator = params_st->allocator; - RCUTILS_CHECK_ALLOCATOR_WITH_MSG( - &allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT); - - default: - break; - } - - } + rcutils_ret_t ret = RCUTILS_RET_OK; + // Set initial events + yaml_event_t event; yaml_document_end_event_initialize(&event, 0); - if (!yaml_emitter_emit(&emitter, &event)) + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } yaml_stream_end_event_initialize(&event); - if (!yaml_emitter_emit(&emitter, &event)) + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } - yaml_emitter_delete(&emitter); + return ret; +} // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function char* copied_yaml = rcutils_strndup((char *)nested_param_string_allocator, written_size, allocator); From b15a3a5a1f39f7cd53599216e3ca6d13eaf90397 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 20:14:59 -0400 Subject: [PATCH 12/18] chore: Add new parameters to parser functions Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 8 ++++++-- rcl_yaml_param_parser/src/parse.c | 7 ++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 4ab923be2..24289925a 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -63,8 +63,8 @@ RCL_YAML_PARAM_PARSER_PUBLIC RCUTILS_WARN_UNUSED rcutils_ret_t write_structured_parameter_to_string( yaml_parser_t * parser, - yaml_event_t * current_event, - uint32_t * map_depth, + char * yaml_string_buffer, + size_t * written_size, const size_t node_index, const size_t parameter_index, rcl_params_t * params_st); @@ -75,6 +75,7 @@ rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, + bool * dont_overwrite_yaml_key, size_t * node_idx, size_t * parameter_idx, namespace_tracker_t * ns_tracker, @@ -84,6 +85,9 @@ RCL_YAML_PARAM_PARSER_PUBLIC RCUTILS_WARN_UNUSED rcutils_ret_t parse_file_events( yaml_parser_t * parser, + yaml_emitter_t * emitter, + char * emitter_string_buffer, + size_t * emitter_written_bytes, namespace_tracker_t * ns_tracker, rcl_params_t * params_st); diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index af6027807..08b47bc39 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -667,12 +667,12 @@ rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, + bool * dont_overwrite_yaml_key, size_t * node_idx, size_t * parameter_idx, namespace_tracker_t * ns_tracker, rcl_params_t * params_st) { - // printf("parse_key:: Entering!\n"); RCUTILS_CHECK_ARGUMENT_FOR_NULL(map_level, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); rcutils_allocator_t allocator = params_st->allocator; @@ -682,7 +682,6 @@ rcutils_ret_t parse_key( const size_t val_size = event.data.scalar.length; const char * value = (char *)event.data.scalar.value; const uint32_t line_num = ((uint32_t)(event.start_mark.line) + 1U); - // printf("parse_key:: Key is %s with map level %u\n", value, *map_level); RCUTILS_CHECK_FOR_NULL_WITH_MSG( value, "event argument has no value", return RCUTILS_RET_INVALID_ARGUMENT); @@ -749,7 +748,6 @@ rcutils_ret_t parse_key( break; case MAP_PARAMS_LVL: { - // printf("Event: MAP_PARAMS_LVL\n"); char * parameter_ns = NULL; char * param_name = NULL; @@ -884,6 +882,9 @@ rcutils_ret_t end_emitter_string( /// rcutils_ret_t parse_file_events( yaml_parser_t * parser, + yaml_emitter_t * emitter, + char * emitter_string_buffer, + size_t * emitter_written_bytes, namespace_tracker_t * ns_tracker, rcl_params_t * params_st) { From 7ca623f9b0dd511c0f8aa0c91adb8046b521ff9b Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 20:15:44 -0400 Subject: [PATCH 13/18] chore: Add emitter and pass it as part of `parser.c` Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parser.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/rcl_yaml_param_parser/src/parser.c b/rcl_yaml_param_parser/src/parser.c index 988e68df1..7d8b6f801 100644 --- a/rcl_yaml_param_parser/src/parser.c +++ b/rcl_yaml_param_parser/src/parser.c @@ -265,6 +265,21 @@ bool rcl_parse_yaml_file( return false; } + + + // Emitter for nested parameters + yaml_emitter_t emitter; + success = yaml_emitter_initialize(&emitter); + if (0 == success) { + RCUTILS_SET_ERROR_MSG("Could not initialize the emitter"); + } + + size_t max_string_length = 100000; + volatile size_t written_size = 0; + unsigned char nested_param_string_allocator[100000]; + yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, &written_size); + + FILE * yaml_file = fopen(file_path, "r"); if (NULL == yaml_file) { yaml_parser_delete(&parser); @@ -276,11 +291,12 @@ bool rcl_parse_yaml_file( namespace_tracker_t ns_tracker; memset(&ns_tracker, 0, sizeof(namespace_tracker_t)); - rcutils_ret_t ret = parse_file_events(&parser, &ns_tracker, params_st); + rcutils_ret_t ret = parse_file_events(&parser, &emitter, nested_param_string_allocator, &written_size, &ns_tracker, params_st); fclose(yaml_file); yaml_parser_delete(&parser); + yaml_emitter_delete(&emitter); rcutils_allocator_t allocator = params_st->allocator; if (NULL != ns_tracker.node_ns) { From 610e56aa15f9a969374d7cdf8f59a52e91e7e40c Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 20:22:29 -0400 Subject: [PATCH 14/18] Add structured yaml parameter parsing using counter method Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 102 ++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 26 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 08b47bc39..0ba871800 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -780,7 +780,13 @@ rcutils_ret_t parse_key( break; } } else { - ret = find_parameter(*node_idx, parameter_ns, params_st, parameter_idx); + if (*dont_overwrite_yaml_key == true) + { + *dont_overwrite_yaml_key = false; + ret = find_parameter(*node_idx, value, params_st, parameter_idx); + }else{ + ret = find_parameter(*node_idx, parameter_ns, params_st, parameter_idx); + } if (ret != RCUTILS_RET_OK) { break; } @@ -836,11 +842,11 @@ rcutils_ret_t initialize_emitter_string( } return ret; - } +} rcutils_ret_t end_emitter_string( yaml_emitter_t * emitter) - { +{ rcutils_ret_t ret = RCUTILS_RET_OK; // Set initial events @@ -860,8 +866,22 @@ rcutils_ret_t end_emitter_string( return ret; } +// TODO: Replace the counter method with indentation method +rcutils_ret_t write_structured_parameter_to_string( + yaml_parser_t * parser, + char * yaml_string_buffer, + size_t * written_size, + const size_t node_index, + const size_t parameter_index, + rcl_params_t * params_st) +{ + rcutils_ret_t ret = RCUTILS_RET_OK; + rcutils_allocator_t allocator = params_st->allocator; + rcl_node_params_t * node_param_st = &(params_st->params[node_index]); + const char* parname = node_param_st->parameter_names[parameter_index]; + // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function - char* copied_yaml = rcutils_strndup((char *)nested_param_string_allocator, written_size, allocator); + char* copied_yaml = rcutils_strndup( yaml_string_buffer, *written_size, allocator); RCUTILS_CHECK_ARGUMENT_FOR_NULL(copied_yaml, RCUTILS_RET_BAD_ALLOC); rcl_variant_t * param_value = &(params_st->params[node_index].parameter_values[parameter_index]); @@ -898,6 +918,16 @@ rcutils_ret_t parse_file_events( uint32_t map_depth = 0U; bool is_new_map = false; + *emitter_written_bytes = 0; + int event_start_end_counter = -1; + bool is_writing_nested_yaml = false; + size_t nested_param_idx = 0; + rcutils_ret_t ret = RCUTILS_RET_OK; + bool dont_overwrite_yaml_key = false; + + + + RCUTILS_CHECK_ARGUMENT_FOR_NULL(parser, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); rcutils_allocator_t allocator = params_st->allocator; @@ -907,7 +937,6 @@ rcutils_ret_t parse_file_events( 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) { break; @@ -919,12 +948,15 @@ rcutils_ret_t parse_file_events( ret = RCUTILS_RET_ERROR; break; } + line_num = ((uint32_t)(event.start_mark.line) + 1U); - // printf("\n\n"); - // printf("parse_file_events:: At start of while loop, map level is %u\n", map_level); - // printf("parse_file_events:: At start of while loop, map depth is %u\n", map_depth); - // printf("parse_file_events:: At start of while loop, map line is %u\n", line_num); - // printf("parse_file_events:: Number of node namespaces is %u\n\n", ns_tracker->num_node_ns); + + if (is_writing_nested_yaml) { + if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) { + ret = RCUTILS_RET_ERROR; + break; + } + } switch (event.type) { case YAML_STREAM_END_EVENT: @@ -939,8 +971,12 @@ rcutils_ret_t parse_file_events( if (map_level == MAP_PARAMS_LVL) { is_key_value_pair_found = false; } + if (is_writing_nested_yaml && (event_start_end_counter == 0)) + { + dont_overwrite_yaml_key = true; + } ret = parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, ns_tracker, params_st); + event, &map_level, &is_new_map, &dont_overwrite_yaml_key,&node_idx, ¶meter_idx, ns_tracker, params_st); if (RCUTILS_RET_OK != ret) { break; } @@ -978,8 +1014,6 @@ rcutils_ret_t parse_file_events( } break; case YAML_SEQUENCE_START_EVENT: - // printf("YAML_SEQUENCE_START_EVENT!\n"); - if (is_key) { RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( "Sequences cannot be key at line %d", line_num); @@ -996,12 +1030,14 @@ rcutils_ret_t parse_file_events( seq_data_type = DATA_TYPE_UNKNOWN; break; case YAML_SEQUENCE_END_EVENT: - // printf("YAML_SEQUENCE_END_EVENT!\n"); is_seq = false; is_key = true; break; case YAML_MAPPING_START_EVENT: - // printf("YAML_MAPPING_START_EVENT!\n"); + if (is_writing_nested_yaml) + { + event_start_end_counter++; + } map_depth++; is_new_map = true; is_key = true; @@ -1013,23 +1049,37 @@ rcutils_ret_t parse_file_events( } // Parsing nested (structured) YAML parameters // If we're at the param level inside the YAML - if (map_level == MAP_PARAMS_LVL) { // If a value has not been found for the previous key, and we get a new mapping event, // In theory, this means we have a nested yaml struct - if (is_key_value_pair_found == false) { - // printf("Nested key at line %u with map depth %u\n", line_num, map_depth); - ret = write_structured_parameter_to_string(parser, &event, &map_depth, node_idx, parameter_idx, params_st); - if (RCUTILS_RET_OK != ret) { - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( - "Internal error while parsing structured yaml parameter at line %d\n", line_num); - break; - } - is_key_value_pair_found = true; - is_key = true; + if (is_key_value_pair_found == false && is_writing_nested_yaml == false) { + is_writing_nested_yaml = true; + event_start_end_counter++; + nested_param_idx = parameter_idx; + initialize_emitter_string(emitter); + if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) + { + ret = RCUTILS_RET_ERROR; + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Error adding line %d to structured yaml parameter", line_num); } } break; case YAML_MAPPING_END_EVENT: + if (is_writing_nested_yaml) + { + event_start_end_counter--; + if (event_start_end_counter < 0) + { + end_emitter_string(emitter); + write_structured_parameter_to_string(parser, emitter_string_buffer, emitter_written_bytes, node_idx, nested_param_idx, params_st); + is_writing_nested_yaml = false; + is_key_value_pair_found = true; + event_start_end_counter = 0; + nested_param_idx = 0; + // Reset byte counter so that we can reuse buffer + *emitter_written_bytes = 0; + event_start_end_counter = -1; + } + } if (MAP_PARAMS_LVL == map_level) { if (ns_tracker->num_parameter_ns > 0U) { /// Remove param namesapce From e945c483ade7cffb23472f97dbf2c73a73b33487 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Wed, 27 Aug 2025 21:09:20 -0400 Subject: [PATCH 15/18] chore: Move to a depth-based structured yaml detection system Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/impl/parse.h | 2 +- rcl_yaml_param_parser/src/parse.c | 80 +++++++++++++------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/rcl_yaml_param_parser/src/impl/parse.h b/rcl_yaml_param_parser/src/impl/parse.h index 24289925a..6948277f6 100644 --- a/rcl_yaml_param_parser/src/impl/parse.h +++ b/rcl_yaml_param_parser/src/impl/parse.h @@ -75,7 +75,7 @@ rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, - bool * dont_overwrite_yaml_key, + bool * overwrite_previous_key, size_t * node_idx, size_t * parameter_idx, namespace_tracker_t * ns_tracker, diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 0ba871800..83f19df34 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -667,7 +667,7 @@ rcutils_ret_t parse_key( const yaml_event_t event, uint32_t * map_level, bool * is_new_map, - bool * dont_overwrite_yaml_key, + bool * overwrite_previous_key, size_t * node_idx, size_t * parameter_idx, namespace_tracker_t * ns_tracker, @@ -780,10 +780,11 @@ rcutils_ret_t parse_key( break; } } else { - if (*dont_overwrite_yaml_key == true) + if (*overwrite_previous_key == false) { - *dont_overwrite_yaml_key = false; + // Handle cases where the code tries to overwrite the yaml parameter name entry ret = find_parameter(*node_idx, value, params_st, parameter_idx); + *overwrite_previous_key = true; }else{ ret = find_parameter(*node_idx, parameter_ns, params_st, parameter_idx); } @@ -877,8 +878,6 @@ rcutils_ret_t write_structured_parameter_to_string( { rcutils_ret_t ret = RCUTILS_RET_OK; rcutils_allocator_t allocator = params_st->allocator; - rcl_node_params_t * node_param_st = &(params_st->params[node_index]); - const char* parname = node_param_st->parameter_names[parameter_index]; // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function char* copied_yaml = rcutils_strndup( yaml_string_buffer, *written_size, allocator); @@ -918,16 +917,13 @@ rcutils_ret_t parse_file_events( uint32_t map_depth = 0U; bool is_new_map = false; + uint32_t structure_detect_depth = 0; *emitter_written_bytes = 0; - int event_start_end_counter = -1; - bool is_writing_nested_yaml = false; - size_t nested_param_idx = 0; + bool is_writing_structured_yaml = false; + size_t structured_yaml_param_idx = 0; rcutils_ret_t ret = RCUTILS_RET_OK; - bool dont_overwrite_yaml_key = false; + bool overwrite_previous_key = true; - - - RCUTILS_CHECK_ARGUMENT_FOR_NULL(parser, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(params_st, RCUTILS_RET_INVALID_ARGUMENT); rcutils_allocator_t allocator = params_st->allocator; @@ -951,7 +947,7 @@ rcutils_ret_t parse_file_events( line_num = ((uint32_t)(event.start_mark.line) + 1U); - if (is_writing_nested_yaml) { + if (is_writing_structured_yaml) { if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) { ret = RCUTILS_RET_ERROR; break; @@ -971,12 +967,15 @@ rcutils_ret_t parse_file_events( if (map_level == MAP_PARAMS_LVL) { is_key_value_pair_found = false; } - if (is_writing_nested_yaml && (event_start_end_counter == 0)) - { - dont_overwrite_yaml_key = true; + // Since the yaml parameter key is also considered as a namespace to all indented children + // We must make sure that the parameter index of the yaml parameter is not overwritten + // By default, if a namespace is detected, then the parameter entry in the param table is replaced by its immediate chile + // This is done for optimization (?) - Rahul-K-A + if (is_writing_structured_yaml && (map_depth == structure_detect_depth) ) { + overwrite_previous_key = false; } ret = parse_key( - event, &map_level, &is_new_map, &dont_overwrite_yaml_key,&node_idx, ¶meter_idx, ns_tracker, params_st); + event, &map_level, &is_new_map, &overwrite_previous_key, &node_idx, ¶meter_idx, ns_tracker, params_st); if (RCUTILS_RET_OK != ret) { break; } @@ -1034,10 +1033,6 @@ rcutils_ret_t parse_file_events( is_key = true; break; case YAML_MAPPING_START_EVENT: - if (is_writing_nested_yaml) - { - event_start_end_counter++; - } map_depth++; is_new_map = true; is_key = true; @@ -1051,10 +1046,10 @@ rcutils_ret_t parse_file_events( // If we're at the param level inside the YAML // If a value has not been found for the previous key, and we get a new mapping event, // In theory, this means we have a nested yaml struct - if (is_key_value_pair_found == false && is_writing_nested_yaml == false) { - is_writing_nested_yaml = true; - event_start_end_counter++; - nested_param_idx = parameter_idx; + if (is_key_value_pair_found == false && is_writing_structured_yaml == false) { + is_writing_structured_yaml = true; + structured_yaml_param_idx = parameter_idx; + structure_detect_depth = map_depth; initialize_emitter_string(emitter); if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) { @@ -1064,22 +1059,6 @@ rcutils_ret_t parse_file_events( } break; case YAML_MAPPING_END_EVENT: - if (is_writing_nested_yaml) - { - event_start_end_counter--; - if (event_start_end_counter < 0) - { - end_emitter_string(emitter); - write_structured_parameter_to_string(parser, emitter_string_buffer, emitter_written_bytes, node_idx, nested_param_idx, params_st); - is_writing_nested_yaml = false; - is_key_value_pair_found = true; - event_start_end_counter = 0; - nested_param_idx = 0; - // Reset byte counter so that we can reuse buffer - *emitter_written_bytes = 0; - event_start_end_counter = -1; - } - } if (MAP_PARAMS_LVL == map_level) { if (ns_tracker->num_parameter_ns > 0U) { /// Remove param namesapce @@ -1106,6 +1085,25 @@ rcutils_ret_t parse_file_events( } } map_depth--; + // Terminate structured yaml parameter if needed + if (is_writing_structured_yaml) + { + if (map_depth < structure_detect_depth) + { + end_emitter_string(emitter); + write_structured_parameter_to_string(parser, emitter_string_buffer, emitter_written_bytes, node_idx, structured_yaml_param_idx, params_st); + is_writing_structured_yaml = false; + is_key_value_pair_found = true; + structure_detect_depth = 0; + structured_yaml_param_idx = 0; + // Reset byte counter so that we can reuse buffer + *emitter_written_bytes = 0; + } + else + { + + } + } break; case YAML_ALIAS_EVENT: RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( From 240e2e89b8b92961e7aed5a433052a092e7fda46 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Thu, 28 Aug 2025 20:28:31 -0400 Subject: [PATCH 16/18] chore: Remove volatile qualifier for written_size Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rcl_yaml_param_parser/src/parser.c b/rcl_yaml_param_parser/src/parser.c index 7d8b6f801..c79845d21 100644 --- a/rcl_yaml_param_parser/src/parser.c +++ b/rcl_yaml_param_parser/src/parser.c @@ -275,7 +275,7 @@ bool rcl_parse_yaml_file( } size_t max_string_length = 100000; - volatile size_t written_size = 0; + size_t written_size = 0; unsigned char nested_param_string_allocator[100000]; yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, &written_size); From 1587c6593a493905e458f5d59437f760f7e90bb8 Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Thu, 28 Aug 2025 20:29:51 -0400 Subject: [PATCH 17/18] chore: Apply `ament_uncrustify` Signed-off-by: Rahul K.A --- rcl_yaml_param_parser/src/parse.c | 116 +++++++++++----------- rcl_yaml_param_parser/src/parser.c | 7 +- rcl_yaml_param_parser/test/test_parse.cpp | 40 ++++++-- 3 files changed, 93 insertions(+), 70 deletions(-) diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 83f19df34..74e26b297 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -607,51 +607,58 @@ rcutils_ret_t write_event_to_emitter( // So we need to make a copy of it and pass the copy to the emitter yaml_event_t event_copy; int success; - switch (event->type) - { + switch (event->type) { /** A SCALAR event. */ case YAML_SCALAR_EVENT: - { - success = yaml_scalar_event_initialize(&event_copy, event->data.scalar.anchor,event->data.scalar.tag, event->data.scalar.value, event->data.scalar.length, event->data.scalar.plain_implicit, event->data.scalar.quoted_implicit, event->data.scalar.style ); - break; - } + { + success = yaml_scalar_event_initialize(&event_copy, event->data.scalar.anchor, + event->data.scalar.tag, event->data.scalar.value, event->data.scalar.length, + event->data.scalar.plain_implicit, event->data.scalar.quoted_implicit, + event->data.scalar.style); + break; + } /** A SEQUENCE-START event. */ case YAML_SEQUENCE_START_EVENT: - { - success = yaml_sequence_start_event_initialize(&event_copy, event->data.sequence_start.anchor,event->data.sequence_start.tag, event->data.sequence_start.implicit, event->data.sequence_start.style ); - break; - } + { + success = yaml_sequence_start_event_initialize(&event_copy, + event->data.sequence_start.anchor, event->data.sequence_start.tag, + event->data.sequence_start.implicit, event->data.sequence_start.style); + break; + } /** A SEQUENCE-END event. */ case YAML_SEQUENCE_END_EVENT: - { - success = yaml_sequence_end_event_initialize(&event_copy); - break; - } + { + success = yaml_sequence_end_event_initialize(&event_copy); + break; + } /** A MAPPING-START event. */ case YAML_MAPPING_START_EVENT: - { - success = yaml_mapping_start_event_initialize(&event_copy, event->data.mapping_start.anchor, event->data.mapping_start.tag, event->data.mapping_start.implicit, event->data.mapping_start.style); - break; - } + { + success = yaml_mapping_start_event_initialize(&event_copy, event->data.mapping_start.anchor, + event->data.mapping_start.tag, event->data.mapping_start.implicit, + event->data.mapping_start.style); + break; + } /** A MAPPING-END event. */ case YAML_MAPPING_END_EVENT: - { - success = yaml_mapping_end_event_initialize(&event_copy); - break; - } + { + success = yaml_mapping_end_event_initialize(&event_copy); + break; + } default: - { - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unexpected YAML token of type %d", (int) event->type); - ret = RCUTILS_RET_ERROR; - break; - } + { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unexpected YAML token of type %d", + (int) event->type); + ret = RCUTILS_RET_ERROR; + break; + } } - if (success == 0) - { - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unable to duplicate YAML token of type %d", (int) event->type); + if (success == 0) { + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Unable to duplicate YAML token of type %d", + (int) event->type); return RCUTILS_RET_ERROR; } yaml_emitter_emit(emitter, &event_copy); @@ -780,12 +787,11 @@ rcutils_ret_t parse_key( break; } } else { - if (*overwrite_previous_key == false) - { + if (*overwrite_previous_key == false) { // Handle cases where the code tries to overwrite the yaml parameter name entry ret = find_parameter(*node_idx, value, params_st, parameter_idx); *overwrite_previous_key = true; - }else{ + } else { ret = find_parameter(*node_idx, parameter_ns, params_st, parameter_idx); } if (ret != RCUTILS_RET_OK) { @@ -831,14 +837,12 @@ rcutils_ret_t initialize_emitter_string( // Set initial events yaml_event_t event; yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); - if (!yaml_emitter_emit(emitter, &event)) - { + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); - if (!yaml_emitter_emit(emitter, &event)) - { + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } @@ -853,14 +857,12 @@ rcutils_ret_t end_emitter_string( // Set initial events yaml_event_t event; yaml_document_end_event_initialize(&event, 0); - if (!yaml_emitter_emit(emitter, &event)) - { + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } yaml_stream_end_event_initialize(&event); - if (!yaml_emitter_emit(emitter, &event)) - { + if (!yaml_emitter_emit(emitter, &event)) { ret = RCUTILS_RET_ERROR; } @@ -880,13 +882,12 @@ rcutils_ret_t write_structured_parameter_to_string( rcutils_allocator_t allocator = params_st->allocator; // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function - char* copied_yaml = rcutils_strndup( yaml_string_buffer, *written_size, allocator); + char * copied_yaml = rcutils_strndup(yaml_string_buffer, *written_size, allocator); RCUTILS_CHECK_ARGUMENT_FOR_NULL(copied_yaml, RCUTILS_RET_BAD_ALLOC); rcl_variant_t * param_value = &(params_st->params[node_index].parameter_values[parameter_index]); - - if (param_value->yaml_value != NULL) - { + + if (param_value->yaml_value != NULL) { // Overwriting, deallocate original allocator.deallocate(param_value->yaml_value, allocator.state); } @@ -895,7 +896,6 @@ rcutils_ret_t write_structured_parameter_to_string( } - /// /// Get events from parsing a parameter YAML file and process them /// @@ -946,7 +946,7 @@ rcutils_ret_t parse_file_events( } line_num = ((uint32_t)(event.start_mark.line) + 1U); - + if (is_writing_structured_yaml) { if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) { ret = RCUTILS_RET_ERROR; @@ -975,7 +975,8 @@ rcutils_ret_t parse_file_events( overwrite_previous_key = false; } ret = parse_key( - event, &map_level, &is_new_map, &overwrite_previous_key, &node_idx, ¶meter_idx, ns_tracker, params_st); + event, &map_level, &is_new_map, &overwrite_previous_key, &node_idx, ¶meter_idx, + ns_tracker, params_st); if (RCUTILS_RET_OK != ret) { break; } @@ -1051,10 +1052,10 @@ rcutils_ret_t parse_file_events( structured_yaml_param_idx = parameter_idx; structure_detect_depth = map_depth; initialize_emitter_string(emitter); - if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) - { + if (RCUTILS_RET_ERROR == write_event_to_emitter(emitter, &event)) { ret = RCUTILS_RET_ERROR; - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Error adding line %d to structured yaml parameter", line_num); + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( + "Error adding line %d to structured yaml parameter", line_num); } } break; @@ -1086,21 +1087,18 @@ rcutils_ret_t parse_file_events( } map_depth--; // Terminate structured yaml parameter if needed - if (is_writing_structured_yaml) - { - if (map_depth < structure_detect_depth) - { + if (is_writing_structured_yaml) { + if (map_depth < structure_detect_depth) { end_emitter_string(emitter); - write_structured_parameter_to_string(parser, emitter_string_buffer, emitter_written_bytes, node_idx, structured_yaml_param_idx, params_st); + write_structured_parameter_to_string(parser, emitter_string_buffer, + emitter_written_bytes, node_idx, structured_yaml_param_idx, params_st); is_writing_structured_yaml = false; is_key_value_pair_found = true; structure_detect_depth = 0; structured_yaml_param_idx = 0; // Reset byte counter so that we can reuse buffer *emitter_written_bytes = 0; - } - else - { + } else { } } diff --git a/rcl_yaml_param_parser/src/parser.c b/rcl_yaml_param_parser/src/parser.c index c79845d21..014a4e95a 100644 --- a/rcl_yaml_param_parser/src/parser.c +++ b/rcl_yaml_param_parser/src/parser.c @@ -266,7 +266,6 @@ bool rcl_parse_yaml_file( } - // Emitter for nested parameters yaml_emitter_t emitter; success = yaml_emitter_initialize(&emitter); @@ -277,7 +276,8 @@ bool rcl_parse_yaml_file( size_t max_string_length = 100000; size_t written_size = 0; unsigned char nested_param_string_allocator[100000]; - yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, &written_size); + yaml_emitter_set_output_string(&emitter, nested_param_string_allocator, max_string_length, + &written_size); FILE * yaml_file = fopen(file_path, "r"); @@ -291,7 +291,8 @@ bool rcl_parse_yaml_file( namespace_tracker_t ns_tracker; memset(&ns_tracker, 0, sizeof(namespace_tracker_t)); - rcutils_ret_t ret = parse_file_events(&parser, &emitter, nested_param_string_allocator, &written_size, &ns_tracker, params_st); + rcutils_ret_t ret = parse_file_events(&parser, &emitter, nested_param_string_allocator, + &written_size, &ns_tracker, params_st); fclose(yaml_file); diff --git a/rcl_yaml_param_parser/test/test_parse.cpp b/rcl_yaml_param_parser/test/test_parse.cpp index f7e004f20..436a17e63 100644 --- a/rcl_yaml_param_parser/test/test_parse.cpp +++ b/rcl_yaml_param_parser/test/test_parse.cpp @@ -370,6 +370,7 @@ TEST(TestParse, parse_key_bad_args) rcutils_allocator_t allocator = rcutils_get_default_allocator(); uint32_t map_level = MAP_NODE_NAME_LVL; bool is_new_map = false; + bool overwrite_yaml_param = true; size_t node_idx = 0; size_t parameter_idx = 0; namespace_tracker_t ns_tracker; @@ -387,7 +388,8 @@ TEST(TestParse, parse_key_bad_args) // map_level is nullptr EXPECT_EQ( RCUTILS_RET_INVALID_ARGUMENT, - parse_key(event, nullptr, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + parse_key(event, nullptr, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, + &ns_tracker, params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -395,7 +397,8 @@ TEST(TestParse, parse_key_bad_args) // params_st is nullptr EXPECT_EQ( RCUTILS_RET_INVALID_ARGUMENT, - parse_key(event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, nullptr)) << + parse_key(event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, + &ns_tracker, nullptr)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -406,7 +409,8 @@ TEST(TestParse, parse_key_bad_args) EXPECT_EQ( RCUTILS_RET_INVALID_ARGUMENT, parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, &ns_tracker, + params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -420,7 +424,8 @@ TEST(TestParse, parse_key_bad_args) EXPECT_EQ( RCUTILS_RET_ERROR, parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, &ns_tracker, + params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -431,7 +436,8 @@ TEST(TestParse, parse_key_bad_args) EXPECT_EQ( RCUTILS_RET_ERROR, parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, &ns_tracker, + params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -441,7 +447,8 @@ TEST(TestParse, parse_key_bad_args) EXPECT_EQ( RCUTILS_RET_ERROR, parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, &ns_tracker, + params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -453,7 +460,8 @@ TEST(TestParse, parse_key_bad_args) EXPECT_EQ( RCUTILS_RET_ERROR, parse_key( - event, &map_level, &is_new_map, &node_idx, ¶meter_idx, &ns_tracker, params_st)) << + event, &map_level, &is_new_map, &overwrite_yaml_param, &node_idx, ¶meter_idx, &ns_tracker, + params_st)) << rcutils_get_error_string().str; EXPECT_TRUE(rcutils_error_is_set()); rcutils_reset_error(); @@ -488,6 +496,20 @@ TEST(TestParse, parse_file_events_mock_yaml_parser_parse) { yaml_parser_delete(&parser); }); + size_t max_string_length = 100000; + + yaml_emitter_t emitter; + ASSERT_NE(0, yaml_emitter_initialize(&emitter)); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + yaml_emitter_delete(&emitter); + }); + + + size_t written_size = 0; + char nested_param_string_allocator[100000]; + yaml_emitter_set_output_string(&emitter, (unsigned char *)nested_param_string_allocator, + max_string_length, &written_size); FILE * yaml_file = fopen(path, "r"); ASSERT_NE(nullptr, yaml_file); OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( @@ -505,7 +527,9 @@ TEST(TestParse, parse_file_events_mock_yaml_parser_parse) { event->type = YAML_NO_EVENT; return 1; }); - EXPECT_EQ(RCUTILS_RET_ERROR, parse_file_events(&parser, &ns_tracker, params_hdl)); + EXPECT_EQ(RCUTILS_RET_ERROR, + parse_file_events(&parser, &emitter, nested_param_string_allocator, &written_size, &ns_tracker, + params_hdl)); } TEST(TestParse, parse_value_events_mock_yaml_parser_parse) { From 6882ca7bdc20472c0bacee4e057334a95a43d96b Mon Sep 17 00:00:00 2001 From: "Rahul K.A" Date: Thu, 4 Sep 2025 22:22:27 -0400 Subject: [PATCH 18/18] chore: Fix cpplint complaints Signed-off-by: Rahul K.A --- .../include/rcl_yaml_param_parser/types.h | 2 +- rcl_yaml_param_parser/src/parse.c | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h b/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h index 5ff4b9109..72cdf7ed2 100644 --- a/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h +++ b/rcl_yaml_param_parser/include/rcl_yaml_param_parser/types.h @@ -76,7 +76,7 @@ typedef struct rcl_variant_s int64_t * integer_value; ///< If integer, gets stored here double * double_value; ///< If double, gets stored here char * string_value; ///< If string, gets stored here - char * yaml_value; //< If structured YAML, gets stored here -> Is this right? + char * yaml_value; ///< If structured YAML, gets stored here -> Is this right? rcl_byte_array_t * byte_array_value; ///< If array of bytes rcl_bool_array_t * bool_array_value; ///< If array of bool's rcl_int64_array_t * integer_array_value; ///< If array of integers diff --git a/rcl_yaml_param_parser/src/parse.c b/rcl_yaml_param_parser/src/parse.c index 74e26b297..55786ac0e 100644 --- a/rcl_yaml_param_parser/src/parse.c +++ b/rcl_yaml_param_parser/src/parse.c @@ -274,7 +274,8 @@ rcutils_ret_t parse_value( return RCUTILS_RET_ERROR; } - // rahul-k-a: TODO Combine this with the parameter allocation part of `write_structured_parameter_to_string` and put everything in a seperate function + // rahul-k-a: TODO Combine this with the parameter allocation part of + // `write_structured_parameter_to_string` and put everything in a seperate functiong rcutils_ret_t ret = RCUTILS_RET_OK; switch (val_type) { case DATA_TYPE_UNKNOWN: @@ -599,7 +600,6 @@ rcutils_ret_t write_event_to_emitter( yaml_event_t * event ) { - RCUTILS_CHECK_ARGUMENT_FOR_NULL(emitter, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(event, RCUTILS_RET_INVALID_ARGUMENT); rcutils_ret_t ret = RCUTILS_RET_OK; @@ -663,7 +663,6 @@ rcutils_ret_t write_event_to_emitter( } yaml_emitter_emit(emitter, &event_copy); return ret; - } @@ -869,7 +868,6 @@ rcutils_ret_t end_emitter_string( return ret; } -// TODO: Replace the counter method with indentation method rcutils_ret_t write_structured_parameter_to_string( yaml_parser_t * parser, char * yaml_string_buffer, @@ -881,7 +879,8 @@ rcutils_ret_t write_structured_parameter_to_string( rcutils_ret_t ret = RCUTILS_RET_OK; rcutils_allocator_t allocator = params_st->allocator; - // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` and put everything in a seperate function + // rahul-k-a: TODO combine this with the parameter allocation part of `parse_value` + // and put everything in a seperate function char * copied_yaml = rcutils_strndup(yaml_string_buffer, *written_size, allocator); RCUTILS_CHECK_ARGUMENT_FOR_NULL(copied_yaml, RCUTILS_RET_BAD_ALLOC); @@ -963,13 +962,16 @@ rcutils_ret_t parse_file_events( { /// Need to toggle between key and value at params level if (is_key) { - // If we're at the parameter level, set this flag to denote a value for the key has not been found yet + // If we're at the parameter level, set this flag to denote a + // value for the key has not been found yet if (map_level == MAP_PARAMS_LVL) { is_key_value_pair_found = false; } - // Since the yaml parameter key is also considered as a namespace to all indented children - // We must make sure that the parameter index of the yaml parameter is not overwritten - // By default, if a namespace is detected, then the parameter entry in the param table is replaced by its immediate chile + // Since the yaml parameter key is also considered as a + // namespace to all indented children, we must + // make sure that the parameter index of the yaml parameter is not overwritten + // By default, if a namespace is detected, then the parameter entry in the param + // table is replaced by its immediate chile // This is done for optimization (?) - Rahul-K-A if (is_writing_structured_yaml && (map_depth == structure_detect_depth) ) { overwrite_previous_key = false; @@ -1098,8 +1100,6 @@ rcutils_ret_t parse_file_events( structured_yaml_param_idx = 0; // Reset byte counter so that we can reuse buffer *emitter_written_bytes = 0; - } else { - } } break;