Skip to content

Commit

Permalink
fix malformed nan and inf json output (#162)
Browse files Browse the repository at this point in the history
* fix malformed nan and inf json output
  • Loading branch information
cyrush committed Apr 27, 2017
1 parent 9ef9871 commit 295ff9d
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 8 deletions.
13 changes: 12 additions & 1 deletion src/libs/conduit/conduit_data_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,18 @@ DataArray<T>::to_json(std::ostream &os) const
case DataType::FLOAT32_ID:
case DataType::FLOAT64_ID:
{
os << utils::float64_to_string((float64) element(idx));
std::string fs = utils::float64_to_string((float64)element(idx));
//check for inf and nan
// looking for 'n' covers inf and nan
bool inf_or_nan = fs.find('n') != std::string::npos;

if(inf_or_nan)
os << "\"";

os << fs;

if(inf_or_nan)
os << "\"";
break;
}
default:
Expand Down
10 changes: 6 additions & 4 deletions src/libs/conduit/conduit_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,8 @@ Generator::data_ptr() const
// JSON Parsing interface
//-----------------------------------------------------------------------------s

const rapidjson::ParseFlag RAPIDJSON_PARSE_OPTS = rapidjson::kParseNoFlags;

//---------------------------------------------------------------------------//
void
Generator::walk(Schema &schema) const
Expand All @@ -1280,7 +1282,7 @@ Generator::walk(Schema &schema) const
rapidjson::Document document;
std::string res = utils::json_sanitize(m_json_schema);

if(document.Parse<0>(res.c_str()).HasParseError())
if(document.Parse<RAPIDJSON_PARSE_OPTS>(res.c_str()).HasParseError())
{
CONDUIT_JSON_PARSE_ERROR(document);
}
Expand Down Expand Up @@ -1309,7 +1311,7 @@ Generator::walk_external(Node &node) const
rapidjson::Document document;
std::string res = utils::json_sanitize(m_json_schema);

if(document.Parse<0>(res.c_str()).HasParseError())
if(document.Parse<RAPIDJSON_PARSE_OPTS>(res.c_str()).HasParseError())
{
CONDUIT_JSON_PARSE_ERROR(document);
}
Expand All @@ -1323,7 +1325,7 @@ Generator::walk_external(Node &node) const
rapidjson::Document document;
std::string res = utils::json_sanitize(m_json_schema);

if(document.Parse<0>(res.c_str()).HasParseError())
if(document.Parse<RAPIDJSON_PARSE_OPTS>(res.c_str()).HasParseError())
{
CONDUIT_JSON_PARSE_ERROR(document);
}
Expand All @@ -1335,7 +1337,7 @@ Generator::walk_external(Node &node) const
rapidjson::Document document;
std::string res = utils::json_sanitize(m_json_schema);

if(document.Parse<0>(res.c_str()).HasParseError())
if(document.Parse<RAPIDJSON_PARSE_OPTS>(res.c_str()).HasParseError())
{
CONDUIT_JSON_PARSE_ERROR(document);
}
Expand Down
10 changes: 9 additions & 1 deletion src/libs/conduit/conduit_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
#include <stdio.h>
#include <stdlib.h>

#include <limits>


// define proper path sep
#if defined(CONDUIT_PLATFORM_WINDOWS)
Expand Down Expand Up @@ -793,8 +795,14 @@ float64_to_string(float64 value)
snprintf(buffer,64,"%.15g",value);

std::string res(buffer);

// we check for inf or nan in string form.
// std::isnan, isn't portable until c++11
// http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c

if(res.find('.') == std::string::npos &&
// searching for 'n' covers inf and nan
if(res.find('n') == std::string::npos &&
res.find('.') == std::string::npos &&
res.find('e') == std::string::npos )
{
res += ".0";
Expand Down
23 changes: 23 additions & 0 deletions src/tests/conduit/t_conduit_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "conduit.hpp"

#include <iostream>
#include <limits>
#include "gtest/gtest.h"

using namespace conduit;
Expand Down Expand Up @@ -595,6 +596,28 @@ TEST(conduit_json, json_schema_preserve_floats)

}

//-----------------------------------------------------------------------------
TEST(conduit_json, json_inf_and_nan)
{
Node n;
n["pos_inf"] = std::numeric_limits<float64>::infinity();
n["neg_inf"] = -std::numeric_limits<float64>::infinity();
n["nan"] = std::numeric_limits<float64>::quiet_NaN();

CONDUIT_INFO(n.to_json());

std::string json_str = n.to_json();
CONDUIT_INFO(json_str);

Generator g(json_str,"json");

Node n_res;
g.walk(n_res);

CONDUIT_INFO(n_res.to_json());

}




18 changes: 16 additions & 2 deletions src/tests/conduit/t_conduit_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
#include "conduit.hpp"

#include <iostream>
#include <limits>
#include "gtest/gtest.h"

#include "t_config.hpp"


using namespace conduit;

bool info_occured = false;
Expand Down Expand Up @@ -214,15 +216,27 @@ TEST(conduit_utils, escape_special_chars)
//-----------------------------------------------------------------------------
TEST(conduit_utils, float64_to_string)
{


float64 v = 10.0;

EXPECT_EQ("10.0",utils::float64_to_string(v));

v = 10000000000000000;
EXPECT_EQ("1e+16",utils::float64_to_string(v));

v = std::numeric_limits<float64>::infinity();
CONDUIT_INFO(utils::float64_to_string(v));

EXPECT_EQ("inf",utils::float64_to_string(v));

v = -std::numeric_limits<float64>::infinity();
CONDUIT_INFO(utils::float64_to_string(v));

EXPECT_EQ("-inf",utils::float64_to_string(v));

v = std::numeric_limits<float64>::quiet_NaN();
CONDUIT_INFO(utils::float64_to_string(v));

EXPECT_EQ("nan",utils::float64_to_string(v));
}


Expand Down

0 comments on commit 295ff9d

Please sign in to comment.