fix issue 844/848: support the as<uint8_t>/as<int8_t>

This commit is contained in:
dota17 2020-05-21 11:27:02 +08:00
parent d9c35b6079
commit 27d88f83d9
2 changed files with 56 additions and 3 deletions

View File

@ -7,15 +7,16 @@
#pragma once #pragma once
#endif #endif
#include <algorithm>
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <cstdint>
#include <limits> #include <limits>
#include <list> #include <list>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include <type_traits>
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/node/impl.h" #include "yaml-cpp/node/impl.h"
@ -114,6 +115,44 @@ typename std::enable_if<!std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){ inner_encode(const T& rhs, std::stringstream& stream){
stream << rhs; stream << rhs;
} }
template <typename T>
typename std::enable_if<std::is_same<T, unsigned char>::value, bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
uint16_t num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
rhs = std::min(num, (uint16_t)UINT8_MAX);
return true;
}
return false;
}
template <typename T>
typename std::enable_if<std::is_same<T, signed char>::value, bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
int16_t num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
if (num > INT8_MAX) {
rhs = INT8_MAX;
} else if (num < INT8_MIN) {
rhs = INT8_MIN;
} else {
rhs = num;
}
return true;
}
return false;
}
template <typename T>
typename std::enable_if<!(std::is_same<T,unsigned char>::value ||
std::is_same<T, signed char>::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) \ #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
@ -137,7 +176,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \ if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \ return false; \
} \ } \
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \ if (conversion::ConvertStreamTo(stream, rhs)) { \
return true; \ return true; \
} \ } \
if (std::numeric_limits<type>::has_infinity) { \ if (std::numeric_limits<type>::has_infinity) { \

View File

@ -21,7 +21,7 @@ TEST(LoadNodeTest, FallbackValues) {
} }
TEST(LoadNodeTest, NumericConversion) { TEST(LoadNodeTest, NumericConversion) {
Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015, -128, 127, 128, 255, 256, a, ab]");
EXPECT_EQ(1.5f, node[0].as<float>()); EXPECT_EQ(1.5f, node[0].as<float>());
EXPECT_EQ(1.5, node[0].as<double>()); EXPECT_EQ(1.5, node[0].as<double>());
EXPECT_THROW(node[0].as<int>(), TypedBadConversion<int>); EXPECT_THROW(node[0].as<int>(), TypedBadConversion<int>);
@ -32,11 +32,25 @@ TEST(LoadNodeTest, NumericConversion) {
EXPECT_EQ(-std::numeric_limits<float>::infinity(), node[4].as<float>()); EXPECT_EQ(-std::numeric_limits<float>::infinity(), node[4].as<float>());
EXPECT_EQ(21, node[5].as<int>()); EXPECT_EQ(21, node[5].as<int>());
EXPECT_EQ(13, node[6].as<int>()); EXPECT_EQ(13, node[6].as<int>());
EXPECT_EQ(-128, +node[7].as<int8_t>());
EXPECT_EQ(127, +node[8].as<int8_t>());
EXPECT_EQ(127, +node[9].as<int8_t>());
EXPECT_EQ(255, +node[10].as<uint8_t>());
EXPECT_EQ(255, +node[11].as<uint8_t>());
// test as<char>/as<uint8_t> with a,"ab",'1',"127"
EXPECT_EQ('a', node[12].as<char>());
EXPECT_THROW(node[13].as<char>(), TypedBadConversion<char>);
EXPECT_EQ('1', node[1].as<char>());
EXPECT_THROW(node[8].as<char>(), TypedBadConversion<char>);
EXPECT_THROW(node[12].as<uint8_t>(), TypedBadConversion<unsigned char>);
EXPECT_THROW(node[13].as<uint8_t>(), TypedBadConversion<unsigned char>);
EXPECT_EQ(1, +node[1].as<uint8_t>());
// Throw exception: convert a negative number to an unsigned number. // Throw exception: convert a negative number to an unsigned number.
EXPECT_THROW(node[7].as<unsigned>(), TypedBadConversion<unsigned int>); EXPECT_THROW(node[7].as<unsigned>(), TypedBadConversion<unsigned int>);
EXPECT_THROW(node[7].as<unsigned short>(), TypedBadConversion<unsigned short>); EXPECT_THROW(node[7].as<unsigned short>(), TypedBadConversion<unsigned short>);
EXPECT_THROW(node[7].as<unsigned long>(), TypedBadConversion<unsigned long>); EXPECT_THROW(node[7].as<unsigned long>(), TypedBadConversion<unsigned long>);
EXPECT_THROW(node[7].as<unsigned long long>(), TypedBadConversion<unsigned long long>); EXPECT_THROW(node[7].as<unsigned long long>(), TypedBadConversion<unsigned long long>);
EXPECT_THROW(node[7].as<uint8_t>(), TypedBadConversion<unsigned char>);
} }
TEST(LoadNodeTest, Binary) { TEST(LoadNodeTest, Binary) {