mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 04:41:16 +00:00
Updated new API conversion to handle nan/inf and to throw when the conversion didn't use the entire string (e.g., parsing 1.2 as an integer)
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
@@ -16,6 +17,20 @@
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
namespace conversion {
|
||||
inline bool IsInfinity(const std::string& input) {
|
||||
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF";
|
||||
}
|
||||
|
||||
inline bool IsNegativeInfinity(const std::string& input) {
|
||||
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
|
||||
}
|
||||
|
||||
inline bool IsNaN(const std::string& input) {
|
||||
return input == ".nan" || input == ".NaN" || input == ".NAN";
|
||||
}
|
||||
}
|
||||
|
||||
// std::string
|
||||
template<>
|
||||
struct convert<std::string> {
|
||||
@@ -54,9 +69,27 @@ namespace YAML
|
||||
static bool decode(const Node& node, type& rhs) {\
|
||||
if(node.Type() != NodeType::Scalar)\
|
||||
return false;\
|
||||
std::stringstream stream(node.Scalar());\
|
||||
stream >> rhs;\
|
||||
return !!stream;\
|
||||
const std::string& input = node.Scalar();\
|
||||
std::stringstream stream(input);\
|
||||
stream.unsetf(std::ios::dec);\
|
||||
if((stream >> rhs) && (stream >> std::ws).eof())\
|
||||
return true;\
|
||||
if(std::numeric_limits<type>::has_infinity) {\
|
||||
if(conversion::IsInfinity(input)) {\
|
||||
rhs = std::numeric_limits<type>::infinity();\
|
||||
return true;\
|
||||
} else if(conversion::IsNegativeInfinity(input)) {\
|
||||
rhs = -std::numeric_limits<type>::infinity();\
|
||||
return true;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
if(std::numeric_limits<type>::has_quiet_NaN && conversion::IsNaN(input)) {\
|
||||
rhs = std::numeric_limits<type>::quiet_NaN();\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
return false;\
|
||||
}\
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,8 @@ namespace {
|
||||
|
||||
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false)
|
||||
|
||||
#define YAML_ASSERT_THROWS(cond, exc) do { try { (cond); return " Expression did not throw: " #cond; } catch(const exc&) {} catch(...) { return " Expression threw something other than " #exc ": " #cond; } } while(false)
|
||||
|
||||
namespace Test
|
||||
{
|
||||
namespace Node
|
||||
@@ -298,6 +300,20 @@ namespace Test
|
||||
YAML_ASSERT(node["y"].as<int>(5) == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST NumericConversion()
|
||||
{
|
||||
YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf]");
|
||||
YAML_ASSERT(node[0].as<float>() == 1.5f);
|
||||
YAML_ASSERT(node[0].as<double>() == 1.5);
|
||||
YAML_ASSERT_THROWS(node[0].as<int>(), std::runtime_error);
|
||||
YAML_ASSERT(node[1].as<int>() == 1);
|
||||
YAML_ASSERT(node[1].as<float>() == 1.0f);
|
||||
YAML_ASSERT(node[2].as<float>() != node[2].as<float>());
|
||||
YAML_ASSERT(node[3].as<float>() == std::numeric_limits<float>::infinity());
|
||||
YAML_ASSERT(node[4].as<float>() == -std::numeric_limits<float>::infinity());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
|
||||
@@ -345,6 +361,7 @@ namespace Test
|
||||
RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total);
|
||||
RunNodeTest(&Node::Reassign, "reassign", passed, total);
|
||||
RunNodeTest(&Node::FallbackValues, "fallback values", passed, total);
|
||||
RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total);
|
||||
|
||||
std::cout << "Node tests: " << passed << "/" << total << " passed\n";
|
||||
return passed == total;
|
||||
|
Reference in New Issue
Block a user