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/node.h"
|
||||||
#include "yaml-cpp/node/iterator.h"
|
#include "yaml-cpp/node/iterator.h"
|
||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -16,6 +17,20 @@
|
|||||||
|
|
||||||
namespace YAML
|
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
|
// std::string
|
||||||
template<>
|
template<>
|
||||||
struct convert<std::string> {
|
struct convert<std::string> {
|
||||||
@@ -54,9 +69,27 @@ namespace YAML
|
|||||||
static bool decode(const Node& node, type& rhs) {\
|
static bool decode(const Node& node, type& rhs) {\
|
||||||
if(node.Type() != NodeType::Scalar)\
|
if(node.Type() != NodeType::Scalar)\
|
||||||
return false;\
|
return false;\
|
||||||
std::stringstream stream(node.Scalar());\
|
const std::string& input = node.Scalar();\
|
||||||
stream >> rhs;\
|
std::stringstream stream(input);\
|
||||||
return !!stream;\
|
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(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 Test
|
||||||
{
|
{
|
||||||
namespace Node
|
namespace Node
|
||||||
@@ -298,6 +300,20 @@ namespace Test
|
|||||||
YAML_ASSERT(node["y"].as<int>(5) == 5);
|
YAML_ASSERT(node["y"].as<int>(5) == 5);
|
||||||
return true;
|
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) {
|
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::AutoBoolConversion, "auto bool conversion", passed, total);
|
||||||
RunNodeTest(&Node::Reassign, "reassign", passed, total);
|
RunNodeTest(&Node::Reassign, "reassign", passed, total);
|
||||||
RunNodeTest(&Node::FallbackValues, "fallback values", passed, total);
|
RunNodeTest(&Node::FallbackValues, "fallback values", passed, total);
|
||||||
|
RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total);
|
||||||
|
|
||||||
std::cout << "Node tests: " << passed << "/" << total << " passed\n";
|
std::cout << "Node tests: " << passed << "/" << total << " passed\n";
|
||||||
return passed == total;
|
return passed == total;
|
||||||
|
Reference in New Issue
Block a user