Skip to content

Commit 4dbfeb0

Browse files
authored
Support as<uint8_t>/as<int8_t>.
Fix issue 844/848.
1 parent 33316d5 commit 4dbfeb0

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

docs/Breaking-Changes.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## HEAD ##
66

77
* Throws an exception when trying to parse a negative number as an unsigned integer.
8+
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
89

910
## 0.6.0 ##
1011

include/yaml-cpp/node/convert.h

+26-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <sstream>
1616
#include <type_traits>
1717
#include <vector>
18-
#include <type_traits>
1918

2019
#include "yaml-cpp/binary.h"
2120
#include "yaml-cpp/node/impl.h"
@@ -114,6 +113,31 @@ typename std::enable_if<!std::is_floating_point<T>::value, void>::type
114113
inner_encode(const T& rhs, std::stringstream& stream){
115114
stream << rhs;
116115
}
116+
117+
template <typename T>
118+
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
119+
std::is_same<T, signed char>::value), bool>::type
120+
ConvertStreamTo(std::stringstream& stream, T& rhs) {
121+
int num;
122+
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
123+
if (num >= std::numeric_limits<T>::min() &&
124+
num <= std::numeric_limits<T>::max()) {
125+
rhs = num;
126+
return true;
127+
}
128+
}
129+
return false;
130+
}
131+
132+
template <typename T>
133+
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
134+
std::is_same<T, signed char>::value), bool>::type
135+
ConvertStreamTo(std::stringstream& stream, T& rhs) {
136+
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
137+
return true;
138+
}
139+
return false;
140+
}
117141
}
118142

119143
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
@@ -137,7 +161,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
137161
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
138162
return false; \
139163
} \
140-
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \
164+
if (conversion::ConvertStreamTo(stream, rhs)) { \
141165
return true; \
142166
} \
143167
if (std::numeric_limits<type>::has_infinity) { \

test/integration/load_node_test.cpp

+28-15
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,35 @@ TEST(LoadNodeTest, FallbackValues) {
2121
}
2222

2323
TEST(LoadNodeTest, NumericConversion) {
24-
Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]");
25-
EXPECT_EQ(1.5f, node[0].as<float>());
26-
EXPECT_EQ(1.5, node[0].as<double>());
27-
EXPECT_THROW(node[0].as<int>(), TypedBadConversion<int>);
28-
EXPECT_EQ(1, node[1].as<int>());
29-
EXPECT_EQ(1.0f, node[1].as<float>());
30-
EXPECT_NE(node[2].as<float>(), node[2].as<float>());
31-
EXPECT_EQ(std::numeric_limits<float>::infinity(), node[3].as<float>());
32-
EXPECT_EQ(-std::numeric_limits<float>::infinity(), node[4].as<float>());
33-
EXPECT_EQ(21, node[5].as<int>());
34-
EXPECT_EQ(13, node[6].as<int>());
24+
EXPECT_EQ(1.5f, Load("1.5").as<float>());
25+
EXPECT_EQ(1.5, Load("1.5").as<double>());
26+
EXPECT_THROW(Load("1.5").as<int>(), TypedBadConversion<int>);
27+
EXPECT_EQ(1, Load("1").as<int>());
28+
EXPECT_EQ(1.0f, Load("1").as<float>());
29+
EXPECT_NE(Load(".nan").as<float>(), Load(".nan").as<float>());
30+
EXPECT_EQ(std::numeric_limits<float>::infinity(), Load(".inf").as<float>());
31+
EXPECT_EQ(-std::numeric_limits<float>::infinity(), Load("-.inf").as<float>());
32+
EXPECT_EQ(21, Load("0x15").as<int>());
33+
EXPECT_EQ(13, Load("015").as<int>());
34+
EXPECT_EQ(-128, +Load("-128").as<int8_t>());
35+
EXPECT_EQ(127, +Load("127").as<int8_t>());
36+
EXPECT_THROW(Load("128").as<int8_t>(), TypedBadConversion<signed char>);
37+
EXPECT_EQ(255, +Load("255").as<uint8_t>());
38+
EXPECT_THROW(Load("256").as<uint8_t>(), TypedBadConversion<unsigned char>);
39+
// test as<char>/as<uint8_t> with ‘a’,"ab",'1',"127"
40+
EXPECT_EQ('a', Load("a").as<char>());
41+
EXPECT_THROW(Load("ab").as<char>(), TypedBadConversion<char>);
42+
EXPECT_EQ('1', Load("1").as<char>());
43+
EXPECT_THROW(Load("127").as<char>(), TypedBadConversion<char>);
44+
EXPECT_THROW(Load("a").as<uint8_t>(), TypedBadConversion<unsigned char>);
45+
EXPECT_THROW(Load("ab").as<uint8_t>(), TypedBadConversion<unsigned char>);
46+
EXPECT_EQ(1, +Load("1").as<uint8_t>());
3547
// Throw exception: convert a negative number to an unsigned number.
36-
EXPECT_THROW(node[7].as<unsigned>(), TypedBadConversion<unsigned int>);
37-
EXPECT_THROW(node[7].as<unsigned short>(), TypedBadConversion<unsigned short>);
38-
EXPECT_THROW(node[7].as<unsigned long>(), TypedBadConversion<unsigned long>);
39-
EXPECT_THROW(node[7].as<unsigned long long>(), TypedBadConversion<unsigned long long>);
48+
EXPECT_THROW(Load("-128").as<unsigned>(), TypedBadConversion<unsigned int>);
49+
EXPECT_THROW(Load("-128").as<unsigned short>(), TypedBadConversion<unsigned short>);
50+
EXPECT_THROW(Load("-128").as<unsigned long>(), TypedBadConversion<unsigned long>);
51+
EXPECT_THROW(Load("-128").as<unsigned long long>(), TypedBadConversion<unsigned long long>);
52+
EXPECT_THROW(Load("-128").as<uint8_t>(), TypedBadConversion<unsigned char>);
4053
}
4154

4255
TEST(LoadNodeTest, Binary) {

0 commit comments

Comments
 (0)