Skip to content

Commit cd4e256

Browse files
brawnerAda-Kingclalancette
committed
Fix yaml parser error when meets .nan (refactor on #754) (#781)
* Fix yaml parser error when meets .nan Signed-off-by: Ada-King <[email protected]> Correct code style Signed-off-by: Ada-King <[email protected]> Modify as suggested Signed-off-by: Ada-King <[email protected]> Improve test Signed-off-by: Ada-King <[email protected]> Fix minor flaw Signed-off-by: Ada-King <[email protected]> Fix minor flaw again Signed-off-by: Ada-King <[email protected]> Satisfy windows CI Signed-off-by: Ada-King <[email protected]> Change the match rule for special float Signed-off-by: Ada-King <[email protected]> Distinguish +.inf and -.inf Signed-off-by: Ada-King <[email protected]> * Remove unnecessary #include change. Signed-off-by: Chris Lalancette <[email protected]> * Add in two more necessary includes. Signed-off-by: Chris Lalancette <[email protected]> Co-authored-by: Ada-King <[email protected]> Co-authored-by: Chris Lalancette <[email protected]>
1 parent c5b70a9 commit cd4e256

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

rcl_yaml_param_parser/src/parse.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <ctype.h>
1516
#include <errno.h>
17+
#include <stdlib.h>
18+
#include <string.h>
1619

1720
#include "rcutils/allocator.h"
1821
#include "rcutils/strdup.h"
@@ -116,7 +119,30 @@ void * get_value(
116119
{
117120
errno = 0;
118121
endptr = NULL;
119-
dval = strtod(value, &endptr);
122+
const char * iter_ptr = NULL;
123+
if ((0 == strcmp(value, ".nan")) ||
124+
(0 == strcmp(value, ".NaN")) ||
125+
(0 == strcmp(value, ".NAN")) ||
126+
(0 == strcmp(value, ".inf")) ||
127+
(0 == strcmp(value, ".Inf")) ||
128+
(0 == strcmp(value, ".INF")) ||
129+
(0 == strcmp(value, "+.inf")) ||
130+
(0 == strcmp(value, "+.Inf")) ||
131+
(0 == strcmp(value, "+.INF")) ||
132+
(0 == strcmp(value, "-.inf")) ||
133+
(0 == strcmp(value, "-.Inf")) ||
134+
(0 == strcmp(value, "-.INF")))
135+
{
136+
for (iter_ptr = value; !isalpha(*iter_ptr); ) {
137+
iter_ptr += 1;
138+
}
139+
dval = strtod(iter_ptr, &endptr);
140+
if (*value == '-') {
141+
dval = -dval;
142+
}
143+
} else {
144+
dval = strtod(value, &endptr);
145+
}
120146
if ((0 == errno) && (NULL != endptr)) {
121147
if ((NULL != endptr) && (endptr != value)) {
122148
if (('\0' != *value) && ('\0' == *endptr)) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test_node:
2+
ros__parameters:
3+
isstring: [string, .nananan, .nAN, .Nan, .infinf, .INf, .infinity]
4+
nan_inf: [1.1, 2.2, .nan, .NAN, .inf, +.Inf, -.INF]

rcl_yaml_param_parser/test/test_parse_yaml.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include <stdio.h>
1615
#include <gtest/gtest.h>
1716

17+
#include <cmath>
18+
1819
#include "osrf_testing_tools_cpp/scope_exit.hpp"
1920

2021
#include "rcl_yaml_param_parser/parser.h"
@@ -497,6 +498,53 @@ TEST(test_file_parser, maximum_number_parameters) {
497498
// No cleanup, rcl_parse_yaml_file takes care of that if it fails.
498499
}
499500

501+
// Test special float point(https://github.com/ros2/rcl/issues/555).
502+
TEST(test_file_parser, special_float_point) {
503+
rcutils_reset_error();
504+
EXPECT_TRUE(rcutils_get_cwd(cur_dir, 1024)) << rcutils_get_error_string().str;
505+
rcutils_allocator_t allocator = rcutils_get_default_allocator();
506+
char * test_path = rcutils_join_path(cur_dir, "test", allocator);
507+
ASSERT_TRUE(NULL != test_path) << rcutils_get_error_string().str;
508+
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
509+
{
510+
allocator.deallocate(test_path, allocator.state);
511+
});
512+
char * path = rcutils_join_path(test_path, "special_float.yaml", allocator);
513+
ASSERT_TRUE(NULL != path) << rcutils_get_error_string().str;
514+
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
515+
{
516+
allocator.deallocate(path, allocator.state);
517+
});
518+
ASSERT_TRUE(rcutils_exists(path)) << "No test YAML file found at " << path;
519+
rcl_params_t * params_hdl = rcl_yaml_node_struct_init(allocator);
520+
ASSERT_TRUE(NULL != params_hdl) << rcutils_get_error_string().str;
521+
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
522+
{
523+
rcl_yaml_node_struct_fini(params_hdl);
524+
});
525+
526+
bool res = rcl_parse_yaml_file(path, params_hdl);
527+
EXPECT_TRUE(res) << rcutils_get_error_string().str;
528+
rcl_variant_t * param_value = rcl_yaml_node_struct_get("test_node", "isstring", params_hdl);
529+
ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str;
530+
ASSERT_TRUE(NULL != param_value->string_array_value);
531+
EXPECT_STREQ(".nananan", param_value->string_array_value->data[1]);
532+
EXPECT_STREQ(".nAN", param_value->string_array_value->data[2]);
533+
EXPECT_STREQ(".infinf", param_value->string_array_value->data[4]);
534+
EXPECT_STREQ(".INf", param_value->string_array_value->data[5]);
535+
param_value = rcl_yaml_node_struct_get(
536+
"test_node", "nan_inf", params_hdl);
537+
ASSERT_TRUE(NULL != param_value) << rcutils_get_error_string().str;
538+
ASSERT_TRUE(NULL != param_value->double_array_value);
539+
ASSERT_EQ(7U, param_value->double_array_value->size);
540+
EXPECT_FALSE(std::isnan(param_value->double_array_value->values[1]));
541+
EXPECT_TRUE(std::isnan(param_value->double_array_value->values[2]));
542+
EXPECT_TRUE(std::isnan(param_value->double_array_value->values[3]));
543+
EXPECT_TRUE(std::isinf(param_value->double_array_value->values[4]));
544+
EXPECT_TRUE(std::isinf(param_value->double_array_value->values[5]));
545+
EXPECT_TRUE(std::isinf(param_value->double_array_value->values[6]));
546+
}
547+
500548
int32_t main(int32_t argc, char ** argv)
501549
{
502550
::testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)