blob: 78e4a101e24894f6876f703cb413295ba1366600 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: XSValue.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLStringTokenizer.hpp>
#include <xercesc/util/XMLBigDecimal.hpp>
#include <xercesc/util/XMLBigInteger.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/util/XMLDouble.hpp>
#include <xercesc/util/XMLDateTime.hpp>
#include <xercesc/util/HexBin.hpp>
#include <xercesc/util/Base64.hpp>
#include <xercesc/util/XMLUri.hpp>
#include <xercesc/util/XMLChar.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/util/XMLInitializer.hpp>
#include <xercesc/util/regx/RegularExpression.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/NumberFormatException.hpp>
XERCES_CPP_NAMESPACE_BEGIN
/*** issues
*
* 1. For float, double, datetime family, the validation is almost similar to getActualValue
*
*
* DataType DataGroup
* num dtm str validation canonical actual-value
* ======================================================================================================
* dt_string str [2] Char NA content
* dt_boolean str {true, false, 1, 0} {true, false} bool
* dt_decimal num lexical only yes double
* dt_float num lexical/value yes double
* dt_double num lexical/value yes double
* ---------------------------------------------------------------------------------------------------------
* 5 dt_duration dtm yes NA struct datetime
* dt_dateTime dtm yes yes struct datetime
* dt_time dtm yes yes struct datetime
* dt_date dtm yes NA struct datetime
* dt_gYearMonth dtm yes NA struct datetime
* ---------------------------------------------------------------------------------------------------------
* 10 dt_gYear dtm yes NA struct datetime
* dt_gMonthDay dtm yes NA struct datetime
* dt_gDay dtm yes NA struct datetime
* dt_gMonth dtm yes NA struct datetime
* dt_hexBinary str decoding ([a-f]) unsigned long ?
* ---------------------------------------------------------------------------------------------------------
* 15 dt_base64Binary str decoding NA (errata?) unsigned long ?
* dt_anyURI str yes NA content
* dt_QName str a:b , [6]QName NA content
* dt_NOTATION str [6]QName NA content
* dt_normalizedString str no #xD #xA #x9 NA content
* ---------------------------------------------------------------------------------------------------------
* 20 dt_token str no #xD #xA #x9 traling NA content
* dt_language str language id NA content
* dt_NMTOKEN str [7] Nmtoken NA content
* dt_NMTOKENS str [8] Nmtokens NA content
* dt_Name str [5] Name NA content
* ---------------------------------------------------------------------------------------------------------
* 25 dt_NCName str [4] NCName NA content
* dt_ID str [4] NCName NA content
* dt_IDREF str [4] NCName NA content
* dt_IDREFS str ws seped IDREF NA content
* dt_ENTITY str [4] NCName NA content
* ---------------------------------------------------------------------------------------------------------
* 30 dt_ENTITIES str ws seped ENTITY NA content
* dt_integer num lexical yes long
* dt_nonPositiveInteger num lexical yes long
* dt_negativeInteger num lexical yes long
* dt_long num lexical yes long
* ---------------------------------------------------------------------------------------------------------
* 35 dt_int num lexical yes int
* dt_short num lexical yes short
* dt_byte num lexical yes char
* dt_nonNegativeInteger num lexical yes unsigned long
* dt_unsignedLong num lexical yes unsigned long
* ---------------------------------------------------------------------------------------------------------
* 40 dt_unsignedInt num lexical yes unsigned int
* dt_unsignedShort num lexical yes unsigned short
* dt_unsignedByte num lexical yes unsigned char
* dt_positiveInteger num lexical yes unsigned long
*
***/
const XSValue::DataGroup XSValue::inGroup[XSValue::dt_MAXCOUNT] =
{
dg_strings, dg_strings, dg_numerics, dg_numerics, dg_numerics,
dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes,
dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes, dg_strings,
dg_strings, dg_strings, dg_strings, dg_strings, dg_strings,
dg_strings, dg_strings, dg_strings, dg_strings, dg_strings,
dg_strings, dg_strings, dg_strings, dg_strings, dg_strings,
dg_strings, dg_numerics, dg_numerics, dg_numerics, dg_numerics,
dg_numerics, dg_numerics, dg_numerics, dg_numerics, dg_numerics,
dg_numerics, dg_numerics, dg_numerics, dg_numerics
};
const bool XSValue::numericSign[XSValue::dt_MAXCOUNT] =
{
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, false, false,
false, false, false, false
};
// ---------------------------------------------------------------------------
// Local static functions
// ---------------------------------------------------------------------------
static XMLMutex* sXSValueMutext = 0;
static XMLRegisterCleanup XSValueMutexCleanup;
static RegularExpression* sXSValueRegEx = 0;
static XMLRegisterCleanup XSValueRegExCleanup;
ValueHashTableOf<XSValue::DataType>* XSValue::fDataTypeRegistry = 0;
static XMLRegisterCleanup XSValueRegistryCleanup;
static XMLMutex& gXSValueMutex()
{
if (!sXSValueMutext)
{
XMLMutexLock lockInit(XMLPlatformUtils::fgAtomicMutex);
if (!sXSValueMutext)
{
sXSValueMutext = new (XMLPlatformUtils::fgMemoryManager) XMLMutex(XMLPlatformUtils::fgMemoryManager);
XSValueRegExCleanup.registerCleanup(XSValue::reinitMutex);
}
}
return *sXSValueMutext;
}
static RegularExpression* getRegEx()
{
if (!sXSValueRegEx)
{
// Lock the mutex
XMLMutexLock lockInit(&gXSValueMutex());
if (!sXSValueRegEx)
{
try {
sXSValueRegEx = new (XMLPlatformUtils::fgMemoryManager)
RegularExpression(
XMLUni::fgLangPattern
, SchemaSymbols::fgRegEx_XOption
, XMLPlatformUtils::fgMemoryManager
);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch (...)
{
return 0;
}
XSValueRegExCleanup.registerCleanup(XSValue::reinitRegEx);
}
}
return sXSValueRegEx;
}
void XMLInitializer::initializeXSValueStatics()
{
sXSValueRegEx = new RegularExpression(XMLUni::fgLangPattern, SchemaSymbols::fgRegEx_XOption);
if (sXSValueRegEx) {
XSValueRegExCleanup.registerCleanup(XSValue::reinitRegEx);
}
XSValue::initializeRegistry();
}
XSValue::DataType XSValue::getDataType(const XMLCh* const dtString)
{
if (!fDataTypeRegistry)
{
// Lock the mutex
XMLMutexLock lockInit(&gXSValueMutex());
if (!fDataTypeRegistry)
{
try {
initializeRegistry();
}
catch(const OutOfMemoryException&)
{
throw;
}
catch (...) {
return dt_MAXCOUNT;
}
}
}
if (fDataTypeRegistry->containsKey(dtString)) {
return fDataTypeRegistry->get(dtString);
}
return dt_MAXCOUNT;
}
void XSValue::initializeRegistry()
{
//using the XMLPlatformUtils::fgMemoryManager
fDataTypeRegistry = new ValueHashTableOf<XSValue::DataType>(43);
if (fDataTypeRegistry) {
XSValueRegistryCleanup.registerCleanup(XSValue::reinitRegistry);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_STRING, XSValue::dt_string);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BOOLEAN, XSValue::dt_boolean);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DECIMAL, XSValue::dt_decimal);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_FLOAT, XSValue::dt_float);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DOUBLE, XSValue::dt_double);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DURATION, XSValue::dt_duration);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DATETIME, XSValue::dt_dateTime);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_TIME, XSValue::dt_time);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DATE, XSValue::dt_date);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_YEARMONTH, XSValue::dt_gYearMonth);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_YEAR, XSValue::dt_gYear);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_MONTHDAY, XSValue::dt_gMonthDay);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DAY, XSValue::dt_gDay);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_MONTH, XSValue::dt_gMonth);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_HEXBINARY, XSValue::dt_hexBinary);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BASE64BINARY, XSValue::dt_base64Binary);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_ANYURI, XSValue::dt_anyURI);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_QNAME, XSValue::dt_QName);
fDataTypeRegistry->put((void*) XMLUni::fgNotationString, XSValue::dt_NOTATION);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NORMALIZEDSTRING, XSValue::dt_normalizedString);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_TOKEN, XSValue::dt_token);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_LANGUAGE, XSValue::dt_language);
fDataTypeRegistry->put((void*) XMLUni::fgNmTokenString, XSValue::dt_NMTOKEN);
fDataTypeRegistry->put((void*) XMLUni::fgNmTokensString, XSValue::dt_NMTOKENS);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NAME, XSValue::dt_Name);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NCNAME, XSValue::dt_NCName);
fDataTypeRegistry->put((void*) XMLUni::fgIDString, XSValue::dt_ID);
fDataTypeRegistry->put((void*) XMLUni::fgIDRefString, XSValue::dt_IDREF);
fDataTypeRegistry->put((void*) XMLUni::fgIDRefsString, XSValue::dt_IDREFS);
fDataTypeRegistry->put((void*) XMLUni::fgEntityString, XSValue::dt_ENTITY);
fDataTypeRegistry->put((void*) XMLUni::fgEntitiesString, XSValue::dt_ENTITIES);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_INTEGER, XSValue::dt_integer);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NONPOSITIVEINTEGER, XSValue::dt_nonPositiveInteger);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NEGATIVEINTEGER, XSValue::dt_negativeInteger);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_LONG, XSValue::dt_long);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_INT, XSValue::dt_int);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_SHORT, XSValue::dt_short);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BYTE, XSValue::dt_byte);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NONNEGATIVEINTEGER, XSValue::dt_nonNegativeInteger);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_ULONG, XSValue::dt_unsignedLong);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_UINT, XSValue::dt_unsignedInt);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_USHORT, XSValue::dt_unsignedShort);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_UBYTE, XSValue::dt_unsignedByte);
fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_POSITIVEINTEGER, XSValue::dt_positiveInteger);
}
}
static bool checkTimeZoneError(XSValue::DataType const &datatype
, SchemaDateTimeException const &e )
{
return (((datatype == XSValue::dt_dateTime) || (datatype == XSValue::dt_time) || (datatype == XSValue::dt_date)) &&
((e.getCode() == XMLExcepts::DateTime_tz_noUTCsign) ||
(e.getCode() == XMLExcepts::DateTime_tz_stuffAfterZ) ||
(e.getCode() == XMLExcepts::DateTime_tz_invalid) ||
(e.getCode() == XMLExcepts::DateTime_tz_hh_invalid)));
}
// ---------------------------------------------------------------------------
// Local Data
// ---------------------------------------------------------------------------
static const XMLCh Separator_20[] = {chSpace, chNull};
static const XMLCh Separator_ws[] = {chSpace, chLF, chCR, chHTab, chNull};
// ---------------------------------------------------------------------------
// XSValue: Constructors and Destructor
// ---------------------------------------------------------------------------
XSValue::XSValue(DataType const dt
, MemoryManager* const manager)
:fMemAllocated(false)
,fMemoryManager(manager)
{
fData.f_datatype = dt;
}
XSValue::~XSValue()
{
if (fMemAllocated)
fMemoryManager->deallocate(fData.fValue.f_byteVal);
}
// ---------------------------------------------------------------------------
// XSValue: Public Interface
//
// No exception is thrown from these methods
//
// ---------------------------------------------------------------------------
bool XSValue::validate(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, MemoryManager* const manager)
{
if (!content ||
!*content ||
((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) ||
((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) {
switch (datatype) {
case XSValue::dt_string:
case XSValue::dt_normalizedString:
case XSValue::dt_token:
case XSValue::dt_anyURI:
case XSValue::dt_hexBinary:
case XSValue::dt_base64Binary:
status = st_Init;
return true;
break;
default:
status = st_NoContent;
return false;
break;
}
}
status = st_Init;
switch (inGroup[datatype]) {
case XSValue::dg_numerics:
return validateNumerics(content, datatype, status, manager);
break;
case XSValue::dg_datetimes:
return validateDateTimes(content, datatype, status, manager);
break;
case XSValue::dg_strings:
return validateStrings(content, datatype, status, version, manager);
break;
default:
status = st_UnknownType;
return false;
break;
}
}
XMLCh*
XSValue::getCanonicalRepresentation(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, bool toValidate
, MemoryManager* const manager)
{
if (!content ||
!*content ||
((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) ||
((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) {
status = st_NoContent;
return 0;
}
status = st_Init;
switch (inGroup[datatype]) {
case XSValue::dg_numerics:
return getCanRepNumerics(content, datatype, status, toValidate, manager);
break;
case XSValue::dg_datetimes:
return getCanRepDateTimes(content, datatype, status, toValidate, manager);
break;
case XSValue::dg_strings:
return getCanRepStrings(content, datatype, status, version, toValidate, manager);
break;
default:
status = st_UnknownType;
return 0;
break;
}
}
XSValue* XSValue::getActualValue(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, bool toValidate
, MemoryManager* const manager)
{
if (!content ||
!*content ||
((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) ||
((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) {
status = st_NoContent;
return 0;
}
status = st_Init;
switch (inGroup[datatype]) {
case XSValue::dg_numerics:
return getActValNumerics(content, datatype, status, toValidate, manager);
break;
case XSValue::dg_datetimes:
return getActValDateTimes(content, datatype, status, manager);
break;
case XSValue::dg_strings:
return getActValStrings(content, datatype, status, version, toValidate, manager);
break;
default:
status = st_UnknownType;
return 0;
break;
}
}
// ---------------------------------------------------------------------------
// XSValue: Helpers
// ---------------------------------------------------------------------------
/***
*
* Boundary checking is done against Schema Type's lexcial space
***/
bool
XSValue::validateNumerics(const XMLCh* const content
, DataType datatype
, Status& status
, MemoryManager* const manager)
{
try {
switch (datatype) {
case XSValue::dt_decimal:
XMLBigDecimal::parseDecimal(content, manager);
break;
case XSValue::dt_float:
{
//XMLFloat takes care of 0, -0, -INF, INF and NaN
//XMLFloat::checkBoundary() handles error and outofbound issues
XMLFloat data(content, manager);
break;
}
case XSValue::dt_double:
{
//XMLDouble takes care of 0, -0, -INF, INF and NaN
//XMLDouble::checkBoundary() handles error and outofbound issues
XMLDouble data(content, manager);
break;
}
/***
* For all potentially unrepresentable types
*
* For dt_long, dt_unsignedLong, doing lexical space
* checking ensures consistent behaviour on 32/64 boxes
*
***/
case XSValue::dt_integer:
case XSValue::dt_negativeInteger:
case XSValue::dt_nonPositiveInteger:
case XSValue::dt_nonNegativeInteger:
case XSValue::dt_positiveInteger:
case XSValue::dt_long:
case XSValue::dt_unsignedLong:
{
XMLCh* compareData = (XMLCh*) manager->allocate((XMLString::stringLen(content) + 1) * sizeof(XMLCh));
ArrayJanitor<XMLCh> janName(compareData, manager);
int signValue = 0;
XMLBigInteger::parseBigInteger(content, compareData, signValue, manager);
switch (datatype) {
case XSValue::dt_integer:
//error: no
break;
case XSValue::dt_negativeInteger:
// error: > -1
if (XMLBigInteger::compareValues(compareData
, signValue
, &(XMLUni::fgNegOne[1])
, -1
, manager)
== XMLNumber::GREATER_THAN)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_nonPositiveInteger:
// error: > 0
if (XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgValueZero
, 0
, manager)
== XMLNumber::GREATER_THAN)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_nonNegativeInteger:
// error: < 0
if (XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgValueZero
, 0
, manager)
== XMLNumber::LESS_THAN)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_positiveInteger:
// error: < 1
if (XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgValueOne
, 1
, manager)
== XMLNumber::LESS_THAN)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_long:
// error: < -9223372036854775808 || > 9223372036854775807
if ((XMLBigInteger::compareValues(compareData
, signValue
, &(XMLUni::fgLongMinInc[1])
, -1
, manager)
== XMLNumber::LESS_THAN) ||
(XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgLongMaxInc
, 1
, manager)
== XMLNumber::GREATER_THAN))
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_unsignedLong:
// error: < 0 || > 18446744073709551615
if ((XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgValueZero
, 0
, manager)
== XMLNumber::LESS_THAN) ||
(XMLBigInteger::compareValues(compareData
, signValue
, XMLUni::fgULongMaxInc
, 1
, manager)
== XMLNumber::GREATER_THAN))
{
status = st_FOCA0002;
return false;
}
break;
default:
status = st_NotSupported;
return false;
break;
}
break;
}
case XSValue::dt_int:
case XSValue::dt_short:
case XSValue::dt_byte:
case XSValue::dt_unsignedInt:
case XSValue::dt_unsignedShort:
case XSValue::dt_unsignedByte:
{
t_value actVal;
if ( !getActualNumericValue(
content
, status
, actVal
, manager
, datatype
)
)
{
return false;
}
break;
}
default:
return false;
} // end switch
return true; //both valid chars and within boundary
}
catch (const NumberFormatException&)
{
//getActValue()/getCanonical() need to know the failure details
//if validation is required
status = st_FOCA0002;
return false;
}
}
bool XSValue::validateDateTimes(const XMLCh* const input_content
, DataType datatype
, Status& status
, MemoryManager* const manager)
{
XMLCh* content = XMLString::replicate(input_content, manager);
ArrayJanitor<XMLCh> janTmpName(content, manager);
XMLString::trim(content);
try
{
XMLDateTime coreDate = XMLDateTime(content, manager);
switch (datatype) {
case XSValue::dt_duration:
coreDate.parseDuration();
break;
case XSValue::dt_dateTime:
coreDate.parseDateTime();
break;
case XSValue::dt_time:
coreDate.parseTime();
break;
case XSValue::dt_date:
coreDate.parseDate();
break;
case XSValue::dt_gYearMonth:
coreDate.parseYearMonth();
break;
case XSValue::dt_gYear:
coreDate.parseYear();
break;
case XSValue::dt_gMonthDay:
coreDate.parseMonthDay();
break;
case XSValue::dt_gDay:
coreDate.parseDay();
break;
case XSValue::dt_gMonth:
coreDate.parseMonth();
break;
default:
return false;
break;
}
return true; //parsing succeed
}
catch (const SchemaDateTimeException &e)
{
status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002;
return false;
}
catch (const NumberFormatException&)
{
//getActValue()/getCanonical() need to know the failure details
//if validation is required
status = st_FOCA0002;
return false;
}
}
bool XSValue::validateStrings(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, MemoryManager* const manager)
{
bool isValid = true;
switch (datatype) {
case XSValue::dt_boolean:
{
unsigned int i = 0;
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
for (; i < XMLUni::fgBooleanValueSpaceArraySize; i++) {
if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[i]))
break;
}
if (XMLUni::fgBooleanValueSpaceArraySize == i) {
isValid = false;
}
break;
}
case XSValue::dt_hexBinary:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
if (HexBin::getDataLength(tmpStrValue) == -1) {
isValid = false;
}
}
break;
case XSValue::dt_base64Binary:
if (Base64::getDataLength(content, manager) == -1) {
isValid = false;
}
break;
case XSValue::dt_anyURI:
if (XMLUri::isValidURI(true, content) == false) {
isValid = false;
}
break;
case XSValue::dt_QName:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
isValid = (version == ver_10) ?
XMLChar1_0::isValidQName(tmpStrValue, XMLString::stringLen(tmpStrValue)) :
XMLChar1_1::isValidQName(tmpStrValue, XMLString::stringLen(tmpStrValue));
}
break;
case XSValue::dt_NOTATION:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
if ( XMLString::isValidNOTATION(tmpStrValue, manager) == false) {
isValid = false;
}
}
break;
case XSValue::dt_string:
{
const XMLCh* rawPtr = content;
if (version == ver_10) {
while (*rawPtr)
if (!XMLChar1_0::isXMLChar(*rawPtr++)) {
isValid = false;
break;
}
}
else {
while (*rawPtr)
if (!XMLChar1_1::isXMLChar(*rawPtr++)) {
isValid = false;
break;
}
}
break;
}
case XSValue::dt_normalizedString:
{
const XMLCh* rawPtr = content;
if (version == ver_10) {
while (*rawPtr) {
if (!XMLChar1_0::isXMLChar(*rawPtr)) {
isValid = false;
break;
}
else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) {
isValid = false;
break;
}
else {
rawPtr++;
}
}
}
else {
while (*rawPtr) {
if (!XMLChar1_1::isXMLChar(*rawPtr)) {
isValid = false;
break;
}
else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) {
isValid = false;
break;
}
else {
rawPtr++;
}
}
}
break;
}
case XSValue::dt_token:
case XSValue::dt_language:
{
unsigned int strLen = XMLString::stringLen(content);
const XMLCh* rawPtr = content;
bool inWS = false;
if (version == ver_10) {
// Check leading/Trailing white space
if (XMLChar1_0::isWhitespace(content[0]) ||
XMLChar1_0::isWhitespace(content[strLen - 1]) ) {
isValid = false;
}
else {
while (*rawPtr) {
if (!XMLChar1_0::isXMLChar(*rawPtr)) {
isValid = false;
break;
}
else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) {
isValid = false;
break;
}
else if (XMLChar1_0::isWhitespace(*rawPtr)) {
if (inWS) {
isValid = false;
break;
}
else {
inWS = true;
}
}
else {
inWS = false;
}
rawPtr++;
}
}
}
else {
// Check leading/Trailing white space
if (XMLChar1_1::isWhitespace(content[0]) ||
XMLChar1_1::isWhitespace(content[strLen - 1]) ) {
isValid = false;
}
else {
while (*rawPtr) {
if (!XMLChar1_1::isXMLChar(*rawPtr)) {
isValid = false;
break;
}
else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) {
isValid = false;
break;
}
else if (XMLChar1_1::isWhitespace(*rawPtr)) {
if (inWS) {
isValid = false;
break;
}
else {
inWS = true;
}
}
else {
inWS = false;
}
rawPtr++;
}
}
}
if (isValid == true && datatype == XSValue::dt_language) {
RegularExpression* regEx = getRegEx();
if (!regEx) {
status = st_CantCreateRegEx;
isValid = false;
}
else {
if (regEx->matches(content, manager) == false) {
isValid = false;
}
}
}
break;
}
case XSValue::dt_NMTOKEN:
isValid = (version == ver_10) ?
XMLChar1_0::isValidNmtoken(content, XMLString::stringLen(content)) :
XMLChar1_1::isValidNmtoken(content, XMLString::stringLen(content));
break;
case XSValue::dt_NMTOKENS:
// [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
{
XMLStringTokenizer tokenizer(content, Separator_20, manager);
if (version == ver_10) {
while (tokenizer.hasMoreTokens()) {
const XMLCh* token = tokenizer.nextToken();
if (!XMLChar1_0::isValidNmtoken(token, XMLString::stringLen(token))) {
isValid = false;
break;
}
}
}
else {
while (tokenizer.hasMoreTokens()) {
const XMLCh* token = tokenizer.nextToken();
if (!XMLChar1_1::isValidNmtoken(token, XMLString::stringLen(token))) {
isValid = false;
break;
}
}
}
break;
}
case XSValue::dt_Name:
isValid = (version == ver_10) ?
XMLChar1_0::isValidName(content) :
XMLChar1_1::isValidName(content);
break;
case XSValue::dt_NCName:
case XSValue::dt_ID:
case XSValue::dt_IDREF:
case XSValue::dt_ENTITY:
isValid = (version == ver_10) ?
XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) :
XMLChar1_1::isValidNCName(content, XMLString::stringLen(content));
break;
case XSValue::dt_ENTITIES:
case XSValue::dt_IDREFS:
{
XMLStringTokenizer tokenizer(content, Separator_ws, manager);
if (version == ver_10 ) {
while (tokenizer.hasMoreTokens()) {
const XMLCh* token = tokenizer.nextToken();
if (!XMLChar1_0::isValidNCName(token, XMLString::stringLen(token))) {
isValid = false;
break;
}
}
}
else {
while (tokenizer.hasMoreTokens()) {
const XMLCh* token = tokenizer.nextToken();
if (!XMLChar1_1::isValidNCName(token, XMLString::stringLen(token))) {
isValid = false;
break;
}
}
}
}
break;
default:
status = st_NotSupported;
isValid = false;
break;
}
if (isValid == false && status == st_Init) {
status = st_FOCA0002;
}
return isValid;
}
XMLCh* XSValue::getCanRepNumerics(const XMLCh* const content
, DataType datatype
, Status& status
, bool toValidate
, MemoryManager* const manager)
{
try
{
// getCanonicalRepresentation does lexical space validation only
// (no range checking), therefore if validation is required,
// we need to pass the content to the validate interface for complete checking
if (toValidate && !validateNumerics(content, datatype, status, manager))
return 0;
XMLCh* retVal = 0;
if (datatype == XSValue::dt_decimal)
{
retVal = XMLBigDecimal::getCanonicalRepresentation(content, manager);
if (!retVal)
status = st_FOCA0002;
return retVal;
}
else if (datatype == XSValue::dt_float || datatype == XSValue::dt_double )
{
// In XML4C, no float or double is treated as out of range
// it gets converted to INF, -INF or zero.
// The getCanonical method should treat double & float the
// same way as the rest of XML4C for consistentcy so need
// to getActualValue and see if it was converted.
XSValue* xsval = getActValNumerics(content, datatype, status, false, manager);
if (!xsval) {
status = st_FOCA0002;
return retVal;
}
DoubleFloatType enumVal;
if (datatype == XSValue::dt_float) {
enumVal = xsval->fData.fValue.f_floatType.f_floatEnum;
}
else {
enumVal = xsval->fData.fValue.f_doubleType.f_doubleEnum;
}
delete xsval;
switch(enumVal) {
case DoubleFloatType_NegINF:
retVal = XMLString::replicate(XMLUni::fgNegINFString, manager);
break;
case DoubleFloatType_PosINF:
retVal = XMLString::replicate(XMLUni::fgPosINFString, manager);
break;
case DoubleFloatType_NaN:
retVal = XMLString::replicate(XMLUni::fgNaNString, manager);
break;
case DoubleFloatType_Zero:
retVal = XMLString::replicate(XMLUni::fgPosZeroString, manager);
break;
default: //DoubleFloatType_Normal
retVal = XMLAbstractDoubleFloat::getCanonicalRepresentation(content, manager);
if (!retVal)
status = st_FOCA0002;
break;
}
return retVal;
}
else
{
retVal = XMLBigInteger::getCanonicalRepresentation(content, manager, datatype == XSValue::dt_nonPositiveInteger);
if (!retVal)
status = st_FOCA0002;
return retVal;
}
}
catch (const NumberFormatException&)
{
status = st_FOCA0002;
return 0;
}
}
XMLCh* XSValue::getCanRepDateTimes(const XMLCh* const input_content
, DataType datatype
, Status& status
, bool toValidate
, MemoryManager* const manager)
{
XMLCh* content = XMLString::replicate(input_content, manager);
ArrayJanitor<XMLCh> janTmpName(content, manager);
XMLString::trim(content);
try
{
XMLDateTime coreDate = XMLDateTime(content, manager);
switch (datatype) {
case XSValue::dt_dateTime:
//we need this parsing
coreDate.parseDateTime();
return coreDate.getDateTimeCanonicalRepresentation(manager);
break;
case XSValue::dt_time:
// we need this parsing
coreDate.parseTime();
return coreDate.getTimeCanonicalRepresentation(manager);
break;
case XSValue::dt_date:
// we need this parsing
coreDate.parseDate();
return coreDate.getDateCanonicalRepresentation(manager);
break;
case XSValue::dt_duration:
case XSValue::dt_gYearMonth:
case XSValue::dt_gYear:
case XSValue::dt_gMonthDay:
case XSValue::dt_gDay:
case XSValue::dt_gMonth:
{
if (!(toValidate && !validateDateTimes(content, datatype, status, manager)))
status = st_NoCanRep;
return 0;
}
break;
default:
return 0;
break;
}
}
catch (SchemaDateTimeException &e)
{
status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002;
}
catch (const NumberFormatException&)
{
status = st_FOCA0002;
}
return 0;
}
XMLCh* XSValue::getCanRepStrings(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, bool toValidate
, MemoryManager* const manager)
{
switch (datatype) {
case XSValue::dt_boolean:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
//always validate before getting canRep
if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[0]) ||
XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[2]) )
{
return XMLString::replicate(XMLUni::fgBooleanValueSpace[0], manager);
}
else if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[1]) ||
XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[3]) )
{
return XMLString::replicate(XMLUni::fgBooleanValueSpace[1], manager);
}
else
{
status = st_FOCA0002;
return 0;
}
}
break;
case XSValue::dt_hexBinary:
{
//HexBin::getCanonicalRepresentation does validation automatically
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
XMLCh* canRep = HexBin::getCanonicalRepresentation(tmpStrValue, manager);
if (!canRep)
status = st_FOCA0002;
return canRep;
break;
}
case XSValue::dt_base64Binary:
{
//Base64::getCanonicalRepresentation does validation automatically
XMLCh* canRep = Base64::getCanonicalRepresentation(content, manager);
if (!canRep)
status = st_FOCA0002;
return canRep;
break;
}
case XSValue::dt_anyURI:
case XSValue::dt_QName:
case XSValue::dt_NOTATION:
case XSValue::dt_string:
case XSValue::dt_normalizedString:
case XSValue::dt_token:
case XSValue::dt_language:
case XSValue::dt_NMTOKEN:
case XSValue::dt_NMTOKENS:
case XSValue::dt_Name:
case XSValue::dt_NCName:
case XSValue::dt_ID:
case XSValue::dt_IDREF:
case XSValue::dt_ENTITY:
case XSValue::dt_ENTITIES:
case XSValue::dt_IDREFS:
if (toValidate && !validateStrings(content, datatype, status, version, manager))
status = st_FOCA0002;
else
status = st_NoCanRep;
return 0;
break;
default:
return 0;
break;
}
return 0;
}
XSValue*
XSValue::getActValNumerics(const XMLCh* const content
, DataType datatype
, Status& status
, bool toValidate
, MemoryManager* const manager)
{
try {
switch (datatype) {
case XSValue::dt_decimal:
{
if (toValidate) {
XMLBigDecimal::parseDecimal(content, manager);
}
//Prepare the double value
XMLDouble data(content, manager);
if (data.isDataConverted())
{
status = st_FOCA0001;
return 0;
}
XSValue* retVal = new (manager) XSValue(dt_decimal, manager);
retVal->fData.fValue.f_decimal.f_dvalue = data.getValue();
return retVal;
break;
}
case XSValue::dt_float:
{
//XMLFloat takes care of 0, -0, -INF, INF and NaN
//XMLFloat::checkBoundary() handles error and outofbound issues
XMLFloat data(content, manager);
XSValue* retVal = new (manager) XSValue(dt_float, manager);
if (data.isDataConverted())
{
retVal->fData.fValue.f_floatType.f_float = 0.0;
retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_Zero;
switch(data.getType()) {
case XMLAbstractDoubleFloat::NegINF:
retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_NegINF;
break;
case XMLAbstractDoubleFloat::PosINF:
retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_PosINF;
break;
case XMLAbstractDoubleFloat::NaN:
retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_NaN;
break;
default:
break;
}
}
else {
retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_Normal;
retVal->fData.fValue.f_floatType.f_float = (float) data.getValue();
}
return retVal;
break;
}
case XSValue::dt_double:
{
//XMLDouble takes care of 0, -0, -INF, INF and NaN
//XMLDouble::checkBoundary() handles error and outofbound issues
XMLDouble data(content, manager);
XSValue* retVal = new (manager) XSValue(dt_double, manager);
if (data.isDataConverted())
{
retVal->fData.fValue.f_doubleType.f_double = 0.0;
retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_Zero;
switch(data.getType()) {
case XMLAbstractDoubleFloat::NegINF:
retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_NegINF;
break;
case XMLAbstractDoubleFloat::PosINF:
retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_PosINF;
break;
case XMLAbstractDoubleFloat::NaN:
retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_NaN;
break;
default:
break;
}
}
else {
retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_Normal;
retVal->fData.fValue.f_doubleType.f_double = data.getValue();
}
return retVal;
break;
}
case XSValue::dt_integer:
case XSValue::dt_negativeInteger:
case XSValue::dt_nonPositiveInteger:
case XSValue::dt_nonNegativeInteger:
case XSValue::dt_positiveInteger:
case XSValue::dt_long:
case XSValue::dt_int:
case XSValue::dt_short:
case XSValue::dt_byte:
case XSValue::dt_unsignedLong:
case XSValue::dt_unsignedInt:
case XSValue::dt_unsignedShort:
case XSValue::dt_unsignedByte:
{
t_value actVal;
if ( !getActualNumericValue(
content
, status
, actVal
, manager
, datatype
)
)
{
//status has been set by getActualNumericValue
return 0;
}
XSValue* retVal = new (manager) XSValue(datatype, manager);
switch (datatype) {
case XSValue::dt_integer:
retVal->fData.fValue.f_long = actVal.f_long;
break;
case XSValue::dt_negativeInteger:
retVal->fData.fValue.f_long = actVal.f_long;
break;
case XSValue::dt_nonPositiveInteger:
retVal->fData.fValue.f_long = actVal.f_long;
break;
case XSValue::dt_nonNegativeInteger:
retVal->fData.fValue.f_long = actVal.f_ulong;
break;
case XSValue::dt_positiveInteger:
retVal->fData.fValue.f_long = actVal.f_ulong;
break;
case XSValue::dt_long:
retVal->fData.fValue.f_long = actVal.f_long;
break;
case XSValue::dt_int:
retVal->fData.fValue.f_int = (int) actVal.f_long;
break;
case XSValue::dt_short:
retVal->fData.fValue.f_short = (short) actVal.f_long;
break;
case XSValue::dt_byte:
retVal->fData.fValue.f_char = (char) actVal.f_long;
break;
case XSValue::dt_unsignedLong:
retVal->fData.fValue.f_ulong = actVal.f_ulong;
break;
case XSValue::dt_unsignedInt:
retVal->fData.fValue.f_uint = (unsigned int) actVal.f_ulong;
break;
case XSValue::dt_unsignedShort:
retVal->fData.fValue.f_ushort = (unsigned short) actVal.f_ulong;
break;
case XSValue::dt_unsignedByte:
retVal->fData.fValue.f_uchar = (unsigned char) actVal.f_ulong;
break;
default:
return 0;
break;
}
return retVal;
break;
}
default:
return 0;
break;
} // end switch
}
catch (const NumberFormatException&)
{
status = st_FOCA0002;
}
return 0;
}
XSValue*
XSValue::getActValDateTimes(const XMLCh* const input_content
, DataType datatype
, Status& status
, MemoryManager* const manager)
{
XMLCh* content = XMLString::replicate(input_content, manager);
ArrayJanitor<XMLCh> janTmpName(content, manager);
XMLString::trim(content);
try
{
//Need not check if validation is requested since
//parsing functions below does the validation automatically
XMLDateTime coreDate = XMLDateTime(content, manager);
switch (datatype) {
case XSValue::dt_duration:
coreDate.parseDuration();
break;
case XSValue::dt_dateTime:
coreDate.parseDateTime();
break;
case XSValue::dt_time:
coreDate.parseTime();
coreDate.fValue[XMLDateTime::CentYear] = 0;
coreDate.fValue[XMLDateTime::Month] = 0;
coreDate.fValue[XMLDateTime::Day] = 0;
break;
case XSValue::dt_date:
coreDate.parseDate();
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
case XSValue::dt_gYearMonth:
coreDate.parseYearMonth();
coreDate.fValue[XMLDateTime::Day] = 0;
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
case XSValue::dt_gYear:
coreDate.parseYear();
coreDate.fValue[XMLDateTime::Month] = 0;
coreDate.fValue[XMLDateTime::Day] = 0;
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
case XSValue::dt_gMonthDay:
coreDate.parseMonthDay();
coreDate.fValue[XMLDateTime::CentYear] = 0;
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
case XSValue::dt_gDay:
coreDate.parseDay();
coreDate.fValue[XMLDateTime::CentYear] = 0;
coreDate.fValue[XMLDateTime::Month] = 0;
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
case XSValue::dt_gMonth:
coreDate.parseMonth();
coreDate.fValue[XMLDateTime::CentYear] = 0;
coreDate.fValue[XMLDateTime::Day] = 0;
coreDate.fValue[XMLDateTime::Hour] = 0;
coreDate.fValue[XMLDateTime::Minute] = 0;
break;
default:
return 0;
break;
}
XSValue* retVal = new (manager) XSValue(datatype, manager);
retVal->fData.fValue.f_datetime.f_year = coreDate.fValue[XMLDateTime::CentYear];
retVal->fData.fValue.f_datetime.f_month = coreDate.fValue[XMLDateTime::Month];
retVal->fData.fValue.f_datetime.f_day = coreDate.fValue[XMLDateTime::Day];
retVal->fData.fValue.f_datetime.f_hour = coreDate.fValue[XMLDateTime::Hour];
retVal->fData.fValue.f_datetime.f_min = coreDate.fValue[XMLDateTime::Minute];
retVal->fData.fValue.f_datetime.f_second = coreDate.fValue[XMLDateTime::Second];
retVal->fData.fValue.f_datetime.f_milisec = coreDate.fMiliSecond;
return retVal;
}
catch (SchemaDateTimeException const &e)
{
status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002;
}
catch (const NumberFormatException&)
{
status = st_FOCA0002;
}
return 0;
}
XSValue*
XSValue::getActValStrings(const XMLCh* const content
, DataType datatype
, Status& status
, XMLVersion version
, bool toValidate
, MemoryManager* const manager)
{
switch (datatype) {
case XSValue::dt_boolean:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
//do validation here more efficiently
if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[0]) ||
XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[2]) )
{
XSValue* retVal = new (manager) XSValue(dt_boolean, manager);
retVal->fData.fValue.f_bool = false;
return retVal;
}
else if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[1]) ||
XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[3]) )
{
XSValue* retVal = new (manager) XSValue(dt_boolean, manager);
retVal->fData.fValue.f_bool = true;
return retVal;
}
else
{
status = st_FOCA0002;
return 0;
}
}
break;
case XSValue::dt_hexBinary:
{
XMLCh* tmpStrValue = XMLString::replicate(content, manager);
ArrayJanitor<XMLCh> janTmpName(tmpStrValue, manager);
XMLString::trim(tmpStrValue);
XMLByte* decodedData = HexBin::decodeToXMLByte(tmpStrValue, manager);
if (!decodedData)
{
status = st_FOCA0002;
return 0;
}
XSValue* retVal = new (manager) XSValue(dt_hexBinary, manager);
retVal->fData.fValue.f_byteVal = decodedData;
retVal->fMemAllocated = true;
return retVal;
break;
}
case XSValue::dt_base64Binary:
{
unsigned int len = 0;
XMLByte* decodedData = Base64::decodeToXMLByte(content, &len, manager);
if (!decodedData)
{
status = st_FOCA0002;
return 0;
}
XSValue* retVal = new (manager) XSValue(dt_base64Binary, manager);
retVal->fData.fValue.f_byteVal = decodedData;
retVal->fMemAllocated = true;
return retVal;
break;
}
case XSValue::dt_anyURI:
case XSValue::dt_QName:
case XSValue::dt_NOTATION:
case XSValue::dt_string:
case XSValue::dt_normalizedString:
case XSValue::dt_token:
case XSValue::dt_language:
case XSValue::dt_NMTOKEN:
case XSValue::dt_NMTOKENS:
case XSValue::dt_Name:
case XSValue::dt_NCName:
case XSValue::dt_ID:
case XSValue::dt_IDREF:
case XSValue::dt_ENTITY:
case XSValue::dt_ENTITIES:
case XSValue::dt_IDREFS:
if (toValidate && !validateStrings(content, datatype, status, version, manager))
status = st_FOCA0002;
else
status = st_NoActVal;
return 0;
break;
default:
return 0;
break;
}
return 0;
}
// ---------------------------------------------------------------------------
// Utilities
// ---------------------------------------------------------------------------
bool XSValue::getActualNumericValue(const XMLCh* const content
, Status& status
, t_value& retVal
, MemoryManager* const manager
, DataType datatype)
{
char *nptr = XMLString::transcode(content, manager);
ArrayJanitor<char> jan(nptr, manager);
char *endptr = 0;
errno = 0;
if (XSValue::numericSign[datatype])
{
retVal.f_long = strtol(nptr, &endptr, (int)10);
}
else
{
if (XMLString::indexOf(content, chDash) != -1)
{
status = st_FOCA0002; //invalid lexcial value
return false;
}
retVal.f_ulong = strtoul(nptr, &endptr, (int)10);
}
// need to check out-of-bounds before checking erange...
switch (datatype) {
case XSValue::dt_nonPositiveInteger:
if (retVal.f_long > 0)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_negativeInteger:
if (retVal.f_long >= 0)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_int:
// strtol will set value to LONG_MIN/LONG_MAX if ERANGE error
if ((retVal.f_long < INT_MIN) ||
(retVal.f_long > INT_MAX) ||
(errno == ERANGE))
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_short:
if ((retVal.f_long < SHRT_MIN) ||
(retVal.f_long > SHRT_MAX))
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_byte:
if ((retVal.f_long < SCHAR_MIN) ||
(retVal.f_long > SCHAR_MAX))
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_unsignedInt:
// strtoul will set value to LONG_INT if ERANGE error
if ((retVal.f_ulong > UINT_MAX) ||
(errno == ERANGE))
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_unsignedShort:
if (retVal.f_ulong > USHRT_MAX)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_unsignedByte:
if (retVal.f_ulong > UCHAR_MAX)
{
status = st_FOCA0002;
return false;
}
break;
case XSValue::dt_positiveInteger:
if (retVal.f_ulong == 0)
{
status = st_FOCA0002;
return false;
}
break;
default:
break;
} // end switch
// check if overflow/underflow occurs
if (errno == ERANGE)
{
status = st_FOCA0003;
return false;
}
// check if all chars are valid char. If they are, endptr will
// pointer to the null terminator, or all of the remaining
// characters will be whitespace characters.
while (*endptr != '\0')
{
const char ch = *endptr;
if (ch == '\t' || ch == '\n' || ch == '\r' || ch == ' ')
{
++endptr;
}
else
{
status = st_FOCA0002;
return false;
}
}
return true;
}
// -----------------------------------------------------------------------
// Reinitialise the mutex and RegEx
// -----------------------------------------------------------------------
void XSValue::reinitMutex()
{
delete sXSValueMutext;
sXSValueMutext = 0;
}
void XSValue::reinitRegEx()
{
delete sXSValueRegEx;
sXSValueRegEx = 0;
}
void XSValue::reinitRegistry()
{
delete fDataTypeRegistry;
fDataTypeRegistry = 0;
}
XERCES_CPP_NAMESPACE_END