From 4dbfeb0bbccac8164ab8f8686307867c0729d8c1 Mon Sep 17 00:00:00 2001 From: Chen Date: Mon, 15 Jun 2020 23:31:59 +0800 Subject: [PATCH] Support as/as. Fix issue 844/848. --- docs/Breaking-Changes.md | 1 + include/yaml-cpp/node/convert.h | 28 +++++++++++++++++-- test/integration/load_node_test.cpp | 43 +++++++++++++++++++---------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/docs/Breaking-Changes.md b/docs/Breaking-Changes.md index 3b23127..959adea 100644 --- a/docs/Breaking-Changes.md +++ b/docs/Breaking-Changes.md @@ -5,6 +5,7 @@ ## HEAD ## * Throws an exception when trying to parse a negative number as an unsigned integer. + * Supports the `as`/`as`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`. ## 0.6.0 ## diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index db7e44d..532d349 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -15,7 +15,6 @@ #include #include #include -#include #include "yaml-cpp/binary.h" #include "yaml-cpp/node/impl.h" @@ -114,6 +113,31 @@ typename std::enable_if::value, void>::type inner_encode(const T& rhs, std::stringstream& stream){ stream << rhs; } + +template +typename std::enable_if<(std::is_same::value || + std::is_same::value), bool>::type +ConvertStreamTo(std::stringstream& stream, T& rhs) { + int num; + if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) { + if (num >= std::numeric_limits::min() && + num <= std::numeric_limits::max()) { + rhs = num; + return true; + } + } + return false; +} + +template +typename std::enable_if::value || + std::is_same::value), bool>::type +ConvertStreamTo(std::stringstream& stream, T& rhs) { + if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { + return true; + } + return false; +} } #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ @@ -137,7 +161,7 @@ inner_encode(const T& rhs, std::stringstream& stream){ if ((stream.peek() == '-') && std::is_unsigned::value) { \ return false; \ } \ - if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \ + if (conversion::ConvertStreamTo(stream, rhs)) { \ return true; \ } \ if (std::numeric_limits::has_infinity) { \ diff --git a/test/integration/load_node_test.cpp b/test/integration/load_node_test.cpp index 9a93a68..8186486 100644 --- a/test/integration/load_node_test.cpp +++ b/test/integration/load_node_test.cpp @@ -21,22 +21,35 @@ TEST(LoadNodeTest, FallbackValues) { } TEST(LoadNodeTest, NumericConversion) { - Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); - EXPECT_EQ(1.5f, node[0].as()); - EXPECT_EQ(1.5, node[0].as()); - EXPECT_THROW(node[0].as(), TypedBadConversion); - EXPECT_EQ(1, node[1].as()); - EXPECT_EQ(1.0f, node[1].as()); - EXPECT_NE(node[2].as(), node[2].as()); - EXPECT_EQ(std::numeric_limits::infinity(), node[3].as()); - EXPECT_EQ(-std::numeric_limits::infinity(), node[4].as()); - EXPECT_EQ(21, node[5].as()); - EXPECT_EQ(13, node[6].as()); + EXPECT_EQ(1.5f, Load("1.5").as()); + EXPECT_EQ(1.5, Load("1.5").as()); + EXPECT_THROW(Load("1.5").as(), TypedBadConversion); + EXPECT_EQ(1, Load("1").as()); + EXPECT_EQ(1.0f, Load("1").as()); + EXPECT_NE(Load(".nan").as(), Load(".nan").as()); + EXPECT_EQ(std::numeric_limits::infinity(), Load(".inf").as()); + EXPECT_EQ(-std::numeric_limits::infinity(), Load("-.inf").as()); + EXPECT_EQ(21, Load("0x15").as()); + EXPECT_EQ(13, Load("015").as()); + EXPECT_EQ(-128, +Load("-128").as()); + EXPECT_EQ(127, +Load("127").as()); + EXPECT_THROW(Load("128").as(), TypedBadConversion); + EXPECT_EQ(255, +Load("255").as()); + EXPECT_THROW(Load("256").as(), TypedBadConversion); + // test as/as with ‘a’,"ab",'1',"127" + EXPECT_EQ('a', Load("a").as()); + EXPECT_THROW(Load("ab").as(), TypedBadConversion); + EXPECT_EQ('1', Load("1").as()); + EXPECT_THROW(Load("127").as(), TypedBadConversion); + EXPECT_THROW(Load("a").as(), TypedBadConversion); + EXPECT_THROW(Load("ab").as(), TypedBadConversion); + EXPECT_EQ(1, +Load("1").as()); // Throw exception: convert a negative number to an unsigned number. - EXPECT_THROW(node[7].as(), TypedBadConversion); - EXPECT_THROW(node[7].as(), TypedBadConversion); - EXPECT_THROW(node[7].as(), TypedBadConversion); - EXPECT_THROW(node[7].as(), TypedBadConversion); + EXPECT_THROW(Load("-128").as(), TypedBadConversion); + EXPECT_THROW(Load("-128").as(), TypedBadConversion); + EXPECT_THROW(Load("-128").as(), TypedBadConversion); + EXPECT_THROW(Load("-128").as(), TypedBadConversion); + EXPECT_THROW(Load("-128").as(), TypedBadConversion); } TEST(LoadNodeTest, Binary) {