You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@apache.org on 2001/01/16 03:42:14 UTC
cvs commit: xml-xalan/c/src/PlatformSupport DOMStringHelper.cpp DoubleSupport.cpp DoubleSupport.hpp
dbertoni 01/01/15 18:42:14
Modified: c/src/PlatformSupport DOMStringHelper.cpp DoubleSupport.cpp
DoubleSupport.hpp
Log:
Added validation function for converting string to double.
Revision Changes Path
1.50 +14 -1 xml-xalan/c/src/PlatformSupport/DOMStringHelper.cpp
Index: DOMStringHelper.cpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/PlatformSupport/DOMStringHelper.cpp,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- DOMStringHelper.cpp 2001/01/08 18:15:30 1.49
+++ DOMStringHelper.cpp 2001/01/16 02:42:13 1.50
@@ -1242,14 +1242,21 @@
const XalanDOMChar* theString,
Type /* theDummy */)
{
- if (theString == 0)
+ if (theString == 0 || DoubleSupport::isValid(theString) == false)
{
return Type(0);
}
else
{
+ // OK, now we know we have a valid string, so start converting...
Type theResult = 0;
+ // Consume any leading whitespace (which we allow)
+ while(isXMLWhitespace(*theString) == true)
+ {
+ ++theString;
+ }
+
const bool isNegative = *theString == XalanUnicode::charHyphenMinus ? true : false;
if (isNegative == true)
@@ -1267,8 +1274,14 @@
++theString;
}
+ else if (isXMLWhitespace(*theString) == true)
+ {
+ // This must be trailing whitespace...
+ break;
+ }
else
{
+ // An non-numeric character was encountered, so stop...
return 0;
}
}
1.18 +220 -23 xml-xalan/c/src/PlatformSupport/DoubleSupport.cpp
Index: DoubleSupport.cpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/PlatformSupport/DoubleSupport.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- DoubleSupport.cpp 2000/12/01 21:36:00 1.17
+++ DoubleSupport.cpp 2001/01/16 02:42:13 1.18
@@ -363,9 +363,7 @@
-#if 1
-
-void
+static void
consumeNumbers(const XalanDOMChar*& theString)
{
while(*theString &&
@@ -378,12 +376,177 @@
+static bool
+doValidate(
+ const XalanDOMChar* theString,
+ bool& fGotDecimalPoint)
+{
+ assert(theString != 0);
+
+ bool fError = false;
+ bool fGotDigit = false;
+ bool fGotMinus = false;
+ bool fGotWhitespace = false;
+
+ const XalanDOMChar* theCurrent = theString;
+
+ // trim any whitespace
+ consumeWhitespace(theCurrent);
+
+ while(*theCurrent != 0 && fError == false)
+ {
+ switch(*theCurrent)
+ {
+ case XalanUnicode::charFullStop:
+ if (fGotDecimalPoint == true || // can't have more than one...
+ fGotWhitespace == true) // can't have one after whitespace...
+ {
+ fError = true;
+ }
+ else
+ {
+ fGotDecimalPoint = true;
+
+ ++theCurrent;
+ }
+ break;
+
+ case XalanUnicode::charHyphenMinus:
+ if (fGotDecimalPoint == true ||
+ fGotMinus == true ||
+ fGotDigit == true ||
+ fGotWhitespace == true)
+ {
+ // Error -- more than one, or in bad position.
+ fError = true;
+ }
+ else
+ {
+ fGotMinus = true;
+
+ ++theCurrent;
+ }
+ break;
+
+ case XalanUnicode::charDigit_0:
+ case XalanUnicode::charDigit_1:
+ case XalanUnicode::charDigit_2:
+ case XalanUnicode::charDigit_3:
+ case XalanUnicode::charDigit_4:
+ case XalanUnicode::charDigit_5:
+ case XalanUnicode::charDigit_6:
+ case XalanUnicode::charDigit_7:
+ case XalanUnicode::charDigit_8:
+ case XalanUnicode::charDigit_9:
+ if (fGotWhitespace == true)
+ {
+ fError = true;
+ }
+ else
+ {
+ fGotDigit = true;
+
+ consumeNumbers(theCurrent);
+ }
+ break;
+
+ case XalanUnicode::charSpace:
+ case XalanUnicode::charCR:
+ case XalanUnicode::charHTab:
+ case XalanUnicode::charLF:
+ if (fGotWhitespace == true)
+ {
+ fError = true;
+ }
+ else
+ {
+ fGotWhitespace = true;
+
+ consumeWhitespace(theCurrent);
+ }
+ break;
+
+ default:
+ fError = true;
+ break;
+ }
+ }
+
+ // If there was no error, check to see that we got
+ // at least one digit. Otherwise, return false if
+ // there was an error.
+ return fError == false ? fGotDigit : false;
+}
+
+
+
+static bool
+doValidate(const XalanDOMChar* theString)
+{
+ bool fDummy = false;
+
+ return doValidate(theString, fDummy);
+}
+
+
+
+inline double
+convertHelper(
+ const XalanDOMChar* theString,
+ bool fGotDecimalPoint)
+{
+ // This is a big hack. If the length of the
+ // string is less than n characters, we'll convert
+ // it as a long and coerce that to a double. This
+ // is _much_ cheaper...
+ const unsigned int theLongHackThreshold = 11;
+
+ const unsigned int theLength = length(theString);
+
+ if (fGotDecimalPoint == false && theLength < theLongHackThreshold)
+ {
+ return double(WideStringToLong(theString));
+ }
+ else
+ {
+ // Use a stack-based buffer, when possible...
+ const unsigned int theBufferSize = 200u;
+
+ if (theLength < theBufferSize)
+ {
+ char theBuffer[theBufferSize];
+
+ for(unsigned int i = 0; i < theLength; ++i)
+ {
+ theBuffer[i] = char(theString[i]);
+ }
+
+ theBuffer[theLength] = '\0';
+
+ return atof(theBuffer);
+ }
+ else
+ {
+ CharVectorType theVector;
+
+ theVector.reserve(theLength + 1);
+
+ CopyWideStringToVector(theString, theVector);
+
+ return atof(&*theVector.begin());
+ }
+ }
+}
+
+
+
double
doConvert(const XalanDOMChar* theString)
{
assert(theString != 0);
assert(*theString != 0);
+#if 0
bool fError = false;
bool fGotDecimalPoint = false;
bool fGotDigit = false;
@@ -485,17 +648,67 @@
return wcstod(theString, &theDummy);
#else
- CharVectorType theVector;
+ return convertHelper(theString, fGotDecimalPoint);
+#endif
+ }
+#else
+ bool fGotDecimalPoint = false;
- CopyWideStringToVector(theString, theVector);
+ if (doValidate(theString, fGotDecimalPoint) == false)
+ {
+ return DoubleSupport::getNaN();
+ }
+ else
+ {
+#if defined(XALAN_FULL_WCHAR_SUPPORT) && defined(XALAN_USE_WCHAR_SUPPORT)
+ XalanDOMChar* theDummy;
- return atof(&theVector.front());
+ return wcstod(theString, &theDummy);
+#else
+ return convertHelper(theString, fGotDecimalPoint);
#endif
}
+#endif
}
-#else
+
+double
+DoubleSupport::toDouble(const XalanDOMChar* theString)
+{
+ if (theString == 0 ||
+ *theString == 0)
+ {
+ return getNaN();
+ }
+ else
+ {
+ return doConvert(theString);
+ }
+}
+
+
+
+bool
+DoubleSupport::isValid(const XalanDOMString theString)
+{
+ return isValid(c_wstr(theString));
+}
+
+
+
+bool
+DoubleSupport::isValid(const XalanDOMChar* theString)
+{
+ bool fDummy = false;
+
+ return doValidate(theString);
+}
+
+
+
+#if 0
+
// This version is disabled because it turns out that
// an unsigned long is not large enough to accumulate
// all values (duh!). Perhaps on 64-bit platforms, we
@@ -670,19 +883,3 @@
}
#endif
-
-
-
-double
-DoubleSupport::toDouble(const XalanDOMChar* theString)
-{
- if (theString == 0 ||
- *theString == 0)
- {
- return getNaN();
- }
- else
- {
- return doConvert(theString);
- }
-}
1.10 +36 -0 xml-xalan/c/src/PlatformSupport/DoubleSupport.hpp
Index: DoubleSupport.hpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/PlatformSupport/DoubleSupport.hpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- DoubleSupport.hpp 2000/12/01 21:36:00 1.9
+++ DoubleSupport.hpp 2001/01/16 02:42:13 1.10
@@ -551,9 +551,45 @@
}
};
+ /**
+ * Determine whether or not a string contains
+ * a valid floating point number.
+ *
+ * @param theString The string to check.
+ * @return true if the string is valid, false if not.
+ */
+ static bool
+ isValid(const XalanDOMString theString);
+
+ /**
+ * Determine whether or not a string contains
+ * a valid floating point number.
+ *
+ * @param theString The string to check.
+ * @return true if the string is valid, false if not.
+ */
+ static bool
+ isValid(const XalanDOMChar* theString);
+
+ /**
+ * Convert a string to a double value. Returns
+ * NaN if the string is not a valid floating
+ * point number.
+ *
+ * @param theString The string to convert.
+ * @return The result of the conversion
+ */
static double
toDouble(const XalanDOMString& theString);
+ /**
+ * Convert a string to a double value. Returns
+ * NaN if the string is not a valid floating
+ * point number.
+ *
+ * @param theString The string to convert.
+ * @return The result of the conversion
+ */
static double
toDouble(const XalanDOMChar* theString);