xmldatetime.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,784 行 · 第 1/4 页
CPP
1,784 行
//"The month must have values 1 to 12"); } //validate days if ( fValue[Day] > maxDayInMonthFor( fValue[CentYear], fValue[Month]) || fValue[Day] == 0 ) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_day_invalid , fBuffer , fMemoryManager); //"The day must have values 1 to 31"); } //validate hours if ((fValue[Hour] < 0) || (fValue[Hour] > 24) || ((fValue[Hour] == 24) && ((fValue[Minute] !=0) || (fValue[Second] !=0) || (fMiliSecond !=0)))) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_hour_invalid , fBuffer , fMemoryManager); //("Hour must have values 0-23"); } //validate minutes if ( fValue[Minute] < 0 || fValue[Minute] > 59 ) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_min_invalid , fBuffer , fMemoryManager); //"Minute must have values 0-59"); } //validate seconds if ( fValue[Second] < 0 || fValue[Second] > 60 ) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_second_invalid , fBuffer , fMemoryManager); //"Second must have values 0-60"); } //validate time-zone hours if ( (abs(fTimeZone[hh]) > 14) || ((abs(fTimeZone[hh]) == 14) && (fTimeZone[mm] != 0)) ) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_tz_hh_invalid , fBuffer , fMemoryManager); //"Time zone should have range -14..+14"); } //validate time-zone minutes if ( abs(fTimeZone[mm]) > 59 ) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_min_invalid , fBuffer , fMemoryManager); //("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{ unsigned int retVal = 0; for (int i=start; i < end; i++) { if (fBuffer[i] < chDigit_0 || fBuffer[i] > chDigit_9) ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, fMemoryManager); retVal = (retVal * 10) + (unsigned int) (fBuffer[i] - chDigit_0); } return (int) retVal;}//// Note:// start: pointing to the first digit after the '.'// end: pointing to one position after the last digit// fStart NOT updated//double XMLDateTime::parseMiliSecond(const int start, const int end) const{ unsigned int miliSecLen = (end-1) - (start-1) + 1; //to include the '.' XMLCh* miliSecData = (XMLCh*) fMemoryManager->allocate( (miliSecLen + 1) * sizeof(XMLCh)); ArrayJanitor<XMLCh> janMili(miliSecData, fMemoryManager); XMLString::copyNString(miliSecData, &(fBuffer[start-1]), miliSecLen); *(miliSecData + miliSecLen) = chNull; char *nptr = XMLString::transcode(miliSecData, fMemoryManager); ArrayJanitor<char> jan(nptr, fMemoryManager); int strLen = strlen(nptr); char *endptr = 0; errno = 0; //printf("milisec=<%s>\n", nptr); double retVal = strtod(nptr, &endptr); // check if all chars are valid char if ( (endptr - nptr) != strLen) ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, fMemoryManager); // we don't check underflow occurs since // nothing we can do about it. return retVal;}//// [-]CCYY//// Note: start from fStart// end (exclusive)// fStart NOT updated//int XMLDateTime::parseIntYear(const int end) const{ // skip the first leading '-' int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart; int length = end - start; if (length < 4) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_year_tooShort , fBuffer , fMemoryManager); //"Year must have 'CCYY' format"); } else if (length > 4 && fBuffer[start] == chDigit_0) { ThrowXMLwithMemMgr1(SchemaDateTimeException , XMLExcepts::DateTime_year_leadingZero , fBuffer , fMemoryManager); //"Leading zeros are required if the year value would otherwise have fewer than four digits; // otherwise they are forbidden"); } bool negative = (fBuffer[0] == chDash); int yearVal = parseInt((negative ? 1 : 0), end); return ( negative ? (-1) * yearVal : yearVal );}/*** * E2-41 * * 3.2.7.2 Canonical representation * * Except for trailing fractional zero digits in the seconds representation, * '24:00:00' time representations, and timezone (for timezoned values), * the mapping from literals to values is one-to-one. Where there is more * than one possible representation, the canonical representation is as follows: * redundant trailing zero digits in fractional-second literals are prohibited. * An hour representation of '24' is prohibited. Timezoned values are canonically * represented by appending 'Z' to the nontimezoned representation. (All * timezoned dateTime values are UTC.) * * .'24:00:00' -> '00:00:00' * .milisecond: trailing zeros removed * .'Z' * ***/XMLCh* XMLDateTime::getDateTimeCanonicalRepresentation(MemoryManager* const memMgr) const{ XMLCh *miliStartPtr, *miliEndPtr; searchMiliSeconds(miliStartPtr, miliEndPtr); int miliSecondsLen = miliEndPtr - miliStartPtr; MemoryManager* toUse = memMgr? memMgr : fMemoryManager; XMLCh* retBuf = (XMLCh*) toUse->allocate( (21 + miliSecondsLen + 2) * sizeof(XMLCh)); XMLCh* retPtr = retBuf; // (-?) cc+yy-mm-dd'T'hh:mm:ss'Z' ('.'s+)? // 2+ 8 1 8 1 // int additionalLen = fillYearString(retPtr, CentYear); if(additionalLen != 0) { // very bad luck; have to resize the buffer... XMLCh *tmpBuf = (XMLCh*) toUse->allocate( (additionalLen+21+miliSecondsLen +2) * sizeof(XMLCh)); XMLString::moveChars(tmpBuf, retBuf, 4+additionalLen); retPtr = tmpBuf+(retPtr-retBuf); toUse->deallocate(retBuf); retBuf = tmpBuf; } *retPtr++ = DATE_SEPARATOR; fillString(retPtr, Month, 2); *retPtr++ = DATE_SEPARATOR; fillString(retPtr, Day, 2); *retPtr++ = DATETIME_SEPARATOR; fillString(retPtr, Hour, 2); if (fValue[Hour] == 24) { *(retPtr - 2) = chDigit_0; *(retPtr - 1) = chDigit_0; } *retPtr++ = TIME_SEPARATOR; fillString(retPtr, Minute, 2); *retPtr++ = TIME_SEPARATOR; fillString(retPtr, Second, 2); if (miliSecondsLen) { *retPtr++ = chPeriod; XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); retPtr += miliSecondsLen; } *retPtr++ = UTC_STD_CHAR; *retPtr = chNull; return retBuf;}/*** * 3.2.8 time * * . either the time zone must be omitted or, * if present, the time zone must be Coordinated Universal Time (UTC) indicated by a "Z". * * . Additionally, the canonical representation for midnight is 00:00:00. ****/XMLCh* XMLDateTime::getTimeCanonicalRepresentation(MemoryManager* const memMgr) const{ XMLCh *miliStartPtr, *miliEndPtr; searchMiliSeconds(miliStartPtr, miliEndPtr); int miliSecondsLen = miliEndPtr - miliStartPtr; MemoryManager* toUse = memMgr? memMgr : fMemoryManager; XMLCh* retBuf = (XMLCh*) toUse->allocate( (10 + miliSecondsLen + 2) * sizeof(XMLCh)); XMLCh* retPtr = retBuf; // 'hh:mm:ss'Z' ('.'s+)? // 8 1 // fillString(retPtr, Hour, 2); if (fValue[Hour] == 24) { *(retPtr - 2) = chDigit_0; *(retPtr - 1) = chDigit_0; } *retPtr++ = TIME_SEPARATOR; fillString(retPtr, Minute, 2); *retPtr++ = TIME_SEPARATOR; fillString(retPtr, Second, 2); if (miliSecondsLen) { *retPtr++ = chPeriod; XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); retPtr += miliSecondsLen; } *retPtr++ = UTC_STD_CHAR; *retPtr = chNull; return retBuf;}void XMLDateTime::fillString(XMLCh*& ptr, valueIndex ind, int expLen) const{ XMLCh strBuffer[16]; assert(expLen < 16); XMLString::binToText(fValue[ind], strBuffer, expLen, 10, fMemoryManager); int actualLen = XMLString::stringLen(strBuffer); int i; //append leading zeros for (i = 0; i < expLen - actualLen; i++) { *ptr++ = chDigit_0; } for (i = 0; i < actualLen; i++) { *ptr++ = strBuffer[i]; }}int XMLDateTime::fillYearString(XMLCh*& ptr, valueIndex ind) const{ XMLCh strBuffer[16]; // let's hope we get no years of 15 digits... XMLString::binToText(fValue[ind], strBuffer, 15, 10, fMemoryManager); int actualLen = XMLString::stringLen(strBuffer); // don't forget that years can be negative... int negativeYear = 0; if(strBuffer[0] == chDash) { *ptr++ = strBuffer[0]; negativeYear = 1; } int i; //append leading zeros for (i = 0; i < 4 - actualLen+negativeYear; i++) { *ptr++ = chDigit_0; } for (i = negativeYear; i < actualLen; i++) { *ptr++ = strBuffer[i]; } if(actualLen > 4) return actualLen-4; return 0;}/*** * * .check if the rawData has the mili second component * .capture the substring * ***/void XMLDateTime::searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const{ miliStartPtr = miliEndPtr = 0; int milisec = XMLString::indexOf(fBuffer, MILISECOND_SEPARATOR); if (milisec == -1) return; miliStartPtr = fBuffer + milisec + 1; miliEndPtr = miliStartPtr; while (*miliEndPtr) { if ((*miliEndPtr < chDigit_0) || (*miliEndPtr > chDigit_9)) break; miliEndPtr++; } //remove trailing zeros while( *(miliEndPtr - 1) == chDigit_0) miliEndPtr--; return;}/*** * Support for Serialization/De-serialization ***/IMPL_XSERIALIZABLE_TOCREATE(XMLDateTime)void XMLDateTime::serialize(XSerializeEngine& serEng){ //REVISIT: may not need to call base since it does nothing XMLNumber::serialize(serEng); int i = 0; if (serEng.isStoring()) { for (i = 0; i < TOTAL_SIZE; i++) { serEng<<fValue[i]; } for (i = 0; i < TIMEZONE_ARRAYSIZE; i++) { serEng<<fTimeZone[i]; } serEng<<fStart; serEng<<fEnd; serEng.writeString(fBuffer, fBufferMaxLen, XSerializeEngine::toWriteBufferLen); } else { for (i = 0; i < TOTAL_SIZE; i++) { serEng>>fValue[i]; } for (i = 0; i < TIMEZONE_ARRAYSIZE; i++) { serEng>>fTimeZone[i]; } serEng>>fStart; serEng>>fEnd; int dataLen = 0; serEng.readString(fBuffer, fBufferMaxLen, dataLen ,XSerializeEngine::toReadBufferLen); }}XERCES_CPP_NAMESPACE_END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?