Gracefully handle NaN/inf values in fast_atoreal_move
There are legitimate cases where inf/nan values are embeddded in a mesh. Such values should not cause loading to fail, and indeed, previous versions of Assimp supported their existence. Update the new fast_atoreal_move method to gracefully parse such values, allowing case-insensitive checks for "NAN", "INF" and "INFINITY" as per the atof guidelines found at http://en.cppreference.com/w/cpp/string/byte/atof. Note that the inf/nan text parsing is fairly loose, but is fast for the general case and should handle most legitimate inf/nan values.pull/338/head
parent
0ede630b10
commit
ed124ccbab
|
@ -16,7 +16,9 @@
|
||||||
#define __FAST_A_TO_F_H_INCLUDED__
|
#define __FAST_A_TO_F_H_INCLUDED__
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits.h>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "StringComparison.h"
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
@ -236,18 +238,36 @@ inline const char* fast_atoreal_move( const char* c, Real& out, bool check_comma
|
||||||
++c;
|
++c;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(c[0] >= '0' && c[0] <= '9') &&
|
if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0)
|
||||||
!(c[0] == '.' && c[1] >= '0' && c[1] <= '9'))
|
{
|
||||||
{
|
out = std::numeric_limits<Real>::quiet_NaN();
|
||||||
throw std::invalid_argument("Cannot parse string "
|
c += 3;
|
||||||
"as real number: does not start with digit "
|
return c;
|
||||||
"or decimal point followed by digit.");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (*c != '.')
|
if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0)
|
||||||
{
|
{
|
||||||
f = static_cast<Real>( strtoul10_64 ( c, &c) );
|
out = std::numeric_limits<Real>::infinity();
|
||||||
}
|
c += 3;
|
||||||
|
if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0)
|
||||||
|
{
|
||||||
|
c += 5;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(c[0] >= '0' && c[0] <= '9') &&
|
||||||
|
!(c[0] == '.' && c[1] >= '0' && c[1] <= '9'))
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Cannot parse string "
|
||||||
|
"as real number: does not start with digit "
|
||||||
|
"or decimal point followed by digit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*c != '.')
|
||||||
|
{
|
||||||
|
f = static_cast<Real>( strtoul10_64 ( c, &c) );
|
||||||
|
}
|
||||||
|
|
||||||
if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')
|
if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue