GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: XMLString.cpp 901107 2010-01-20 08:45:02Z borisk $ 00020 */ 00021 00022 00023 // --------------------------------------------------------------------------- 00024 // Includes 00025 // --------------------------------------------------------------------------- 00026 #if HAVE_CONFIG_H 00027 # include <config.h> 00028 #endif 00029 00030 #if !HAVE_STRICMP 00031 # include <stricmp.h> 00032 #endif 00033 #if !HAVE_STRNICMP 00034 # include <strnicmp.h> 00035 #endif 00036 00037 #include <string.h> 00038 #include <ctype.h> 00039 #include <stdlib.h> 00040 #include <errno.h> 00041 #include <assert.h> 00042 00043 #include <xercesc/util/XMLString.hpp> 00044 #include <xercesc/util/ArrayIndexOutOfBoundsException.hpp> 00045 #include <xercesc/util/IllegalArgumentException.hpp> 00046 #include <xercesc/util/NumberFormatException.hpp> 00047 #include <xercesc/util/OutOfMemoryException.hpp> 00048 #include <xercesc/util/RuntimeException.hpp> 00049 #include <xercesc/util/TranscodingException.hpp> 00050 00051 #include <xercesc/util/Janitor.hpp> 00052 #include <xercesc/util/PlatformUtils.hpp> 00053 #include <xercesc/util/RefArrayVectorOf.hpp> 00054 #include <xercesc/util/TransService.hpp> 00055 #include <xercesc/util/XMLUniDefs.hpp> 00056 #include <xercesc/util/XMLUni.hpp> 00057 #include <xercesc/util/XMLUri.hpp> 00058 #include <xercesc/util/XMLURL.hpp> 00059 #include <xercesc/internal/XMLReader.hpp> 00060 00061 XERCES_CPP_NAMESPACE_BEGIN 00062 00063 // --------------------------------------------------------------------------- 00064 // Local static data 00065 // 00066 // gConverter 00067 // This is initialized when the user calls the platform init method, 00068 // which calls our init method. This is the converter used for default 00069 // conversion to/from the local code page. 00070 // --------------------------------------------------------------------------- 00071 static XMLLCPTranscoder* gTranscoder = 0; 00072 static XMLCh gNullStr[] = 00073 { 00074 chOpenCurly, chLatin_n, chLatin_u, chLatin_l, chLatin_l, chCloseCurly, chNull 00075 }; 00076 00077 MemoryManager* XMLString::fgMemoryManager = 0; 00078 00079 00080 // --------------------------------------------------------------------------- 00081 // XMLString: Public static methods 00082 // --------------------------------------------------------------------------- 00083 00084 void XMLString::sizeToText( const XMLSize_t toFormat 00085 , char* const toFill 00086 , const XMLSize_t maxChars 00087 , const unsigned int radix 00088 , MemoryManager* const manager) 00089 { 00090 static const char digitList[16] = 00091 { 00092 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 00093 , 'A', 'B', 'C', 'D', 'E', 'F' 00094 }; 00095 00096 if (!maxChars) 00097 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 00098 00099 // Handle special case 00100 if (!toFormat) 00101 { 00102 toFill[0] = '0'; 00103 toFill[1] = 0; 00104 return; 00105 } 00106 00107 // This is used to fill the temp buffer 00108 XMLSize_t tmpIndex = 0; 00109 00110 // A copy of the conversion value that we can modify 00111 XMLSize_t tmpVal = toFormat; 00112 00113 // 00114 // Convert into a temp buffer that we know is large enough. This avoids 00115 // having to check for overflow in the inner loops, and we have to flip 00116 // the resulting XMLString anyway. 00117 // 00118 char tmpBuf[128]; 00119 00120 // 00121 // For each radix, do the optimal thing. For bin and hex, we can special 00122 // case them and do shift and mask oriented stuff. For oct and decimal 00123 // there isn't much to do but bull through it with divides. 00124 // 00125 if (radix == 2) 00126 { 00127 while (tmpVal) 00128 { 00129 if (tmpVal & 0x1UL) 00130 tmpBuf[tmpIndex++] = '1'; 00131 else 00132 tmpBuf[tmpIndex++] = '0'; 00133 tmpVal >>= 1; 00134 } 00135 } 00136 else if (radix == 16) 00137 { 00138 while (tmpVal) 00139 { 00140 const XMLSize_t charInd = (tmpVal & 0xFUL); 00141 tmpBuf[tmpIndex++] = digitList[charInd]; 00142 tmpVal >>= 4; 00143 } 00144 } 00145 else if ((radix == 8) || (radix == 10)) 00146 { 00147 while (tmpVal) 00148 { 00149 const XMLSize_t charInd = (tmpVal % radix); 00150 tmpBuf[tmpIndex++] = digitList[charInd]; 00151 tmpVal /= radix; 00152 } 00153 } 00154 else 00155 { 00156 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager); 00157 } 00158 00159 // See if have enough room in the caller's buffer 00160 if (tmpIndex > maxChars) 00161 { 00162 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager); 00163 } 00164 00165 // Reverse the tmp buffer into the caller's buffer 00166 XMLSize_t outIndex = 0; 00167 for (; tmpIndex > 0; tmpIndex--) 00168 toFill[outIndex++] = tmpBuf[tmpIndex-1]; 00169 00170 // And cap off the caller's buffer 00171 toFill[outIndex] = char(0); 00172 } 00173 00174 void XMLString::binToText( const unsigned long toFormat 00175 , char* const toFill 00176 , const XMLSize_t maxChars 00177 , const unsigned int radix 00178 , MemoryManager* const manager) 00179 { 00180 static const char digitList[16] = 00181 { 00182 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 00183 , 'A', 'B', 'C', 'D', 'E', 'F' 00184 }; 00185 00186 if (!maxChars) 00187 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 00188 00189 // Handle special case 00190 if (!toFormat) 00191 { 00192 toFill[0] = '0'; 00193 toFill[1] = 0; 00194 return; 00195 } 00196 00197 // This is used to fill the temp buffer 00198 XMLSize_t tmpIndex = 0; 00199 00200 // A copy of the conversion value that we can modify 00201 unsigned long tmpVal = toFormat; 00202 00203 // 00204 // Convert into a temp buffer that we know is large enough. This avoids 00205 // having to check for overflow in the inner loops, and we have to flip 00206 // the resulting XMLString anyway. 00207 // 00208 char tmpBuf[128]; 00209 00210 // 00211 // For each radix, do the optimal thing. For bin and hex, we can special 00212 // case them and do shift and mask oriented stuff. For oct and decimal 00213 // there isn't much to do but bull through it with divides. 00214 // 00215 if (radix == 2) 00216 { 00217 while (tmpVal) 00218 { 00219 if (tmpVal & 0x1UL) 00220 tmpBuf[tmpIndex++] = '1'; 00221 else 00222 tmpBuf[tmpIndex++] = '0'; 00223 tmpVal >>= 1; 00224 } 00225 } 00226 else if (radix == 16) 00227 { 00228 while (tmpVal) 00229 { 00230 const unsigned long charInd = (tmpVal & 0xFUL); 00231 tmpBuf[tmpIndex++] = digitList[charInd]; 00232 tmpVal >>= 4; 00233 } 00234 } 00235 else if ((radix == 8) || (radix == 10)) 00236 { 00237 while (tmpVal) 00238 { 00239 const unsigned long charInd = (tmpVal % radix); 00240 tmpBuf[tmpIndex++] = digitList[charInd]; 00241 tmpVal /= radix; 00242 } 00243 } 00244 else 00245 { 00246 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager); 00247 } 00248 00249 // See if have enough room in the caller's buffer 00250 if (tmpIndex > maxChars) 00251 { 00252 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager); 00253 } 00254 00255 // Reverse the tmp buffer into the caller's buffer 00256 XMLSize_t outIndex = 0; 00257 for (; tmpIndex > 0; tmpIndex--) 00258 toFill[outIndex++] = tmpBuf[tmpIndex-1]; 00259 00260 // And cap off the caller's buffer 00261 toFill[outIndex] = char(0); 00262 } 00263 00264 void XMLString::binToText( const unsigned int toFormat 00265 , char* const toFill 00266 , const XMLSize_t maxChars 00267 , const unsigned int radix 00268 , MemoryManager* const manager) 00269 { 00270 // Just call the unsigned long version 00271 binToText((unsigned long)toFormat, toFill, maxChars, radix, manager); 00272 } 00273 00274 void XMLString::binToText( const long toFormat 00275 , char* const toFill 00276 , const XMLSize_t maxChars 00277 , const unsigned int radix 00278 , MemoryManager* const manager) 00279 { 00280 // 00281 // If its negative, then put a negative sign into the output and flip 00282 // the sign of the local temp value. 00283 // 00284 XMLSize_t startInd = 0; 00285 unsigned long actualVal; 00286 if (toFormat < 0) 00287 { 00288 toFill[0] = '-'; 00289 startInd++; 00290 // Signed integers can represent one extra negative value 00291 // compared to the positive values. If we simply do (v * -1) 00292 // we will overflow on that extra value. 00293 // 00294 long v = toFormat; 00295 v++; 00296 actualVal = (unsigned long)(v * -1); 00297 actualVal++; 00298 } 00299 else 00300 { 00301 actualVal = (unsigned long)(toFormat); 00302 } 00303 00304 // And now call the unsigned long version 00305 binToText(actualVal, &toFill[startInd], maxChars, radix, manager); 00306 } 00307 00308 void XMLString::binToText( const int toFormat 00309 , char* const toFill 00310 , const XMLSize_t maxChars 00311 , const unsigned int radix 00312 , MemoryManager* const manager) 00313 { 00314 // Just call the long version 00315 binToText((long)toFormat, toFill, maxChars, radix, manager); 00316 } 00317 00318 00319 void XMLString::catString(char* const target, const char* const src) 00320 { 00321 strcat(target, src); 00322 } 00323 00324 00325 int XMLString::compareIString(const char* const str1, const char* const str2) 00326 { 00327 return stricmp(str1, str2); 00328 } 00329 00330 00331 int XMLString::compareNString( const char* const str1 00332 , const char* const str2 00333 , const XMLSize_t count) 00334 { 00335 // Watch for pathological secenario 00336 if (!count) 00337 return 0; 00338 00339 return strncmp(str1, str2, count); 00340 } 00341 00342 00343 int XMLString::compareNIString( const char* const str1 00344 , const char* const str2 00345 , const XMLSize_t count) 00346 { 00347 if (!count) 00348 return 0; 00349 00350 return strnicmp(str1, str2, count); 00351 } 00352 00353 00354 int XMLString::compareString( const char* const str1 00355 , const char* const str2) 00356 { 00357 return strcmp(str1, str2); 00358 } 00359 00360 00361 void XMLString::copyString( char* const target 00362 , const char* const src) 00363 { 00364 strcpy(target, src); 00365 } 00366 00367 00368 void XMLString::cut( XMLCh* const toCutFrom 00369 , const XMLSize_t count) 00370 { 00371 #if defined(XML_DEBUG) 00372 if (count > stringLen(toCutFrom)) 00373 { 00374 // <TBD> This is bad of course 00375 } 00376 #endif 00377 00378 // If count is zero, then nothing to do 00379 if (!count) 00380 return; 00381 00382 XMLCh* targetPtr = toCutFrom; 00383 XMLCh* srcPtr = toCutFrom + count; 00384 while (*srcPtr) 00385 *targetPtr++ = *srcPtr++; 00386 00387 // Cap it off at the new end 00388 *targetPtr = 0; 00389 } 00390 00391 00392 XMLSize_t XMLString::hash( const char* const tohash 00393 , const XMLSize_t hashModulus) 00394 { 00395 XMLSize_t hashVal = 0; 00396 if (tohash) { 00397 const char* curCh = tohash; 00398 while (*curCh) 00399 { 00400 XMLSize_t top = hashVal >> 24; 00401 hashVal += (hashVal * 37) + top + (XMLSize_t)(*curCh); 00402 curCh++; 00403 } 00404 } 00405 00406 // Divide by modulus 00407 return hashVal % hashModulus; 00408 } 00409 00410 00411 int XMLString::indexOf(const char* const toSearch, const char ch) 00412 { 00413 const XMLSize_t len = strlen(toSearch); 00414 for (XMLSize_t i = 0; i < len; i++) 00415 { 00416 if (toSearch[i] == ch) 00417 return (int)i; 00418 } 00419 return -1; 00420 } 00421 00422 00423 int XMLString::indexOf( const char* const toSearch 00424 , const char ch 00425 , const XMLSize_t fromIndex 00426 , MemoryManager* const manager) 00427 { 00428 const XMLSize_t len = strlen(toSearch); 00429 00430 // Make sure the start index is within the XMLString bounds 00431 if ((int)fromIndex > ((int)len)-1) 00432 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 00433 00434 for (XMLSize_t i = fromIndex; i < len; i++) 00435 { 00436 if (toSearch[i] == ch) 00437 return (int)i; 00438 } 00439 return -1; 00440 } 00441 00442 int XMLString::lastIndexOf(const char* const toSearch, const char ch) 00443 { 00444 const int len = (int)strlen(toSearch); 00445 for (int i = len-1; i >= 0; i--) 00446 { 00447 if (toSearch[i] == ch) 00448 return i; 00449 } 00450 return -1; 00451 } 00452 00453 int XMLString::lastIndexOf( const char* const toSearch 00454 , const char ch 00455 , const XMLSize_t fromIndex 00456 , MemoryManager* const manager) 00457 { 00458 const XMLSize_t len = strlen(toSearch); 00459 00460 // Make sure the start index is within the XMLString bounds 00461 if ((int)fromIndex > ((int)len)-1) 00462 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 00463 00464 for (int i = (int)fromIndex; i >= 0; i--) 00465 { 00466 if (toSearch[i] == ch) 00467 return i; 00468 } 00469 return -1; 00470 } 00471 00472 00473 XMLSize_t XMLString::replaceTokens( XMLCh* const errText 00474 , const XMLSize_t maxChars 00475 , const XMLCh* const text1 00476 , const XMLCh* const text2 00477 , const XMLCh* const text3 00478 , const XMLCh* const text4 00479 , MemoryManager* const manager) 00480 { 00481 // 00482 // We have to build the string back into the source string, so allocate 00483 // a temp string and copy the orignal text to it. We'll then treat the 00484 // incoming buffer as a target buffer. Put a janitor on it to make sure 00485 // it gets cleaned up. 00486 // 00487 XMLCh* orgText = replicate(errText, manager); 00488 ArrayJanitor<XMLCh> janText(orgText, manager); 00489 00490 XMLCh* pszSrc = orgText; 00491 XMLSize_t curOutInd = 0; 00492 00493 while (*pszSrc && (curOutInd < maxChars)) 00494 { 00495 // 00496 // Loop until we see a { character. Until we do, just copy chars 00497 // from src to target, being sure not to overrun the output buffer. 00498 // 00499 while ((*pszSrc != chOpenCurly) && (curOutInd < maxChars)) 00500 { 00501 if (!*pszSrc) 00502 break; 00503 errText[curOutInd++] = *pszSrc++; 00504 } 00505 00506 // If we did not find a curly, then we are done 00507 if (*pszSrc != chOpenCurly) 00508 break; 00509 00510 // 00511 // Probe this one to see if it matches our pattern of {x}. If not 00512 // then copy over those chars and go back to the first loop. 00513 // 00514 if ((*(pszSrc+1) >= chDigit_0) 00515 && (*(pszSrc+1) <= chDigit_3) 00516 && (*(pszSrc+2) == chCloseCurly)) 00517 { 00518 // 00519 // Its one of our guys, so move the source pointer up past the 00520 // token we are replacing. First though get out the token number 00521 // character. 00522 // 00523 XMLCh tokCh = *(pszSrc+1); 00524 pszSrc += 3; 00525 00526 // Now copy over the replacement text 00527 const XMLCh* repText = 0; 00528 if (tokCh == chDigit_0) 00529 repText = text1; 00530 else if (tokCh == chDigit_1) 00531 repText = text2; 00532 else if (tokCh == chDigit_2) 00533 repText = text3; 00534 else if (tokCh == chDigit_3) 00535 repText = text4; 00536 00537 // If this one is null, copy over a null string 00538 if (!repText) 00539 repText = gNullStr; 00540 00541 while (*repText && (curOutInd < maxChars)) 00542 errText[curOutInd++] = *repText++; 00543 } 00544 else 00545 { 00546 // Escape the curly brace character and continue 00547 errText[curOutInd++] = *pszSrc++; 00548 } 00549 } 00550 00551 // Copy over a null terminator 00552 errText[curOutInd] = 0; 00553 00554 // And return the count of chars we output 00555 return curOutInd; 00556 } 00557 00558 00559 char* XMLString::replicate( const char* const toRep 00560 , MemoryManager* const manager) 00561 { 00562 // If a null string, return a null string 00563 if (!toRep) 00564 return 0; 00565 00566 // 00567 // Get the len of the source and allocate a new buffer. Make sure to 00568 // account for the nul terminator. 00569 // 00570 const XMLSize_t srcLen = strlen(toRep); 00571 char* ret = (char*) manager->allocate((srcLen+1) * sizeof(char)); //new char[srcLen+1]; 00572 00573 // Copy over the text, adjusting for the size of a char 00574 memcpy(ret, toRep, (srcLen+1) * sizeof(char)); 00575 return ret; 00576 } 00577 00578 00579 bool XMLString::startsWith(const char* const toTest, const char* const prefix) 00580 { 00581 return (strncmp(toTest, prefix, strlen(prefix)) == 0); 00582 } 00583 00584 00585 bool XMLString::startsWithI(const char* const toTest 00586 , const char* const prefix) 00587 { 00588 return (strnicmp(toTest, prefix, strlen(prefix)) == 0); 00589 } 00590 00591 00592 XMLSize_t XMLString::stringLen(const char* const src) 00593 { 00594 return strlen(src); 00595 } 00596 00597 char* XMLString::transcode(const XMLCh* const toTranscode, 00598 MemoryManager* const manager) 00599 { 00600 return gTranscoder->transcode(toTranscode, manager); 00601 } 00602 00603 00604 bool XMLString::transcode( const XMLCh* const toTranscode 00605 , char* const toFill 00606 , const XMLSize_t maxChars 00607 , MemoryManager* const manager) 00608 { 00609 return gTranscoder->transcode(toTranscode, toFill, maxChars, manager); 00610 } 00611 00612 XMLCh* XMLString::transcode(const char* const toTranscode, 00613 MemoryManager* const manager) 00614 { 00615 return gTranscoder->transcode(toTranscode, manager); 00616 } 00617 00618 bool XMLString::transcode( const char* const toTranscode 00619 , XMLCh* const toFill 00620 , const XMLSize_t maxChars 00621 , MemoryManager* const manager) 00622 { 00623 return gTranscoder->transcode(toTranscode, toFill, maxChars, manager); 00624 } 00625 00626 00627 void XMLString::trim(char* const toTrim) 00628 { 00629 const XMLSize_t len = strlen(toTrim); 00630 00631 XMLSize_t skip, scrape; 00632 for (skip = 0; skip < len; skip++) 00633 { 00634 if (! isspace(toTrim[skip])) 00635 break; 00636 } 00637 00638 for (scrape = len; scrape > skip; scrape--) 00639 { 00640 if (! isspace(toTrim[scrape - 1] )) 00641 break; 00642 } 00643 00644 // Cap off at the scrap point 00645 if (scrape != len) 00646 toTrim[scrape] = 0; 00647 00648 if (skip) 00649 { 00650 // Copy the chars down 00651 XMLSize_t index = 0; 00652 while (toTrim[skip]) 00653 toTrim[index++] = toTrim[skip++]; 00654 00655 toTrim[index] = 0; 00656 } 00657 } 00658 00659 00660 void XMLString::subString(char* const targetStr, const char* const srcStr 00661 , const XMLSize_t startIndex, const XMLSize_t endIndex 00662 , MemoryManager* const manager) 00663 { 00664 if (targetStr == 0) 00665 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 00666 00667 const XMLSize_t srcLen = strlen(srcStr); 00668 00669 // Make sure the start index is within the XMLString bounds 00670 if (startIndex > endIndex || endIndex > srcLen) 00671 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 00672 00673 const XMLSize_t copySize = endIndex - startIndex; 00674 00675 for (XMLSize_t i= startIndex; i < endIndex; i++) { 00676 targetStr[i-startIndex] = srcStr[i]; 00677 } 00678 00679 targetStr[copySize] = 0; 00680 } 00681 00682 bool XMLString::isValidNOTATION(const XMLCh* const name 00683 , MemoryManager* const manager ) 00684 { 00685 // 00686 // NOTATATION: <URI>:<localPart> 00687 // where URI is optional 00688 // ':' and localPart must be present 00689 // 00690 XMLSize_t nameLen = XMLString::stringLen(name); 00691 int colPos = XMLString::lastIndexOf(name, chColon); 00692 00693 if ((colPos == 0) || // no ':' 00694 (colPos == ((int)nameLen) - 1) ) // <URI>':' 00695 return false; 00696 00697 00698 // Examine localpart 00699 if (!XMLChar1_0::isValidNCName(&name[colPos+1], nameLen - colPos -1)) 00700 { 00701 return false; 00702 } 00703 else if (colPos == -1) 00704 { 00705 return true; 00706 } 00707 else 00708 { 00709 // Examine URI 00710 XMLCh* const temp = 00711 (XMLCh*) manager->allocate((colPos + 1) * sizeof(XMLCh)); 00712 const ArrayJanitor<XMLCh> jan(temp, manager); 00713 00714 copyNString(temp, name, colPos); 00715 temp[colPos] = 0; 00716 00717 try 00718 { 00719 XMLUri newURI(temp, manager); // no relative uri support here 00720 } 00721 catch (const MalformedURLException&) 00722 { 00723 return false; 00724 } 00725 00726 return true; 00727 } 00728 } 00729 00736 bool XMLString::isValidEncName(const XMLCh* const name) 00737 { 00738 if (name == 0 || *name == 0) 00739 return false; 00740 00741 const XMLCh* tempName = name; 00742 XMLCh firstChar = *tempName++; 00743 00744 if (!isAlpha(firstChar)) 00745 return false; 00746 00747 while(*tempName) 00748 { 00749 if (( !isAlpha(*tempName)) && 00750 ( !isDigit(*tempName)) && 00751 ( *tempName != chPeriod) && 00752 ( *tempName != chUnderscore) && 00753 ( *tempName != chDash) ) 00754 return false; 00755 00756 tempName++; 00757 } 00758 00759 return true; 00760 } 00761 00762 bool XMLString::isAlpha(XMLCh const theChar) 00763 { 00764 if ((( theChar >= chLatin_a ) && ( theChar <= chLatin_z )) || 00765 (( theChar >= chLatin_A ) && ( theChar <= chLatin_Z )) ) 00766 return true; 00767 00768 return false; 00769 } 00770 00771 bool XMLString::isDigit(XMLCh const theChar) 00772 { 00773 if (( theChar >= chDigit_0 ) && ( theChar <= chDigit_9 )) 00774 return true; 00775 00776 return false; 00777 } 00778 00779 bool XMLString::isAlphaNum(XMLCh const theChar) 00780 { 00781 return (isAlpha(theChar) || isDigit(theChar)); 00782 } 00783 00784 bool XMLString::isHex(XMLCh const theChar) 00785 { 00786 return (isDigit(theChar) || 00787 (theChar >= chLatin_a && theChar <= chLatin_f) || 00788 (theChar >= chLatin_A && theChar <= chLatin_F)); 00789 } 00790 00791 // --------------------------------------------------------------------------- 00792 // Wide char versions of most of the string methods 00793 // --------------------------------------------------------------------------- 00794 00795 void XMLString::sizeToText( const XMLSize_t toFormat 00796 , XMLCh* const toFill 00797 , const XMLSize_t maxChars 00798 , const unsigned int radix 00799 , MemoryManager* const manager) 00800 { 00801 static const XMLCh digitList[16] = 00802 { 00803 chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, chDigit_5 00804 , chDigit_6, chDigit_7, chDigit_8, chDigit_9, chLatin_A, chLatin_B 00805 , chLatin_C, chLatin_D, chLatin_e, chLatin_F 00806 }; 00807 00808 if (!maxChars) 00809 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 00810 00811 // Handle special case 00812 if (!toFormat) 00813 { 00814 toFill[0] = chDigit_0; 00815 toFill[1] = chNull; 00816 return; 00817 } 00818 00819 // This is used to fill the temp buffer 00820 XMLSize_t tmpIndex = 0; 00821 00822 // A copy of the conversion value that we can modify 00823 XMLSize_t tmpVal = toFormat; 00824 00825 // 00826 // Convert into a temp buffer that we know is large enough. This avoids 00827 // having to check for overflow in the inner loops, and we have to flip 00828 // the resulting sring anyway. 00829 // 00830 XMLCh tmpBuf[128]; 00831 00832 // 00833 // For each radix, do the optimal thing. For bin and hex, we can special 00834 // case them and do shift and mask oriented stuff. For oct and decimal 00835 // there isn't much to do but bull through it with divides. 00836 // 00837 if (radix == 2) 00838 { 00839 while (tmpVal) 00840 { 00841 if (tmpVal & 0x1UL) 00842 tmpBuf[tmpIndex++] = chDigit_1; 00843 else 00844 tmpBuf[tmpIndex++] = chDigit_0; 00845 tmpVal >>= 1; 00846 } 00847 } 00848 else if (radix == 16) 00849 { 00850 while (tmpVal) 00851 { 00852 const XMLSize_t charInd = (tmpVal & 0xFUL); 00853 tmpBuf[tmpIndex++] = digitList[charInd]; 00854 tmpVal >>= 4; 00855 } 00856 } 00857 else if ((radix == 8) || (radix == 10)) 00858 { 00859 while (tmpVal) 00860 { 00861 const XMLSize_t charInd = (tmpVal % radix); 00862 tmpBuf[tmpIndex++] = digitList[charInd]; 00863 tmpVal /= radix; 00864 } 00865 } 00866 else 00867 { 00868 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager); 00869 } 00870 00871 // See if have enough room in the caller's buffer 00872 if (tmpIndex > maxChars) 00873 { 00874 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager); 00875 } 00876 00877 // Reverse the tmp buffer into the caller's buffer 00878 XMLSize_t outIndex = 0; 00879 for (; tmpIndex > 0; tmpIndex--) 00880 toFill[outIndex++] = tmpBuf[tmpIndex-1]; 00881 00882 // And cap off the caller's buffer 00883 toFill[outIndex] = chNull; 00884 } 00885 00886 void XMLString::binToText( const unsigned long toFormat 00887 , XMLCh* const toFill 00888 , const XMLSize_t maxChars 00889 , const unsigned int radix 00890 , MemoryManager* const manager) 00891 { 00892 static const XMLCh digitList[16] = 00893 { 00894 chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, chDigit_5 00895 , chDigit_6, chDigit_7, chDigit_8, chDigit_9, chLatin_A, chLatin_B 00896 , chLatin_C, chLatin_D, chLatin_e, chLatin_F 00897 }; 00898 00899 if (!maxChars) 00900 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 00901 00902 // Handle special case 00903 if (!toFormat) 00904 { 00905 toFill[0] = chDigit_0; 00906 toFill[1] = chNull; 00907 return; 00908 } 00909 00910 // This is used to fill the temp buffer 00911 XMLSize_t tmpIndex = 0; 00912 00913 // A copy of the conversion value that we can modify 00914 unsigned long tmpVal = toFormat; 00915 00916 // 00917 // Convert into a temp buffer that we know is large enough. This avoids 00918 // having to check for overflow in the inner loops, and we have to flip 00919 // the resulting sring anyway. 00920 // 00921 XMLCh tmpBuf[128]; 00922 00923 // 00924 // For each radix, do the optimal thing. For bin and hex, we can special 00925 // case them and do shift and mask oriented stuff. For oct and decimal 00926 // there isn't much to do but bull through it with divides. 00927 // 00928 if (radix == 2) 00929 { 00930 while (tmpVal) 00931 { 00932 if (tmpVal & 0x1UL) 00933 tmpBuf[tmpIndex++] = chDigit_1; 00934 else 00935 tmpBuf[tmpIndex++] = chDigit_0; 00936 tmpVal >>= 1; 00937 } 00938 } 00939 else if (radix == 16) 00940 { 00941 while (tmpVal) 00942 { 00943 const unsigned long charInd = (tmpVal & 0xFUL); 00944 tmpBuf[tmpIndex++] = digitList[charInd]; 00945 tmpVal >>= 4; 00946 } 00947 } 00948 else if ((radix == 8) || (radix == 10)) 00949 { 00950 while (tmpVal) 00951 { 00952 const unsigned long charInd = (tmpVal % radix); 00953 tmpBuf[tmpIndex++] = digitList[charInd]; 00954 tmpVal /= radix; 00955 } 00956 } 00957 else 00958 { 00959 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager); 00960 } 00961 00962 // See if have enough room in the caller's buffer 00963 if (tmpIndex > maxChars) 00964 { 00965 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager); 00966 } 00967 00968 // Reverse the tmp buffer into the caller's buffer 00969 XMLSize_t outIndex = 0; 00970 for (; tmpIndex > 0; tmpIndex--) 00971 toFill[outIndex++] = tmpBuf[tmpIndex-1]; 00972 00973 // And cap off the caller's buffer 00974 toFill[outIndex] = chNull; 00975 } 00976 00977 void XMLString::binToText( const unsigned int toFormat 00978 , XMLCh* const toFill 00979 , const XMLSize_t maxChars 00980 , const unsigned int radix 00981 , MemoryManager* const manager) 00982 { 00983 // Just call the unsigned long version 00984 binToText((unsigned long)toFormat, toFill, maxChars, radix, manager); 00985 } 00986 00987 void XMLString::binToText( const long toFormat 00988 , XMLCh* const toFill 00989 , const XMLSize_t maxChars 00990 , const unsigned int radix 00991 , MemoryManager* const manager) 00992 { 00993 // 00994 // If its negative, then put a negative sign into the output and flip 00995 // the sign of the local temp value. 00996 // 00997 XMLSize_t startInd = 0; 00998 unsigned long actualVal; 00999 if (toFormat < 0) 01000 { 01001 toFill[0] = chDash; 01002 startInd++; 01003 // Signed integers can represent one extra negative value 01004 // compared to the positive values. If we simply do (v * -1) 01005 // we will overflow on that extra value. 01006 // 01007 long v = toFormat; 01008 v++; 01009 actualVal = (unsigned long)(v * -1); 01010 actualVal++; 01011 } 01012 else 01013 { 01014 actualVal = (unsigned long)(toFormat); 01015 } 01016 01017 // And now call the unsigned long version 01018 binToText(actualVal, &toFill[startInd], maxChars, radix, manager); 01019 } 01020 01021 void XMLString::binToText( const int toFormat 01022 , XMLCh* const toFill 01023 , const XMLSize_t maxChars 01024 , const unsigned int radix 01025 , MemoryManager* const manager) 01026 { 01027 // Just call the long version 01028 binToText((long)toFormat, toFill, maxChars, radix, manager); 01029 } 01030 01031 void XMLString::catString(XMLCh* const target, const XMLCh* const src) 01032 { 01033 // Get the starting point for the cat on the target XMLString 01034 XMLSize_t index = stringLen(target); 01035 01036 // While the source is not zero, add them to target and bump 01037 const XMLCh* pszTmp = src; 01038 while (*pszTmp) 01039 target[index++] = *pszTmp++; 01040 01041 // Cap off the target where we ended 01042 target[index] = chNull; 01043 } 01044 01045 01046 int XMLString::compareIString( const XMLCh* const str1 01047 , const XMLCh* const str2) 01048 { 01049 // Refer this one to the transcoding service 01050 return XMLPlatformUtils::fgTransService->compareIString(str1, str2); 01051 } 01052 01053 int XMLString::compareIStringASCII( const XMLCh* const str1 01054 , const XMLCh* const str2) 01055 { 01056 const XMLCh* psz1 = str1; 01057 const XMLCh* psz2 = str2; 01058 01059 if (psz1 == 0 || psz2 == 0) { 01060 01061 if (psz1 == 0) { 01062 return 0 - (int)XMLString::stringLen(psz2); 01063 } 01064 else if (psz2 == 0) { 01065 return (int)XMLString::stringLen(psz1); 01066 } 01067 } 01068 01069 XMLCh ch1; 01070 XMLCh ch2; 01071 01072 for (;;) { 01073 if (*psz1 >= chLatin_A && *psz1 <= chLatin_Z) 01074 ch1 = *psz1 - chLatin_A + chLatin_a; 01075 else 01076 ch1 = *psz1; 01077 if (*psz2 >= chLatin_A && *psz2 <= chLatin_Z) 01078 ch2 = *psz2 - chLatin_A + chLatin_a; 01079 else 01080 ch2 = *psz2; 01081 01082 // If an inequality, then return difference 01083 if (ch1 != ch2) 01084 return int(ch1) - int(ch2); 01085 01086 // If either ended, then both ended, so equal 01087 if (!ch1) 01088 break; 01089 01090 // Move upwards to next chars 01091 psz1++; 01092 psz2++; 01093 } 01094 return 0; 01095 } 01096 01097 int XMLString::compareNString( const XMLCh* const str1 01098 , const XMLCh* const str2 01099 , const XMLSize_t maxChars) 01100 { 01101 const XMLCh* psz1 = str1; 01102 const XMLCh* psz2 = str2; 01103 01104 XMLSize_t curCount = 0; 01105 while (curCount < maxChars) 01106 { 01107 // If an inequality, then return difference 01108 if (*psz1 != *psz2) 01109 return int(*psz1) - int(*psz2); 01110 01111 // If either ended, then both ended, so equal 01112 if (!*psz1) 01113 break; 01114 01115 // Move upwards to next chars 01116 psz1++; 01117 psz2++; 01118 01119 // 01120 // Bump the count of chars done. 01121 // 01122 curCount++; 01123 } 01124 // If we inspected all the maxChars, then we are equal. 01125 return 0; 01126 } 01127 01128 01129 int XMLString::compareNIString( const XMLCh* const str1 01130 , const XMLCh* const str2 01131 , const XMLSize_t maxChars) 01132 { 01133 // Refer this oneto the transcoding service 01134 return XMLPlatformUtils::fgTransService->compareNIString(str1, str2, maxChars); 01135 } 01136 01137 01138 int XMLString::compareString( const XMLCh* const str1 01139 , const XMLCh* const str2) 01140 { 01141 const XMLCh* psz1 = str1; 01142 const XMLCh* psz2 = str2; 01143 01144 if (psz1 == 0 || psz2 == 0) { 01145 01146 if (psz1 == 0) { 01147 return 0 - (int)XMLString::stringLen(psz2); 01148 } 01149 else if (psz2 == 0) { 01150 return (int)XMLString::stringLen(psz1); 01151 } 01152 } 01153 01154 for (;;) 01155 { 01156 // If an inequality, then return the difference 01157 if (*psz1 != *psz2) 01158 return int(*psz1) - int(*psz2); 01159 01160 // If either has ended, then they both ended, so equal 01161 if (!*psz1) 01162 break; 01163 01164 // Move upwards for the next round 01165 psz1++; 01166 psz2++; 01167 } 01168 return 0; 01169 } 01170 01171 01172 bool XMLString::regionMatches(const XMLCh* const str1 01173 , const int offset1 01174 , const XMLCh* const str2 01175 , const int offset2 01176 , const XMLSize_t charCount) 01177 { 01178 if (!validateRegion(str1, offset1,str2, offset2, charCount)) 01179 return false; 01180 01181 if (compareNString(str1+offset1, str2+offset2, charCount) != 0) 01182 return false; 01183 01184 return true; 01185 } 01186 01187 bool XMLString::regionIMatches(const XMLCh* const str1 01188 , const int offset1 01189 , const XMLCh* const str2 01190 , const int offset2 01191 , const XMLSize_t charCount) 01192 { 01193 if (!validateRegion(str1, offset1,str2, offset2, charCount)) 01194 return false; 01195 01196 if (compareNIString(str1+offset1, str2+offset2, charCount) != 0) 01197 return false; 01198 01199 return true; 01200 } 01201 01202 void XMLString::copyString(XMLCh* const target, const XMLCh* const src) 01203 { 01204 if (!src) 01205 { 01206 *target = 0; 01207 return; 01208 } 01209 01210 XMLCh* pszOut = target; 01211 const XMLCh* pszIn = src; 01212 while (*pszIn) 01213 *pszOut++ = *pszIn++; 01214 01215 // Cap off the target where we ended 01216 *pszOut = 0; 01217 } 01218 01219 01220 bool XMLString::copyNString( XMLCh* const target 01221 , const XMLCh* const src 01222 , const XMLSize_t maxChars) 01223 { 01224 // Return whether we copied it all or hit the max 01225 XMLSize_t len = stringLen(src); 01226 if(len > maxChars) 01227 { 01228 XMLString::moveChars(target, src, maxChars); 01229 target[maxChars] = 0; 01230 return false; 01231 } 01232 XMLString::moveChars(target, src, len+1); 01233 return true; 01234 } 01235 01236 const XMLCh* XMLString::findAny(const XMLCh* const toSearch 01237 , const XMLCh* const searchList) 01238 { 01239 const XMLCh* srcPtr = toSearch; 01240 while (*srcPtr) 01241 { 01242 const XMLCh* listPtr = searchList; 01243 const XMLCh curCh = *srcPtr; 01244 01245 while (*listPtr) 01246 { 01247 if (curCh == *listPtr++) 01248 return srcPtr; 01249 } 01250 srcPtr++; 01251 } 01252 return 0; 01253 } 01254 01255 XMLCh* XMLString::findAny( XMLCh* const toSearch 01256 , const XMLCh* const searchList) 01257 { 01258 XMLCh* srcPtr = toSearch; 01259 while (*srcPtr) 01260 { 01261 const XMLCh* listPtr = searchList; 01262 const XMLCh curCh = *srcPtr; 01263 01264 while (*listPtr) 01265 { 01266 if (curCh == *listPtr++) 01267 return srcPtr; 01268 } 01269 srcPtr++; 01270 } 01271 return 0; 01272 } 01273 01274 int XMLString::patternMatch( const XMLCh* const toSearch 01275 , const XMLCh* const pattern) 01276 { 01277 if (!toSearch || !*toSearch ) 01278 return -1; 01279 01280 const XMLSize_t patnLen = XMLString::stringLen(pattern); 01281 if ( !patnLen ) 01282 return -1; 01283 01284 const XMLCh* srcPtr = toSearch; 01285 const XMLCh* patnStart = toSearch; 01286 XMLSize_t patnIndex = 0; 01287 01288 while (*srcPtr) 01289 { 01290 if ( !(*srcPtr++ == pattern[patnIndex])) 01291 { 01292 patnIndex = 0; 01293 srcPtr = ++patnStart; 01294 } 01295 else 01296 { 01297 if (++patnIndex == patnLen) 01298 // full pattern match found 01299 return (int)(srcPtr - patnLen - toSearch); 01300 01301 } 01302 } 01303 01304 return -1; 01305 } 01306 01307 01308 int XMLString::indexOf(const XMLCh* const toSearch, const XMLCh ch) 01309 { 01310 if (!toSearch || !*toSearch) return -1; 01311 01312 const XMLCh* srcPtr = toSearch; 01313 while (*srcPtr) 01314 if (ch == *srcPtr++) 01315 return (int)(srcPtr - toSearch - 1); 01316 return -1; 01317 } 01318 01319 01320 int XMLString::indexOf( const XMLCh* const toSearch 01321 , const XMLCh ch 01322 , const XMLSize_t fromIndex 01323 , MemoryManager* const manager) 01324 { 01325 const XMLSize_t len = stringLen(toSearch); 01326 01327 // Make sure the start index is within the XMLString bounds 01328 if (fromIndex >= len) 01329 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 01330 01331 const XMLCh* srcPtr = toSearch+fromIndex; 01332 while (*srcPtr) 01333 if (ch == *srcPtr++) 01334 return (int)(srcPtr - toSearch - 1); 01335 return -1; 01336 } 01337 01338 int XMLString::lastIndexOf(const XMLCh ch, 01339 const XMLCh* const toSearch, 01340 const XMLSize_t toSearchLen) 01341 { 01342 const XMLCh* srcPtr = toSearch+toSearchLen; 01343 while (srcPtr >= toSearch) 01344 if (ch == *srcPtr--) 01345 return (int)(srcPtr + 1 - toSearch); 01346 return -1; 01347 } 01348 01349 int XMLString::lastIndexOf( const XMLCh* const toSearch 01350 , const XMLCh ch 01351 , const XMLSize_t fromIndex 01352 , MemoryManager* const manager) 01353 { 01354 const XMLSize_t len = stringLen(toSearch); 01355 if (fromIndex >= len) 01356 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 01357 01358 const XMLCh* srcPtr = toSearch+fromIndex; 01359 while (srcPtr >= toSearch) 01360 if (ch == *srcPtr--) 01361 return (int)(srcPtr + 1 - toSearch); 01362 return -1; 01363 } 01364 01365 01366 XMLCh* 01367 XMLString::makeUName(const XMLCh* const pszURI, const XMLCh* const pszName) 01368 { 01369 // 01370 // If there is a URI, then format out the full name in the {uri}name 01371 // form. Otherwise, just set it to the same thing as the base name. 01372 // 01373 XMLCh* pszRet = 0; 01374 const XMLSize_t uriLen = stringLen(pszURI); 01375 if (uriLen) 01376 { 01377 pszRet = new XMLCh[uriLen + stringLen(pszName) + 3]; 01378 01379 XMLCh szTmp[2]; 01380 szTmp[1] = 0; 01381 01382 szTmp[0] = chOpenCurly; 01383 copyString(pszRet, szTmp); 01384 catString(pszRet, pszURI); 01385 szTmp[0] = chCloseCurly; 01386 catString(pszRet, szTmp); 01387 catString(pszRet, pszName); 01388 } 01389 else 01390 { 01391 pszRet = replicate(pszName); 01392 } 01393 return pszRet; 01394 } 01395 01396 01397 bool XMLString::textToBin(const XMLCh* const toConvert, unsigned int& toFill 01398 , MemoryManager* const manager) 01399 { 01400 toFill = 0; 01401 01402 // If no string, then its a failure 01403 if ((!toConvert) || (!*toConvert)) 01404 return false; 01405 01406 XMLCh* trimmedStr = XMLString::replicate(toConvert, manager); 01407 ArrayJanitor<XMLCh> jan1(trimmedStr, manager); 01408 XMLString::trim(trimmedStr); 01409 XMLSize_t trimmedStrLen = XMLString::stringLen(trimmedStr); 01410 01411 if ( !trimmedStrLen ) 01412 return false; 01413 01414 // we don't allow '-' sign 01415 if (XMLString::indexOf(trimmedStr, chDash, 0, manager) != -1) 01416 return false; 01417 01418 //the errno set by previous run is NOT automatically cleared 01419 errno = 0; 01420 01421 char *nptr = XMLString::transcode(trimmedStr, manager); 01422 ArrayJanitor<char> jan2(nptr, manager); 01423 01424 char *endptr; 01425 // 01426 // REVISIT: conversion of (unsigned long) to (unsigned int) 01427 // may truncate value on IA64 01428 toFill = (unsigned int) strtoul(nptr, &endptr, 10); 01429 01430 // check if all chars are valid char 01431 // check if overflow/underflow occurs 01432 if ( ( (endptr - nptr) != (int) trimmedStrLen) || 01433 (errno == ERANGE) ) 01434 return false; 01435 01436 return true; 01437 } 01438 01439 int XMLString::parseInt(const XMLCh* const toConvert 01440 , MemoryManager* const manager) 01441 { 01442 // If no string, or empty string, then it is a failure 01443 if ((!toConvert) || (!*toConvert)) 01444 ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager); 01445 01446 XMLCh* trimmedStr = XMLString::replicate(toConvert, manager); 01447 ArrayJanitor<XMLCh> jan1(trimmedStr, manager); 01448 XMLString::trim(trimmedStr); 01449 XMLSize_t trimmedStrLen = XMLString::stringLen(trimmedStr); 01450 01451 if ( !trimmedStrLen ) 01452 ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager); 01453 01454 //the errno set by previous run is NOT automatically cleared 01455 errno = 0; 01456 01457 char *nptr = XMLString::transcode(trimmedStr, manager); 01458 ArrayJanitor<char> jan2(nptr, manager); 01459 01460 char *endptr; 01461 long retVal = strtol(nptr, &endptr, 10); 01462 01463 // check if all chars are valid char 01464 if ( (endptr - nptr) != (int) trimmedStrLen) 01465 ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager); 01466 01467 // check if overflow/underflow occurs 01468 if (errno == ERANGE) 01469 ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::Str_ConvertOverflow, manager); 01470 01471 // 01472 // REVISIT: conversion of (long) to (int) 01473 // may truncate value on IA64 01474 return (int) retVal; 01475 } 01476 01477 01478 void XMLString::trim(XMLCh* const toTrim) 01479 { 01480 const XMLSize_t len = stringLen(toTrim); 01481 01482 XMLSize_t skip, scrape; 01483 for (skip = 0; skip < len; skip++) 01484 { 01485 if (!XMLChar1_0::isWhitespace(toTrim[skip])) 01486 break; 01487 } 01488 01489 for (scrape = len; scrape > skip; scrape--) 01490 { 01491 if (!XMLChar1_0::isWhitespace(toTrim[scrape - 1])) 01492 break; 01493 } 01494 01495 // Cap off at the scrap point 01496 if (scrape != len) 01497 toTrim[scrape] = 0; 01498 01499 if (skip) 01500 { 01501 // Copy the chars down 01502 XMLSize_t index = 0; 01503 while (toTrim[skip]) 01504 toTrim[index++] = toTrim[skip++]; 01505 01506 toTrim[index] = 0; 01507 } 01508 } 01509 01510 01511 void XMLString::upperCase(XMLCh* const toUpperCase) 01512 { 01513 // Refer this one to the transcoding service 01514 XMLPlatformUtils::fgTransService->upperCase(toUpperCase); 01515 } 01516 01517 void XMLString::upperCaseASCII(XMLCh* const toUpperCase) 01518 { 01519 XMLCh* psz1 = toUpperCase; 01520 01521 if (!psz1) 01522 return; 01523 01524 while (*psz1) { 01525 if (*psz1 >= chLatin_a && *psz1 <= chLatin_z) 01526 *psz1 = *psz1 - chLatin_a + chLatin_A; 01527 01528 psz1++; 01529 } 01530 } 01531 01532 01533 void XMLString::lowerCase(XMLCh* const toLowerCase) 01534 { 01535 // Refer this one to the transcoding service 01536 XMLPlatformUtils::fgTransService->lowerCase(toLowerCase); 01537 } 01538 01539 void XMLString::lowerCaseASCII(XMLCh* const toLowerCase) 01540 { 01541 XMLCh* psz1 = toLowerCase; 01542 01543 if (!psz1) 01544 return; 01545 01546 while (*psz1) { 01547 if (*psz1 >= chLatin_A && *psz1 <= chLatin_Z) 01548 *psz1 = *psz1 - chLatin_A + chLatin_a; 01549 01550 psz1++; 01551 } 01552 } 01553 01554 void XMLString::subString(XMLCh* const targetStr, const XMLCh* const srcStr 01555 , const XMLSize_t startIndex, const XMLSize_t endIndex 01556 , MemoryManager* const manager) 01557 { 01558 subString(targetStr, srcStr, startIndex, endIndex, stringLen(srcStr), manager); 01559 } 01560 01561 void XMLString::subString(XMLCh* const targetStr, const XMLCh* const srcStr 01562 , const XMLSize_t startIndex, const XMLSize_t endIndex 01563 , const XMLSize_t srcStrLength 01564 , MemoryManager* const manager) 01565 { 01566 //if (startIndex < 0 || endIndex < 0) 01567 // ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_NegativeIndex); 01568 01569 if (targetStr == 0) 01570 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager); 01571 01572 // Make sure the start index is within the XMLString bounds 01573 if (startIndex > endIndex || endIndex > srcStrLength) 01574 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager); 01575 01576 const XMLSize_t copySize = endIndex - startIndex; 01577 01578 for (XMLSize_t i= startIndex; i < endIndex; i++) { 01579 targetStr[i-startIndex] = srcStr[i]; 01580 } 01581 01582 targetStr[copySize] = 0; 01583 } 01584 01585 BaseRefVectorOf<XMLCh>* XMLString::tokenizeString(const XMLCh* const tokenizeSrc 01586 , MemoryManager* const manager) 01587 { 01588 XMLCh* orgText = replicate(tokenizeSrc, manager); 01589 ArrayJanitor<XMLCh> janText(orgText, manager); 01590 XMLCh* tokenizeStr = orgText; 01591 01592 RefArrayVectorOf<XMLCh>* tokenStack = new (manager) RefArrayVectorOf<XMLCh>(16, true, manager); 01593 01594 XMLSize_t len = stringLen(tokenizeStr); 01595 XMLSize_t skip; 01596 XMLSize_t index = 0; 01597 01598 while (index != len) { 01599 // find the first non-space character 01600 for (skip = index; skip < len; skip++) 01601 { 01602 if (!XMLChar1_0::isWhitespace(tokenizeStr[skip])) 01603 break; 01604 } 01605 index = skip; 01606 01607 // find the delimiter (space character) 01608 for (; skip < len; skip++) 01609 { 01610 if (XMLChar1_0::isWhitespace(tokenizeStr[skip])) 01611 break; 01612 } 01613 01614 // we reached the end of the string 01615 if (skip == index) 01616 break; 01617 01618 // these tokens are adopted in the RefVector and will be deleted 01619 // when the vector is deleted by the caller 01620 XMLCh* token = (XMLCh*) manager->allocate 01621 ( 01622 (skip+1-index) * sizeof(XMLCh) 01623 );//new XMLCh[skip+1-index]; 01624 01625 XMLString::subString(token, tokenizeStr, index, skip, len, manager); 01626 tokenStack->addElement(token); 01627 index = skip; 01628 } 01629 return tokenStack; 01630 } 01631 01632 // 01633 // This method is called when we get a notation or enumeration type attribute 01634 // to validate. We have to confirm that the passed value to find is one of 01635 // the values in the passed list. The list is a space separated string of 01636 // values to match against. 01637 // 01638 bool XMLString::isInList(const XMLCh* const toFind, const XMLCh* const enumList) 01639 { 01640 // 01641 // We loop through the values in the list via this outer loop. We end 01642 // when we hit the end of the enum list or get a match. 01643 // 01644 const XMLCh* listPtr = enumList; 01645 const XMLSize_t findLen = XMLString::stringLen(toFind); 01646 while (*listPtr) 01647 { 01648 XMLSize_t testInd; 01649 for (testInd = 0; testInd < findLen; testInd++) 01650 { 01651 // 01652 // If they don't match, then reset and try again. Note that 01653 // hitting the end of the current item will cause a mismatch 01654 // because there can be no spaces in the toFind string. 01655 // 01656 if (listPtr[testInd] != toFind[testInd]) 01657 break; 01658 } 01659 01660 // 01661 // If we went the distance, see if we matched. If we did, the current 01662 // list character has to be null or space. 01663 // 01664 if (testInd == findLen) 01665 { 01666 if ((listPtr[testInd] == chSpace) || !listPtr[testInd]) 01667 return true; 01668 } 01669 01670 // Run the list pointer up to the next substring 01671 while ((*listPtr != chSpace) && *listPtr) 01672 listPtr++; 01673 01674 // If we hit the end, then we failed 01675 if (!*listPtr) 01676 return false; 01677 01678 // Else move past the space and try again 01679 listPtr++; 01680 } 01681 01682 // We never found it 01683 return false; 01684 } 01685 01686 // 01687 // a string is whitespace:replaced, is having no 01688 // #xD Carriage Return 01689 // #xA Line Feed 01690 // #x9 TAB 01691 // 01692 bool XMLString::isWSReplaced(const XMLCh* const toCheck) 01693 { 01694 // If no string, then its a OK 01695 if (( !toCheck ) || ( !*toCheck )) 01696 return true; 01697 01698 const XMLCh* startPtr = toCheck; 01699 while ( *startPtr ) 01700 { 01701 if ( ( *startPtr == chCR) || 01702 ( *startPtr == chLF) || 01703 ( *startPtr == chHTab)) 01704 return false; 01705 01706 startPtr++; 01707 } 01708 01709 return true; 01710 } 01711 01712 // 01713 // to replace characters listed below to #x20 01714 // #xD Carriage Return 01715 // #xA Line Feed 01716 // #x9 TAB 01717 // 01718 void XMLString::replaceWS(XMLCh* toConvert, MemoryManager* const) 01719 { 01720 // If no string, then its a OK 01721 if (( !toConvert ) || ( !*toConvert )) 01722 return; 01723 01724 XMLCh* cursorPtr = toConvert; 01725 while ( *cursorPtr ) 01726 { 01727 if ( ( *cursorPtr == chCR) || 01728 ( *cursorPtr == chLF) || 01729 ( *cursorPtr == chHTab)) 01730 *cursorPtr = chSpace; 01731 01732 cursorPtr++; 01733 } 01734 } 01735 01736 // 01737 // a string is whitespace:collapsed, is whitespace::replaced 01738 // and no 01739 // leading space (#x20) 01740 // trailing space 01741 // no contiguous sequences of spaces 01742 // 01743 bool XMLString::isWSCollapsed(const XMLCh* const toCheck) 01744 { 01745 if (( !toCheck ) || ( !*toCheck )) 01746 return true; 01747 01748 // shall be whitespace::replaced first 01749 if ( !isWSReplaced(toCheck) ) 01750 return false; 01751 01752 // no leading or trailing space 01753 if ((*toCheck == chSpace) || 01754 (toCheck[XMLString::stringLen(toCheck)-1] == chSpace)) 01755 return false; 01756 01757 const XMLCh* startPtr = toCheck; 01758 XMLCh theChar; 01759 bool inSpace = false; 01760 while ( (theChar = *startPtr) != 0 ) 01761 { 01762 if ( theChar == chSpace) 01763 { 01764 if (inSpace) 01765 return false; 01766 else 01767 inSpace = true; 01768 } 01769 else 01770 inSpace = false; 01771 01772 startPtr++; 01773 01774 } 01775 01776 return true; 01777 } 01778 01779 // 01780 // no leading and/or trailing spaces 01781 // no continuous sequences of spaces 01782 // 01783 void XMLString::collapseWS(XMLCh* toConvert 01784 , MemoryManager* const manager) 01785 { 01786 // If no string, then its a failure 01787 if (( !toConvert ) || ( !*toConvert )) 01788 return; 01789 01790 // replace whitespace first 01791 if(!isWSReplaced(toConvert)) 01792 replaceWS(toConvert, manager); 01793 01794 // remove leading spaces 01795 XMLCh* startPtr = toConvert; 01796 while ( *startPtr == chSpace ) 01797 startPtr++; 01798 01799 if (!*startPtr) 01800 { 01801 *toConvert = chNull; 01802 return; 01803 } 01804 01805 // remove trailing spaces 01806 XMLCh* endPtr = toConvert + stringLen(toConvert); 01807 while (*(endPtr - 1) == chSpace) 01808 endPtr--; 01809 *endPtr = chNull; 01810 01811 // move data to beginning only if there were spaces in front 01812 if(startPtr != toConvert) 01813 XMLString::moveChars(toConvert, startPtr, endPtr - startPtr + 1); 01814 01815 if(!isWSCollapsed(toConvert)) 01816 { 01817 // 01818 // Work through what remains and chop continuous spaces 01819 // 01820 XMLCh* retPtr = toConvert; 01821 startPtr = toConvert; 01822 bool inSpace = false; 01823 while (*startPtr) 01824 { 01825 if ( *startPtr == chSpace) 01826 { 01827 // copy a single space, then ignore subsequent 01828 if (!inSpace) 01829 { 01830 inSpace = true; 01831 *retPtr++ = chSpace; 01832 } 01833 } 01834 else 01835 { 01836 inSpace = false; 01837 *retPtr++ = *startPtr; 01838 } 01839 01840 startPtr++; 01841 } 01842 01843 *retPtr = chNull; 01844 } 01845 } 01846 01847 // 01848 // remove whitespace 01849 // 01850 void XMLString::removeWS(XMLCh* toConvert, MemoryManager* const) 01851 { 01852 // If no string, then its a failure 01853 if (( !toConvert ) || ( !*toConvert )) 01854 return; 01855 01856 XMLCh* retPtr = toConvert; 01857 XMLCh* startPtr = toConvert; 01858 01859 while (*startPtr) 01860 { 01861 if ( ( *startPtr != chCR) && 01862 ( *startPtr != chLF) && 01863 ( *startPtr != chHTab) && 01864 ( *startPtr != chSpace) ) 01865 { 01866 *retPtr++ = *startPtr; 01867 } 01868 01869 startPtr++; 01870 } 01871 01872 *retPtr = chNull; 01873 } 01874 01875 void XMLString::removeChar(const XMLCh* const srcString 01876 , const XMLCh& toRemove 01877 , XMLBuffer& dstBuffer) 01878 { 01879 if(!srcString) return; 01880 const XMLCh* pszSrc = srcString; 01881 XMLCh c; 01882 01883 dstBuffer.reset(); 01884 01885 while ((c=*pszSrc++)!=0) 01886 { 01887 if (c != toRemove) 01888 dstBuffer.append(c); 01889 } 01890 } 01891 01897 void XMLString::fixURI(const XMLCh* const str, XMLCh* const target) 01898 { 01899 if (!str || !*str) 01900 return; 01901 01902 int colonIdx = XMLString::indexOf(str, chColon); 01903 01904 // If starts with a '/' we assume 01905 // this is an absolute (UNIX) file path and prefix it with file:// 01906 if (colonIdx == -1 && XMLString::indexOf(str, chForwardSlash) == 0) { 01907 unsigned index = 0; 01908 target[index++] = chLatin_f; 01909 target[index++] = chLatin_i; 01910 target[index++] = chLatin_l; 01911 target[index++] = chLatin_e; 01912 target[index++] = chColon; 01913 target[index++] = chForwardSlash; 01914 target[index++] = chForwardSlash; 01915 01916 // copy the string 01917 const XMLCh* inPtr = str; 01918 while (*inPtr) 01919 target[index++] = *inPtr++; 01920 01921 target[index] = chNull; 01922 } 01923 else if (colonIdx == 1 && XMLString::isAlpha(*str)) { 01924 // If starts with a driver letter 'x:' we assume 01925 // this is an absolute (Windows) file path and prefix it with file:/// 01926 unsigned index = 0; 01927 target[index++] = chLatin_f; 01928 target[index++] = chLatin_i; 01929 target[index++] = chLatin_l; 01930 target[index++] = chLatin_e; 01931 target[index++] = chColon; 01932 target[index++] = chForwardSlash; 01933 target[index++] = chForwardSlash; 01934 target[index++] = chForwardSlash; 01935 01936 // copy the string and fix any backward slash 01937 const XMLCh* inPtr = str; 01938 while (*inPtr) { 01939 if (*inPtr == chYenSign || 01940 *inPtr == chWonSign || 01941 *inPtr == chBackSlash) 01942 target[index++] = chForwardSlash; 01943 else 01944 target[index++] = *inPtr; 01945 inPtr++; 01946 } 01947 01948 // cap it with null 01949 target[index] = chNull; 01950 } 01951 else { 01952 // not specific case, so just copy the string over 01953 copyString(target, str); 01954 } 01955 } 01956 01957 void XMLString::release(char** buf, MemoryManager* const manager) 01958 { 01959 manager->deallocate(*buf); 01960 *buf = 0; 01961 } 01962 01963 void XMLString::release(XMLCh** buf, MemoryManager* const manager) 01964 { 01965 manager->deallocate(*buf); 01966 *buf = 0; 01967 } 01968 01969 // --------------------------------------------------------------------------- 01970 // XMLString: Private static methods 01971 // --------------------------------------------------------------------------- 01972 void XMLString::initString(XMLLCPTranscoder* const defToUse, 01973 MemoryManager* const manager) 01974 { 01975 // Store away the default transcoder that we are to use 01976 gTranscoder = defToUse; 01977 01978 // Store memory manager 01979 fgMemoryManager = manager; 01980 } 01981 01982 void XMLString::termString() 01983 { 01984 // Just clean up our local code page transcoder 01985 delete gTranscoder; 01986 gTranscoder = 0; 01987 01988 // reset memory manager 01989 fgMemoryManager = 0; 01990 } 01991 01992 XERCES_CPP_NAMESPACE_END