blob: 50d6e003be0c8aa937aedd08d0030776258fa82a [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
* $Log$
* Revision 1.2 2002/05/03 16:05:45 peiyongz
* Bug 7341: Missing newline at end of util and DOM source files,
* patch from Martin Kalen.
*
* Revision 1.1.1.1 2002/02/01 22:22:15 peiyongz
* sane_include
*
* Revision 1.13 2001/11/19 21:33:42 peiyongz
* Reorganization: Double/Float
*
* Revision 1.12 2001/11/19 17:27:55 peiyongz
* Boundary Values updated
*
* Revision 1.11 2001/10/26 16:37:46 peiyongz
* Add thread safe code
*
* Revision 1.9 2001/09/20 13:11:41 knoaman
* Regx + misc. fixes
*
* Revision 1.8 2001/09/14 13:57:59 peiyongz
* exponent is a must if 'E' or 'e' is present.
*
* Revision 1.7 2001/08/23 11:54:26 tng
* Add newline at the end and various typo fixes.
*
* Revision 1.6 2001/08/21 15:10:15 peiyongz
* Bugzilla# 3017: MSVC5.0: C2202: 'compareSpecial' : not all
* control paths return a value
*
* Revision 1.5 2001/08/14 22:10:20 peiyongz
* new exception message added
*
* Revision 1.4 2001/07/31 17:38:16 peiyongz
* Fix: memory leak by static (boundry) objects
*
* Revision 1.3 2001/07/31 13:48:29 peiyongz
* fValue removed
*
* Revision 1.2 2001/07/27 20:43:53 peiyongz
* copy ctor: to check for special types.
*
* Revision 1.1 2001/07/26 20:41:37 peiyongz
* XMLFloat
*
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/NumberFormatException.hpp>
// ---------------------------------------------------------------------------
// local data member
// ---------------------------------------------------------------------------
//
// 2^24 x 2^104 = 2^128 = 3.4028236692093846346337460743177e+38
// +
// 3.4028 236692 093846 346337 460743 177
// e+38
//
static const XMLCh FLT_MAX_POSITIVE[] =
{
chPlus,
chDigit_3, chPeriod, chDigit_4, chDigit_0, chDigit_2, chDigit_8,
chDigit_2, chDigit_3, chDigit_6, chDigit_6, chDigit_9, chDigit_2,
chDigit_0, chDigit_9, chDigit_3, chDigit_8, chDigit_4, chDigit_6,
chDigit_3, chDigit_4, chDigit_6, chDigit_3, chDigit_3, chDigit_7,
chDigit_4, chDigit_6, chDigit_0, chDigit_7, chDigit_4, chDigit_3,
chDigit_1, chDigit_7, chDigit_7,
chLatin_E, chPlus, chDigit_3, chDigit_8, chNull
};
//
// 2^0 x 2^-149 = 2^-149 = 1.4012984643248170709237295832899e-45
// +
// 1.4012 984643 248170 709237 295832 899
// e-45
//
static const XMLCh FLT_MIN_POSITIVE[] =
{
chPlus,
chDigit_1, chPeriod, chDigit_4, chDigit_0, chDigit_1, chDigit_2,
chDigit_9, chDigit_8, chDigit_4, chDigit_6, chDigit_4, chDigit_3,
chDigit_2, chDigit_4, chDigit_8, chDigit_1, chDigit_7, chDigit_0,
chDigit_7, chDigit_0, chDigit_9, chDigit_2, chDigit_3, chDigit_7,
chDigit_2, chDigit_9, chDigit_5, chDigit_8, chDigit_3, chDigit_2,
chDigit_8, chDigit_9, chDigit_9,
chLatin_E, chDash, chDigit_4, chDigit_5, chNull
};
static const XMLCh FLT_MAX_NEGATIVE[] =
{
chDash,
chDigit_3, chPeriod, chDigit_4, chDigit_0, chDigit_2, chDigit_8,
chDigit_2, chDigit_3, chDigit_6, chDigit_6, chDigit_9, chDigit_2,
chDigit_0, chDigit_9, chDigit_3, chDigit_8, chDigit_4, chDigit_6,
chDigit_3, chDigit_4, chDigit_6, chDigit_3, chDigit_3, chDigit_7,
chDigit_4, chDigit_6, chDigit_0, chDigit_7, chDigit_4, chDigit_3,
chDigit_1, chDigit_7, chDigit_7,
chLatin_E, chPlus, chDigit_3, chDigit_8, chNull
};
static const XMLCh FLT_MIN_NEGATIVE[] =
{
chDash,
chDigit_1, chPeriod, chDigit_4, chDigit_0, chDigit_1, chDigit_2,
chDigit_9, chDigit_8, chDigit_4, chDigit_6, chDigit_4, chDigit_3,
chDigit_2, chDigit_4, chDigit_8, chDigit_1, chDigit_7, chDigit_0,
chDigit_7, chDigit_0, chDigit_9, chDigit_2, chDigit_3, chDigit_7,
chDigit_2, chDigit_9, chDigit_5, chDigit_8, chDigit_3, chDigit_2,
chDigit_8, chDigit_9, chDigit_9,
chLatin_E, chDash, chDigit_4, chDigit_5, chNull
};
//
// maxNegativeValue < minNegativeValue < 0 < minPositiveValue < maxPositiveValue
// They are all "Inclusive value"
//
static XMLFloat* maxNegativeValue = 0;
static XMLFloat* minNegativeValue = 0;
static XMLFloat* minPositiveValue = 0;
static XMLFloat* maxPositiveValue = 0;
static XMLMutex* sFloatMutex = 0;
static XMLRegisterCleanup XMLFloatCleanup;
// ---------------------------------------------------------------------------
// ctor/dtor
// ---------------------------------------------------------------------------
XMLFloat::XMLFloat(const XMLCh* const strValue)
:XMLAbstractDoubleFloat()
{
init(strValue);
}
XMLFloat::~XMLFloat()
{
}
//
//
void XMLFloat::checkBoundary(const XMLCh* const strValue)
{
if (!sFloatMutex)
{
XMLMutex* tmpMutex = new XMLMutex;
if (XMLPlatformUtils::compareAndSwap((void**)&sFloatMutex, tmpMutex, 0))
{
// Some other thread beat us to it, so let's clean up ours.
delete tmpMutex;
}
else
{
//
// the thread who creates the mutex succesfully, to
// initialize the followings
//
maxNegativeValue = new XMLFloat(FLT_MAX_NEGATIVE);
minNegativeValue = new XMLFloat(FLT_MIN_NEGATIVE);
minPositiveValue = new XMLFloat(FLT_MIN_POSITIVE);
maxPositiveValue = new XMLFloat(FLT_MAX_POSITIVE);
// This is the real mutex. Register it for cleanup at Termination.
XMLFloatCleanup.registerCleanup(reinitXMLFloat);
}
}
//
// by-pass boundary check for boundary value itself
//
if (( XMLString::compareString(strValue, FLT_MAX_NEGATIVE) == 0 ) ||
( XMLString::compareString(strValue, FLT_MIN_NEGATIVE) == 0 ) ||
( XMLString::compareString(strValue, FLT_MIN_POSITIVE) == 0 ) ||
( XMLString::compareString(strValue, FLT_MAX_POSITIVE) == 0 ) )
return;
// error: this < maxNegativeValue
if ( compareValues(this, maxNegativeValue) == -1 )
{
ThrowXML2(NumberFormatException
, XMLExcepts::XMLNUM_DBL_FLT_maxNeg
, strValue
, FLT_MAX_NEGATIVE);
}
// error: this > maxPositiveValue
if ( compareValues(this, maxPositiveValue) == 1 )
{
ThrowXML2(NumberFormatException
, XMLExcepts::XMLNUM_DBL_FLT_maxPos
, strValue
, FLT_MAX_POSITIVE);
}
// error: minNegativeValue < this < minPositiveValue
// value is not be representable
if (( compareValues(this, minNegativeValue) == 1 ) &&
( compareValues(this, minPositiveValue) == -1 ) )
{
ThrowXML3(NumberFormatException
, XMLExcepts::XMLNUM_DBL_FLT_minNegPos
, strValue
, FLT_MIN_NEGATIVE
, FLT_MIN_POSITIVE);
}
}
// -----------------------------------------------------------------------
// Notification that lazy data has been deleted
// -----------------------------------------------------------------------
void XMLFloat::reinitXMLFloat() {
delete sFloatMutex;
sFloatMutex = 0;
delete maxNegativeValue;
maxNegativeValue = 0;
delete minNegativeValue;
minNegativeValue = 0;
delete minPositiveValue;
minPositiveValue = 0;
delete maxPositiveValue;
maxPositiveValue = 0;
}