[Mobies-commit] [commit] r4035 - in UDM/trunk: include src/UdmBase src/UdmDom src/UdmUtil
ksmyth at redhat1.isis.vanderbilt.edu
ksmyth at redhat1.isis.vanderbilt.edu
Thu Apr 19 09:30:59 CDT 2012
Author: ksmyth
Date: Thu Apr 19 09:30:59 2012
New Revision: 4035
Log:
Handle INF, -INF, and NaN in DOM backend
Modified:
UDM/trunk/include/UdmUtil.h
UDM/trunk/src/UdmBase/UdmBase.cpp
UDM/trunk/src/UdmDom/UdmDom.cpp
UDM/trunk/src/UdmUtil/UdmUtil.cpp
Modified: UDM/trunk/include/UdmUtil.h
==============================================================================
--- UDM/trunk/include/UdmUtil.h Tue Mar 27 16:11:17 2012 (r4034)
+++ UDM/trunk/include/UdmUtil.h Thu Apr 19 09:30:59 2012 (r4035)
@@ -77,6 +77,8 @@
// Converts a double value to a string, using the least necessary
// precision to represent the original double value.
UDM_DLL string doubleToString(double val, int minimum_precision = 2);
+ // returns false if parsing failed
+ UDM_DLL bool stringToDouble(const char* val, double& out);
UDM_DLL string stacktrace();
};
Modified: UDM/trunk/src/UdmBase/UdmBase.cpp
==============================================================================
--- UDM/trunk/src/UdmBase/UdmBase.cpp Tue Mar 27 16:11:17 2012 (r4034)
+++ UDM/trunk/src/UdmBase/UdmBase.cpp Thu Apr 19 09:30:59 2012 (r4035)
@@ -537,7 +537,8 @@
double d;
for (vector<string>::const_iterator i = vals.begin(); i != vals.end(); i++)
{
- if(sscanf(i->c_str(), "%lf", &d) != 1) throw udm_exception("Attr is of non-float format: " + sc_delimited);
+ if (!UdmUtil::stringToDouble(i->c_str(), d))
+ throw udm_exception("Attr is of non-float format: '" + sc_delimited + "'");
ret.push_back(d);
}
Modified: UDM/trunk/src/UdmDom/UdmDom.cpp
==============================================================================
--- UDM/trunk/src/UdmDom/UdmDom.cpp Tue Mar 27 16:11:17 2012 (r4034)
+++ UDM/trunk/src/UdmDom/UdmDom.cpp Thu Apr 19 09:30:59 2012 (r4035)
@@ -1250,18 +1250,13 @@
if(EmptyVal(a)) return 0.0;
char *a_buf = XMLString::transcode(a);
+ double d;
- char *endptr;
- double d = strtod(a_buf, &endptr);
-
- if (*endptr != '\0')
+ if (!UdmUtil::stringToDouble(a_buf, d))
{
XMLString::release(&a_buf);
throw udm_exception("Attr is of non-float format");
}
-
- XMLString::release(&a_buf);
-
return d;
}
Modified: UDM/trunk/src/UdmUtil/UdmUtil.cpp
==============================================================================
--- UDM/trunk/src/UdmUtil/UdmUtil.cpp Tue Mar 27 16:11:17 2012 (r4034)
+++ UDM/trunk/src/UdmUtil/UdmUtil.cpp Thu Apr 19 09:30:59 2012 (r4035)
@@ -811,6 +811,49 @@
return r;
}
+ // return: true if str represents -Inf, Inf, or NaN
+ static bool ParseSpecialDouble(const char* str, double& out)
+ {
+ const char* val = (*str == '-' && *str != '\0') ? str + 1 : str;
+ if (strnicmp("-Inf", str, 4) == 0 || strnicmp("-1.#INF", str, 7) == 0)
+ {
+ out = -std::numeric_limits<double>::infinity();
+ return true;
+ }
+ else if (strnicmp("Inf", str, 3) == 0 || strnicmp("1.#INF", str, 6) == 0)
+ {
+ out = std::numeric_limits<double>::infinity();
+ return true;
+ }
+ else if (strnicmp("NaN", val, 3) == 0 || strnicmp("1.#IND", val, 7) == 0 || strnicmp("1.#QNAN", val, 7) == 0 || strnicmp("1.#SNAN", val, 7) == 0)
+ {
+ out = std::numeric_limits<double>::quiet_NaN();
+ return true;
+ }
+ return false;
+ }
+
+ UDM_DLL bool stringToDouble(const char* val, double& out)
+ {
+ if (ParseSpecialDouble(val, out))
+ {
+ return true;
+ }
+ else
+ {
+ char* endptr;
+ double tmp;
+ tmp = strtod(val, &endptr);
+
+ if (*endptr != '\0')
+ {
+ return false;
+ }
+ out = tmp;
+ return true;
+ }
+ }
+
UDM_DLL string doubleToString(double val, int minimum_precision)
{
const int MAXIMAL_PRECISION = 19;
@@ -818,7 +861,27 @@
char result[64];
+ // special values per xml-xerces/c/src/util/XMLDouble.cpp
+ if (val != val)
+ {
+ return "NaN";
+ }
+ else if(val == std::numeric_limits<double>::infinity())
+ {
+ return "INF";
+ }
+ else if (val == -std::numeric_limits<double>::infinity())
+ {
+ return "-INF";
+ }
+
+ // This works (but is not minimal):
+ //_snprintf_s(result, 64, "%.17g", val);
+ //return result;
+
int precision_is_good;
+ // KMS: this code is incredibly inefficient
+ // TODO: use something like Gay's dtoa.c
do {
UDM_ASSERT(precision <= MAXIMAL_PRECISION);
@@ -834,7 +897,8 @@
#endif
double d;
- if (sscanf(result, "%lf", &d) != 1) throw udm_exception("Internal error when converting from double to string");
+ if (sscanf(result, "%lf", &d) != 1)
+ throw udm_exception("Internal error when converting from double to string");
precision_is_good = d == val;
precision++;
More information about the Mobies-commit
mailing list