GME  13
XMLString.cpp
Go to the documentation of this file.
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