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);