[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