You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by pe...@apache.org on 2001/11/07 20:16:04 UTC
cvs commit: xml-xerces/c/src/util XMLDateTime.hpp XMLDateTime.cpp Makefile.in
peiyongz 01/11/07 11:16:04
Modified: c/src/util Makefile.in
Added: c/src/util XMLDateTime.hpp XMLDateTime.cpp
Log:
DateTime Port
Revision Changes Path
1.49 +5 -0 xml-xerces/c/src/util/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/util/Makefile.in,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- Makefile.in 2001/10/23 23:09:32 1.48
+++ Makefile.in 2001/11/07 19:16:03 1.49
@@ -55,6 +55,9 @@
#
#
# $Log: Makefile.in,v $
+# Revision 1.49 2001/11/07 19:16:03 peiyongz
+# DateTime Port
+#
# Revision 1.48 2001/10/23 23:09:32 peiyongz
# [Bug#880] patch to PlatformUtils:init()/term() and related. from Mark Weaver
#
@@ -363,6 +366,7 @@
XMLBigDecimal.hpp \
XMLBigInteger.hpp \
XMLDouble.hpp \
+ XMLDateTime.hpp \
XMLChTranscoder.hpp \
XMLInteger.hpp \
XMLIBM1140Transcoder.hpp \
@@ -431,6 +435,7 @@
XMLBigDecimal.$(TO) \
XMLBigInteger.$(TO) \
XMLDouble.$(TO) \
+ XMLDateTime.$(TO) \
XMLChTranscoder.$(TO) \
XMLIBM1140Transcoder.$(TO) \
XMLEBCDICTranscoder.$(TO) \
1.1 xml-xerces/c/src/util/XMLDateTime.hpp
Index: XMLDateTime.hpp
===================================================================
/*
* 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: XMLDateTime.hpp,v 1.1 2001/11/07 19:16:03 peiyongz Exp $
* $Log: XMLDateTime.hpp,v $
* Revision 1.1 2001/11/07 19:16:03 peiyongz
* DateTime Port
*
*/
#ifndef XML_DATETIME_HPP
#define XML_DATETIME_HPP
#include <util/XercesDefs.hpp>
#include <util/XMLNumber.hpp>
#include <util/XMLString.hpp>
#include <util/XMLUniDefs.hpp>
#include <util/RuntimeException.hpp>
class XMLUTIL_EXPORT XMLDateTime : public XMLNumber
{
public:
// to be moved to XMLNumber
enum
{
LESS_THAN = -1,
EQUAL = 0,
GREATER_THAN = 1,
INDETERMINATE = 2
};
// -----------------------------------------------------------------------
// ctors and dtor
// -----------------------------------------------------------------------
XMLDateTime();
XMLDateTime(const XMLCh* const);
~XMLDateTime();
inline void setBuffer(const XMLCh* const);
// -----------------------------------------------------------------------
// Copy ctor and Assignment operators
// -----------------------------------------------------------------------
XMLDateTime(const XMLDateTime&);
XMLDateTime& operator=(const XMLDateTime&);
// -----------------------------------------------------------------------
// Implementation of Abstract Interface
// -----------------------------------------------------------------------
virtual XMLCh* toString() const;
virtual int getSign() const;
// -----------------------------------------------------------------------
// parsers
// -----------------------------------------------------------------------
void parseDateTime(); //DateTime
void parseDate(); //Date
void parseTime(); //Time
void parseDay(); //gDay
void parseMonth(); //gMonth
void parseYear(); //gYear
void parseMonthDay(); //gMonthDay
void parseYearMonth(); //gYearMonth
void parseDuration(); //duration
// -----------------------------------------------------------------------
// Comparison
// -----------------------------------------------------------------------
static int compare(const XMLDateTime* const
, const XMLDateTime* const);
static int compare(const XMLDateTime* const
, const XMLDateTime* const
, bool );
static int compareOrder(const XMLDateTime* const
, const XMLDateTime* const);
private:
// -----------------------------------------------------------------------
// Constant data
// -----------------------------------------------------------------------
//
enum valueIndex
{
CentYear = 0,
Month = 1,
Day = 2,
Hour = 3,
Minute = 4,
Second = 5,
MiliSecond = 6,
utc = 7,
TOTAL_SIZE = 8
};
enum timezoneIndex
{
hh = 0,
mm = 1,
TIMEZONE_ARRAYSIZE = 2
};
enum utcType
{
UTC_UNKNOWN = 0,
UTC_STD = 1, // set in parse() or normalize()
UTC_POS = 2, // set in parse()
UTC_NEG = 3 // set in parse()
};
static const int DATETIMES[4][TOTAL_SIZE];
// -----------------------------------------------------------------------
// Comparison
// -----------------------------------------------------------------------
static int compareResult(short
, short
, bool);
static void addDuration(XMLDateTime* pDuration
, const XMLDateTime* const pBaseDate
, int index);
static int compareResult(const XMLDateTime* const
, const XMLDateTime* const
, bool
, int);
static inline int getRetVal(int, int);
// -----------------------------------------------------------------------
// helper
// -----------------------------------------------------------------------
inline void reset();
inline void assertBuffer() const;
inline void copy(const XMLDateTime&);
// allow multiple parsing
inline void initParser();
inline bool isNormalized() const;
// -----------------------------------------------------------------------
// scaners
// -----------------------------------------------------------------------
void getDate();
void getTime();
void getYearMonth();
void getTimeZone(const int);
void parseTimeZone();
// -----------------------------------------------------------------------
// locator and converter
// -----------------------------------------------------------------------
int findUTCSign(int start);
int indexOf(const int start
, const int end
, const XMLCh ch) const;
int parseInt(const int start
, const int end) const;
int parseIntYear(const int end) const;
// -----------------------------------------------------------------------
// validator and normalizer
// -----------------------------------------------------------------------
void validateDateTime() const;
void normalize();
// -----------------------------------------------------------------------
// Unimplemented operator ==
// -----------------------------------------------------------------------
bool operator==(const XMLDateTime& toCompare) const;
// -----------------------------------------------------------------------
// Private data members
//
// fValue[]
// object representation of date time.
//
// fTimeZone[]
// temporary storage for normalization
//
// fStart, fEnd
// pointers to the portion of fBuffer being parsed
//
// fBuffer
// raw data to be parsed, own it.
//
// -----------------------------------------------------------------------
int fValue[TOTAL_SIZE];
int fTimeZone[TIMEZONE_ARRAYSIZE];
int fStart;
int fEnd;
XMLCh* fBuffer;
};
void XMLDateTime::setBuffer(const XMLCh* const aString)
{
reset();
fBuffer = XMLString::replicate(aString);
fEnd = XMLString::stringLen(fBuffer);
}
void XMLDateTime::reset()
{
for ( int i=0; i < TOTAL_SIZE; i++ )
fValue[i] = 0;
fTimeZone[hh] = fTimeZone[mm] = 0;
fStart = fEnd = 0;
if (fBuffer)
{
delete[] fBuffer;
fBuffer = 0;
}
}
void XMLDateTime::copy(const XMLDateTime& rhs)
{
for ( int i = 0; i < TOTAL_SIZE; i++ )
fValue[i] = rhs.fValue[i];
fTimeZone[hh] = rhs.fTimeZone[hh];
fTimeZone[mm] = rhs.fTimeZone[mm];
fStart = rhs.fStart;
fEnd = rhs.fEnd;
if (fBuffer)
{
delete[] fBuffer;
fBuffer = 0;
}
if (rhs.fBuffer)
fBuffer = XMLString::replicate(rhs.fBuffer);
}
void XMLDateTime::assertBuffer() const
{
if ( ( !fBuffer ) ||
( fBuffer[0] == chNull ) )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//" buffer not set properly"
}
}
void XMLDateTime::initParser()
{
assertBuffer();
fStart = 0; // to ensure scan from the very first beginning
// in case the pointer is updated accidentally by someone else.
}
bool XMLDateTime::isNormalized() const
{
return ( fValue[utc] == UTC_STD ? true : false );
}
int XMLDateTime::getRetVal(int c1, int c2)
{
if ((c1 == LESS_THAN && c2 == GREATER_THAN) ||
(c1 == GREATER_THAN && c2 == LESS_THAN) )
{
return INDETERMINATE;
}
return ( c1 != INDETERMINATE ) ? c1 : c2;
}
#endif
1.1 xml-xerces/c/src/util/XMLDateTime.cpp
Index: XMLDateTime.cpp
===================================================================
/*
* 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: XMLDateTime.cpp,v 1.1 2001/11/07 19:16:03 peiyongz Exp $
* $Log: XMLDateTime.cpp,v $
* Revision 1.1 2001/11/07 19:16:03 peiyongz
* DateTime Port
*
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <stdlib.h>
#include <util/XMLDateTime.hpp>
#include <util/XMLString.hpp>
#include <util/XMLUni.hpp>
#include <util/Janitor.hpp>
//
// constants used to process raw data (fBuffer)
//
// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}['Z']
// [{+|-}hh:mm']
//
static const XMLCh DURATION_STARTER = chLatin_P; // 'P'
static const XMLCh DURATION_Y = chLatin_Y; // 'Y'
static const XMLCh DURATION_M = chLatin_M; // 'M'
static const XMLCh DURATION_D = chLatin_D; // 'D'
static const XMLCh DURATION_H = chLatin_H; // 'H'
static const XMLCh DURATION_S = chLatin_S; // 'S'
static const XMLCh DATE_SEPARATOR = chDash; // '-'
static const XMLCh TIME_SEPARATOR = chColon; // ':'
static const XMLCh TIMEZONE_SEPARATOR = chColon; // ':'
static const XMLCh DATETIME_SEPARATOR = chLatin_T; // 'T'
static const XMLCh MILISECOND_SEPARATOR = chPeriod; // '.'
static const XMLCh UTC_STD_CHAR = chLatin_Z; // 'Z'
static const XMLCh UTC_POS_CHAR = chPlus; // '+'
static const XMLCh UTC_NEG_CHAR = chDash; // '-'
static const XMLCh UTC_SET[] = {UTC_STD_CHAR //"Z+-"
, UTC_POS_CHAR
, UTC_NEG_CHAR
, chNull};
static const int YMD_MIN_SIZE = 10; // CCYY-MM-DD
static const int YMONTH_MIN_SIZE = 7; // CCYY_MM
static const int TIME_MIN_SIZE = 8; // hh:mm:ss
static const int TIMEZONE_SIZE = 5; // hh:mm
static const int DAY_SIZE = 5; // ---DD
static const int MONTH_SIZE = 6; // --MM--
static const int MONTHDAY_SIZE = 7; // --MM-DD
static const int NOT_FOUND = -1;
//define constants to be used in assigning default values for
//all date/time excluding duration
static const int YEAR_DEFAULT = 2000;
static const int MONTH_DEFAULT = 01;
static const int DAY_DEFAULT = 15;
// order-relation on duration is a partial order. The dates below are used to
// for comparison of 2 durations, based on the fact that
// duration x and y is x<=y iff s+x<=s+y
// see 3.2.6 duration W3C schema datatype specs
//
// the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone}
const int XMLDateTime::DATETIMES[4][TOTAL_SIZE] =
{
{1696, 9, 1, 0, 0, 0, 0, UTC_STD},
{1697, 2, 1, 0, 0, 0, 0, UTC_STD},
{1903, 3, 1, 0, 0, 0, 0, UTC_STD},
{1903, 7, 1, 0, 0, 0, 0, UTC_STD}
};
// ---------------------------------------------------------------------------
// local methods
// ---------------------------------------------------------------------------
static inline int fQuotient(int a, int b)
{
div_t div_result = div(a, b);
return div_result.quot;
}
static inline int fQuotient(int temp, int low, int high)
{
return fQuotient(temp - low, high - low);
}
static inline int mod(int a, int b, int quotient)
{
return (a - quotient*b) ;
}
static inline int modulo (int temp, int low, int high)
{
//modulo(a - low, high - low) + low
int a = temp - low;
int b = high - low;
return (mod (a, b, fQuotient(a, b)) + low) ;
}
static inline bool isLeapYear(int year)
{
return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
}
static int maxDayInMonthFor(int year, int month)
{
if ( month == 4 || month == 6 || month == 9 || month == 11 )
{
return 30;
}
else if ( month==2 )
{
if ( isLeapYear(year) )
return 29;
else
return 28;
}
else
{
return 31;
}
}
// ---------------------------------------------------------------------------
// static methods : for duration
// ---------------------------------------------------------------------------
/**
* Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
*
* 3.2.6.2 Order relation on duration
*
* In general, the order-relation on duration is a partial order since there is no
* determinate relationship between certain durations such as one month (P1M) and 30 days (P30D).
* The order-relation of two duration values x and y is x < y iff s+x < s+y for each qualified
* dateTime s in the list below.
*
* These values for s cause the greatest deviations in the addition of dateTimes and durations
*
**/
int XMLDateTime::compare(const XMLDateTime* const pDate1
, const XMLDateTime* const pDate2
, bool strict)
{
//REVISIT: this is unoptimazed vs of comparing 2 durations
// Algorithm is described in 3.2.6.2 W3C Schema Datatype specs
//
int resultA, resultB = INDETERMINATE;
//try and see if the objects are equal
if ( (resultA = compareOrder(pDate1, pDate2)) == EQUAL)
return EQUAL;
//long comparison algorithm is required
XMLDateTime tempA, *pTempA = &tempA;
XMLDateTime tempB, *pTempB = &tempB;
addDuration(pTempA, pDate1, 0);
addDuration(pTempB, pDate2, 0);
resultA = compareOrder(pTempA, pTempB);
if ( resultA == INDETERMINATE )
return INDETERMINATE;
addDuration(pTempA, pDate1, 1);
addDuration(pTempB, pDate2, 1);
resultB = compareOrder(pTempA, pTempB);
resultA = compareResult(resultA, resultB, strict);
if ( resultA == INDETERMINATE )
return INDETERMINATE;
addDuration(pTempA, pDate1, 2);
addDuration(pTempB, pDate2, 2);
resultB = compareOrder(pTempA, pTempB);
resultA = compareResult(resultA, resultB, strict);
if ( resultA == INDETERMINATE )
return INDETERMINATE;
addDuration(pTempA, pDate1, 3);
addDuration(pTempB, pDate2, 3);
resultB = compareOrder(pTempA, pTempB);
resultA = compareResult(resultA, resultB, strict);
return resultA;
}
//
// Form a new XMLDateTime with duration and baseDate array
// Note: C++ Java
// fNewDate duration
// fDuration date
//
void XMLDateTime::addDuration(XMLDateTime* fNewDate
, const XMLDateTime* const fDuration
, int index)
{
//REVISIT: some code could be shared between normalize() and this method,
// however is it worth moving it? The structures are different...
//
fNewDate->reset();
//add months (may be modified additionaly below)
int temp = DATETIMES[index][Month] + fDuration->fValue[Month];
fNewDate->fValue[Month] = modulo(temp, 1, 13);
int carry = fQuotient(temp, 1, 13);
//add years (may be modified additionaly below)
fNewDate->fValue[CentYear] = DATETIMES[index][CentYear] + fDuration->fValue[CentYear] + carry;
//add seconds
temp = DATETIMES[index][Second] + fDuration->fValue[Second];
carry = fQuotient (temp, 60);
fNewDate->fValue[Second] = mod(temp, 60, carry);
//add minutes
temp = DATETIMES[index][Minute] + fDuration->fValue[Minute] + carry;
carry = fQuotient(temp, 60);
fNewDate->fValue[Minute] = mod(temp, 60, carry);
//add hours
temp = DATETIMES[index][Hour] + fDuration->fValue[Hour] + carry;
carry = fQuotient(temp, 24);
fNewDate->fValue[Hour] = mod(temp, 24, carry);
fNewDate->fValue[Day] = DATETIMES[index][Day] + fDuration->fValue[Day] + carry;
while ( true )
{
temp = maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]);
if ( fNewDate->fValue[Day] < 1 )
{ //original fNewDate was negative
fNewDate->fValue[Day] += maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]-1);
carry = -1;
}
else if ( fNewDate->fValue[Day] > temp )
{
fNewDate->fValue[Day] -= temp;
carry = 1;
}
else
{
break;
}
temp = fNewDate->fValue[Month] + carry;
fNewDate->fValue[Month] = modulo(temp, 1, 13);
fNewDate->fValue[CentYear] += fQuotient(temp, 1, 13);
}
//fNewDate->fValue[utc] = UTC_STD_CHAR;
fNewDate->fValue[utc] = UTC_STD;
}
int XMLDateTime::compareResult(short resultA
, short resultB
, bool strict)
{
if ( resultB == INDETERMINATE )
{
return INDETERMINATE;
}
else if ( (resultA != resultB) &&
strict )
{
return INDETERMINATE;
}
else if ( (resultA != resultB) &&
!strict )
{
if ( (resultA != EQUAL) &&
(resultB != EQUAL) )
{
return INDETERMINATE;
}
else
{
return (resultA != EQUAL)? resultA : resultB;
}
}
return resultA;
}
// ---------------------------------------------------------------------------
// static methods : for others
// ---------------------------------------------------------------------------
int XMLDateTime::compare(const XMLDateTime* const pDate1
, const XMLDateTime* const pDate2)
{
if (pDate1->fValue[utc] == pDate2->fValue[utc])
{
return XMLDateTime::compareOrder(pDate1, pDate2);
}
short c1, c2;
if ( pDate1->isNormalized())
{
c1 = compareResult(pDate1, pDate2, false, UTC_POS);
c2 = compareResult(pDate1, pDate2, false, UTC_NEG);
return getRetVal(c1, c2);
}
else if ( pDate2->isNormalized())
{
c1 = compareResult(pDate1, pDate2, true, UTC_POS);
c2 = compareResult(pDate1, pDate2, true, UTC_NEG);
return getRetVal(c1, c2);
}
return INDETERMINATE;
}
int XMLDateTime::compareResult(const XMLDateTime* const pDate1
, const XMLDateTime* const pDate2
, bool set2Left
, int utc_type)
{
XMLDateTime tmpDate = (set2Left ? *pDate1 : *pDate2);
tmpDate.fTimeZone[hh] = 14;
tmpDate.fTimeZone[mm] = 0;
tmpDate.fValue[utc] = utc_type;
tmpDate.normalize();
return (set2Left? XMLDateTime::compareOrder(&tmpDate, pDate2) :
XMLDateTime::compareOrder(pDate1, &tmpDate));
}
int XMLDateTime::compareOrder(const XMLDateTime* const lValue
, const XMLDateTime* const rValue)
{
//
// If any of the them is not normalized() yet,
// we need to do something here.
//
XMLDateTime lTemp = *lValue;
XMLDateTime rTemp = *rValue;
lTemp.normalize();
rTemp.normalize();
for ( int i = 0 ; i < TOTAL_SIZE; i++ )
{
if ( lTemp.fValue[i] < rTemp.fValue[i] )
{
return LESS_THAN;
}
else if ( lTemp.fValue[i] > rTemp.fValue[i] )
{
return GREATER_THAN;
}
}
return EQUAL;
}
// ---------------------------------------------------------------------------
// ctor and dtor
// ---------------------------------------------------------------------------
XMLDateTime::~XMLDateTime()
{
if (fBuffer)
delete[] fBuffer;
}
XMLDateTime::XMLDateTime()
:fBuffer(0)
{
reset();
}
XMLDateTime::XMLDateTime(const XMLCh* const aString)
:fBuffer(0)
{
setBuffer(aString);
}
// -----------------------------------------------------------------------
// Copy ctor and Assignment operators
// -----------------------------------------------------------------------
XMLDateTime::XMLDateTime(const XMLDateTime &toCopy)
:fBuffer(0)
{
copy(toCopy);
}
XMLDateTime& XMLDateTime::operator=(const XMLDateTime& rhs)
{
if (this == &rhs)
return *this;
copy(rhs);
return *this;
}
// -----------------------------------------------------------------------
// Implementation of Abstract Interface
// -----------------------------------------------------------------------
//
// We may simply return the handle to fBuffer, but
// for the sake of consistency, we return a duplicated copy
// and the caller is responsible for the release of the buffer
// just like any other things in the XMLNumber family.
//
XMLCh* XMLDateTime::toString() const
{
assertBuffer();
XMLCh* retBuf = XMLString::replicate(fBuffer);
return retBuf;
}
int XMLDateTime::getSign() const
{
return 0;
}
// ---------------------------------------------------------------------------
// Parsers
// ---------------------------------------------------------------------------
//
// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}[TimeZone]
//
void XMLDateTime::parseDateTime()
{
initParser();
getDate();
//fStart is supposed to point to 'T'
if (fBuffer[fStart++] != DATETIME_SEPARATOR)
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("CCYY-MM must be followed by '-' sign");
getTime();
validateDateTime();
normalize();
}
//
// [-]{CCYY-MM-DD}[TimeZone]
//
void XMLDateTime::parseDate()
{
initParser();
getDate();
parseTimeZone();
validateDateTime();
normalize();
}
void XMLDateTime::parseTime()
{
initParser();
// time initialize to default values
fValue[CentYear]= YEAR_DEFAULT;
fValue[Month] = MONTH_DEFAULT;
fValue[Day] = DAY_DEFAULT;
getTime();
validateDateTime();
normalize();
}
//
// {---DD}[TimeZone]
// 01234
//
void XMLDateTime::parseDay()
{
initParser();
if (fBuffer[0] != DATE_SEPARATOR ||
fBuffer[1] != DATE_SEPARATOR ||
fBuffer[2] != DATE_SEPARATOR )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in day parsing");
}
//initialize values
fValue[CentYear] = YEAR_DEFAULT;
fValue[Month] = MONTH_DEFAULT;
fValue[Day] = parseInt(fStart+3, fStart+5);
if ( DAY_SIZE < fEnd )
{
int sign = findUTCSign(DAY_SIZE);
if ( sign < 0 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in day parsing");
}
else
{
getTimeZone(sign);
}
}
validateDateTime();
normalize();
}
//
// {--MM--}[TimeZone]
// 012345
//
void XMLDateTime::parseMonth()
{
initParser();
if (fBuffer[0] != DATE_SEPARATOR ||
fBuffer[1] != DATE_SEPARATOR ||
fBuffer[4] != DATE_SEPARATOR ||
fBuffer[5] != DATE_SEPARATOR )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Invalid format for gMonth: "+str);
}
//set constants
fValue[CentYear] = YEAR_DEFAULT;
fValue[Day] = DAY_DEFAULT;
fValue[Month] = parseInt(2, 4);
if ( MONTH_SIZE < fEnd )
{
int sign = findUTCSign(MONTH_SIZE);
if ( sign < 0 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in month parsing: "+str);
}
else
{
getTimeZone(sign);
}
}
validateDateTime();
normalize();
}
//
//[-]{CCYY}[TimeZone]
// 0 1234
//
void XMLDateTime::parseYear()
{
initParser();
// skip the first '-' and search for timezone
//
int sign = findUTCSign((fBuffer[0] == chDash) ? 1 : 0);
if (sign == -1)
{
fValue[CentYear] = parseIntYear(fEnd);
}
else
{
fValue[CentYear] = parseIntYear(sign);
getTimeZone (sign);
}
//initialize values
fValue[Month] = MONTH_DEFAULT;
fValue[Day] = DAY_DEFAULT; //java is 1
validateDateTime();
normalize();
}
//
//{--MM-DD}[TimeZone]
// 0123456
//
void XMLDateTime::parseMonthDay()
{
initParser();
if (fBuffer[0] != DATE_SEPARATOR ||
fBuffer[1] != DATE_SEPARATOR ||
fBuffer[4] != DATE_SEPARATOR )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Invalid format for gMonthDay: "+str);
}
//initialize
fValue[CentYear] = YEAR_DEFAULT;
fValue[Month] = parseInt(2, 4);
fValue[Day] = parseInt(5, 7);
if ( MONTHDAY_SIZE < fEnd )
{
int sign = findUTCSign(MONTHDAY_SIZE);
if ( sign<0 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in month parsing: "+str);
}
else
{
getTimeZone(sign);
}
}
validateDateTime();
normalize();
}
void XMLDateTime::parseYearMonth()
{
initParser();
// get date
getYearMonth();
parseTimeZone();
validateDateTime();
normalize();
}
//
//PnYn MnDTnH nMnS: -P1Y2M3DT10H30M
//
// [-]{'P'{[n'Y'][n'M'][n'D']['T'][n'H'][n'M'][n'S']}}
//
// Note: the n above shall be >= 0
// if no time element found, 'T' shall be absent
//
void XMLDateTime::parseDuration()
{
initParser();
// must start with '-' or 'P'
//
XMLCh c = fBuffer[fStart++];
if ( (c != DURATION_STARTER) &&
(c != chDash) )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in month parsing: "+str);
//SchemaDateTimeException();
}
// 'P' must ALWAYS be present in either case
if ( (c == chDash) &&
(fBuffer[fStart++]!= DURATION_STARTER ))
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//SchemaDateTimeException();
}
// java code
//date[utc]=(c=='-')?'-':0;
//fValue[utc] = UTC_STD;
fValue[utc] = (fBuffer[0] == chDash? UTC_NEG : UTC_STD);
int negate = ( fBuffer[0] == chDash ? -1 : 1);
//
// No negative value is allowed after 'P'
//
// eg P-1234, invalid
//
if (indexOf(fStart, fEnd, chDash) != NOT_FOUND)
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//SchemaDateTimeException();
}
//at least one number and designator must be seen after P
bool designator = false;
int endDate = indexOf(fStart, fEnd, DATETIME_SEPARATOR);
if ( endDate == NOT_FOUND )
{
endDate = fEnd; // 'T' absent
}
//find 'Y'
int end = indexOf(fStart, endDate, DURATION_Y);
if ( end != NOT_FOUND )
{
//scan year
fValue[CentYear] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, endDate, DURATION_M);
if ( end != NOT_FOUND )
{
//scan month
fValue[Month] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, endDate, DURATION_D);
if ( end != NOT_FOUND )
{
//scan day
fValue[Day] = negate * parseInt(fStart,end);
fStart = end+1;
designator = true;
}
if ( (fEnd == endDate) && // 'T' absent
(fStart != fEnd) ) // something after Day
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//SchemaDateTimeException();
}
if ( fEnd != endDate ) // 'T' present
{
//scan hours, minutes, seconds
//
// skip 'T' first
end = indexOf(++fStart, fEnd, DURATION_H);
if ( end != NOT_FOUND )
{
//scan hours
fValue[Hour] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, fEnd, DURATION_M);
if ( end != NOT_FOUND )
{
//scan min
fValue[Minute] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, fEnd, DURATION_S);
if ( end != NOT_FOUND )
{
//scan seconds
int mlsec = indexOf (fStart, end, MILISECOND_SEPARATOR);
if ( mlsec != NOT_FOUND )
{
fValue[Second] = negate * parseInt(fStart, mlsec);
fValue[MiliSecond] = negate * parseInt(mlsec+1, end);
}
else
{
fValue[Second] = negate * parseInt(fStart,end);
}
fStart = end+1;
designator = true;
}
// no additional data shouls appear after last item
// P1Y1M1DT is illigal value as well
if ( (fStart != fEnd) ||
fBuffer[--fStart] == DATETIME_SEPARATOR )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//SchemaDateTimeException();
}
}
if ( !designator )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//SchemaDateTimeException();
}
}
// ---------------------------------------------------------------------------
// Scanners
// ---------------------------------------------------------------------------
//
// [-]{CCYY-MM-DD}
//
// Note: CCYY could be more than 4 digits
// Assuming fStart point to the beginning of the Date Section
// fStart updated to point to the position right AFTER the second 'D'
// Since the lenght of CCYY might be variable, we can't check format upfront
//
void XMLDateTime::getDate()
{
// Ensure enough chars in buffer
if ( (fStart+YMD_MIN_SIZE) > fEnd)
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Imcomplete Date Format";
getYearMonth(); // Scan YearMonth and
// fStart point to the next '-'
if (fBuffer[fStart++] != DATE_SEPARATOR)
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("CCYY-MM must be followed by '-' sign");
}
fValue[Day] = parseInt(fStart, fStart+2);
fStart += 2 ; //fStart points right after the Day
return;
}
//
// hh:mm:ss[.msssss]['Z']
// hh:mm:ss[.msssss][['+'|'-']hh:mm]
// 012345678
//
// Note: Assuming fStart point to the beginning of the Time Section
// fStart updated to point to the position right AFTER the second 's'
// or ms if any
//
void XMLDateTime::getTime()
{
// Ensure enough chars in buffer
if ( (fStart+TIME_MIN_SIZE) > fEnd)
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Imcomplete Time Format"
// check (fixed) format first
if ((fBuffer[fStart + 2] != TIME_SEPARATOR) ||
(fBuffer[fStart + 5] != TIME_SEPARATOR) )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Error in parsing time" );
}
//
// get hours, minute and second
//
fValue[Hour] = parseInt(fStart + 0, fStart + 2);
fValue[Minute] = parseInt(fStart + 3, fStart + 5);
fValue[Second] = parseInt(fStart + 6, fStart + 8);
fStart += 8;
// to see if any ms and/or utc part after that
if (fStart >= fEnd)
return;
//find UTC sign if any
int sign = findUTCSign(fStart);
//parse miliseconds
int milisec = (fBuffer[fStart] == MILISECOND_SEPARATOR)? fStart : NOT_FOUND;
if ( milisec != NOT_FOUND )
{
fStart++; // skip the '.'
// make sure we have some thing between the '.' and fEnd
if (fStart >= fEnd)
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("ms shall be present once '.' is present" );
}
if ( sign == NOT_FOUND )
{
fValue[MiliSecond] = parseInt(fStart, fEnd); //get ms between '.' and fEnd
fStart = fEnd;
}
else
{
fValue[MiliSecond] = parseInt(fStart, sign); //get ms between UTC sign and fEnd
}
}
//parse UTC time zone (hh:mm)
if ( sign > 0 ) {
getTimeZone(sign);
}
}
//
// [-]{CCYY-MM}
//
// Note: CCYY could be more than 4 digits
// fStart updated to point AFTER the second 'M' (probably meet the fEnd)
//
void XMLDateTime::getYearMonth()
{
// Ensure enough chars in buffer
if ( (fStart+YMONTH_MIN_SIZE) > fEnd)
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Imcomplete YearMonth Format";
// skip the first leading '-'
int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart;
//
// search for year separator '-'
//
int yearSeparator = indexOf(start, fEnd, DATE_SEPARATOR);
if ( yearSeparator == NOT_FOUND)
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Year separator is missing or misplaced");
int length = yearSeparator - start;
if (length < 4)
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Year must have 'CCYY' format");
}
else if (length > 4 &&
fBuffer[start] == chDigit_0)
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Leading zeros are required if the year value would otherwise have fewer than four digits;
// otherwise they are forbidden");
}
fValue[CentYear] = parseIntYear(yearSeparator);
fStart = yearSeparator + 1; //skip the '-' and point to the first M
//
//gonna check we have enough byte for month
//
if ((fStart + 2) > fEnd )
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"no month in buffer"
fValue[Month] = parseInt(fStart, yearSeparator + 3);
fStart += 2; //fStart points right after the MONTH
return;
}
void XMLDateTime::parseTimeZone()
{
if ( fStart < fEnd )
{
int sign = findUTCSign(fStart);
if ( sign < 0 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Error in month parsing");
}
else
{
getTimeZone(sign);
}
}
return;
}
//
// 'Z'
// ['+'|'-']hh:mm
//
// Note: Assuming fStart points to the beginning of TimeZone section
// fStart updated to meet fEnd
//
void XMLDateTime::getTimeZone(const int sign)
{
if ( fBuffer[sign] == UTC_STD_CHAR )
{
if ((sign + 1) != fEnd )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Error in parsing time zone");
}
return;
}
//
// otherwise, it has to be this format
// '[+|-]'hh:mm
// 1 23456 7
// sign fEnd
//
if ( ( ( sign + TIMEZONE_SIZE + 1) != fEnd ) ||
( fBuffer[sign + 3] != TIMEZONE_SEPARATOR ) )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Error in parsing time zone");
}
fTimeZone[hh] = parseInt(sign+1, sign+3);
fTimeZone[mm] = parseInt(sign+4, fEnd);
return;
}
// ---------------------------------------------------------------------------
// Validator and normalizer
// ---------------------------------------------------------------------------
/**
* If timezone present - normalize dateTime [E Adding durations to dateTimes]
*
* @param date CCYY-MM-DDThh:mm:ss+03
* @return CCYY-MM-DDThh:mm:ssZ
*/
void XMLDateTime::normalize()
{
if ((fValue[utc] == UTC_UNKNOWN) ||
(fValue[utc] == UTC_STD) )
return;
int negate = (fValue[utc] == UTC_POS)? -1: 1;
// add mins
int temp = fValue[Minute] + negate * fTimeZone[mm];
int carry = fQuotient(temp, 60);
fValue[Minute] = mod(temp, 60, carry);
//add hours
temp = fValue[Hour] + negate * fTimeZone[hh] + carry;
carry = fQuotient(temp, 24);
fValue[Hour] = mod(temp, 24, carry);
fValue[Day] += carry;
while (1)
{
temp = maxDayInMonthFor(fValue[CentYear], fValue[Month]);
if (fValue[Day] < 1)
{
fValue[Day] += maxDayInMonthFor(fValue[CentYear], fValue[Month] - 1);
carry = -1;
}
else if ( fValue[Day] > temp )
{
fValue[Day] -= temp;
carry = 1;
}
else
{
break;
}
temp = fValue[Month] + carry;
fValue[Month] = modulo(temp, 1, 13);
fValue[CentYear] += fQuotient(temp, 1, 13);
}
// set to normalized
fValue[utc] = UTC_STD;
return;
}
void XMLDateTime::validateDateTime() const
{
//REVISIT: should we throw an exception for not valid dates
// or reporting an error message should be sufficient?
if ( fValue[CentYear] == 0 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"The year \"0000\" is an illegal year value");
}
if ( fValue[Month] < 1 ||
fValue[Month] > 12 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"The month must have values 1 to 12");
}
//validate days
if ( fValue[Day] > maxDayInMonthFor( fValue[CentYear], fValue[Month]))
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"The day must have values 1 to 31");
}
//validate hours
if ( fValue[Hour] < 0 ||
fValue[Hour] > 23 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Hour must have values 0-23");
}
//validate
if ( fValue[Minute] < 0 ||
fValue[Minute] > 59 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Minute must have values 0-59");
}
//validate
if ( fValue[Second] < 0 ||
fValue[Second] > 60 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Second must have values 0-60");
}
//validate
if ( fTimeZone[hh] < -14 ||
fTimeZone[hh] > 14 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//"Time zone should have range -14..+14");
}
//validate
if ( fTimeZone[mm] < -59 ||
fTimeZone[mm] > 59 )
{
ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
//("Minute must have values 0-59");
}
return;
}
// -----------------------------------------------------------------------
// locator and converter
// -----------------------------------------------------------------------
int XMLDateTime::indexOf(const int start, const int end, const XMLCh ch) const
{
for ( int i = start; i < end; i++ )
if ( fBuffer[i] == ch )
return i;
return NOT_FOUND;
}
int XMLDateTime::findUTCSign (const int start)
{
int pos;
for ( int index = start; index < fEnd; index++ )
{
pos = XMLString::indexOf(UTC_SET, fBuffer[index]);
if ( pos != NOT_FOUND)
{
fValue[utc] = pos+1; // refer to utcType, there is 1 diff
return index;
}
}
return NOT_FOUND;
}
//
// Note:
// start: starting point in fBuffer
// end: ending point in fBuffer (exclusive)
// fStart NOT updated
//
int XMLDateTime::parseInt(const int start, const int end) const
{
XMLCh* strToScan = new XMLCh[end - start + 1];
ArrayJanitor<XMLCh> jname(strToScan);
XMLString::subString(strToScan, fBuffer, start, end);
unsigned int retVal;
XMLString::textToBin(strToScan, retVal);
return (int) retVal;
}
//
// [-]CCYY
//
// Note: start from fStart
// end (exclusive)
// fStart NOT updated
//
int XMLDateTime::parseIntYear(const int end) const
{
bool negative = (fBuffer[0] == chDash);
int yearVal = parseInt((negative ? 1 : 0), end);
return ( negative ? (-1) * yearVal : yearVal );
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org