XMLString.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:47k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: XMLString.cpp,v 1.30 2001/11/28 16:44:24 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <string.h>
  63. #include <ctype.h>
  64. #include <util/ArrayIndexOutOfBoundsException.hpp>
  65. #include <util/IllegalArgumentException.hpp>
  66. #include <util/NumberFormatException.hpp>
  67. #include <util/Janitor.hpp>
  68. #include <util/PlatformUtils.hpp>
  69. #include <util/RuntimeException.hpp>
  70. #include <util/TransService.hpp>
  71. #include <util/TranscodingException.hpp>
  72. #include <util/ValueArrayOf.hpp>
  73. #include <util/XMLString.hpp>
  74. #include <util/XMLUniDefs.hpp>
  75. #include <util/XMLUni.hpp>
  76. #include <internal/XMLReader.hpp>
  77. // ---------------------------------------------------------------------------
  78. //  Local static data
  79. //
  80. //  gConverter
  81. //      This is initialized when the user calls the platform init method,
  82. //      which calls our init method. This is the converter used for default
  83. //      conversion to/from the local code page.
  84. // ---------------------------------------------------------------------------
  85. static XMLLCPTranscoder*    gTranscoder = 0;
  86. static XMLCh                gNullStr[] =
  87. {
  88.     chOpenCurly, chLatin_n, chLatin_u, chLatin_l, chLatin_l, chCloseCurly, chNull
  89. };
  90. // ---------------------------------------------------------------------------
  91. //  XMLString: Public static methods
  92. // ---------------------------------------------------------------------------
  93. void XMLString::binToText(  const   unsigned long   toFormat
  94.                             ,       char* const     toFill
  95.                             , const unsigned int    maxChars
  96.                             , const unsigned int    radix)
  97. {
  98.     static const char digitList[16] =
  99.     {
  100.           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
  101.         , 'A', 'B', 'C', 'D', 'E', 'F'
  102.     };
  103.     if (!maxChars)
  104.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf);
  105.     // Handle special case
  106.     if (!toFormat)
  107.     {
  108.         toFill[0] = '0';
  109.         toFill[1] = 0;
  110.         return;
  111.     }
  112.     // This is used to fill the temp buffer
  113.     unsigned int tmpIndex = 0;
  114.     // A copy of the conversion value that we can modify
  115.     unsigned int tmpVal = toFormat;
  116.     //
  117.     //  Convert into a temp buffer that we know is large enough. This avoids
  118.     //  having to check for overflow in the inner loops, and we have to flip
  119.     //  the resulting XMLString anyway.
  120.     //
  121.     char tmpBuf[128];
  122.     //
  123.     //  For each radix, do the optimal thing. For bin and hex, we can special
  124.     //  case them and do shift and mask oriented stuff. For oct and decimal
  125.     //  there isn't much to do but bull through it with divides.
  126.     //
  127.     if (radix == 2)
  128.     {
  129.         while (tmpVal)
  130.         {
  131.             if (tmpVal & 0x1UL)
  132.                 tmpBuf[tmpIndex++] = '1';
  133.             else
  134.                 tmpBuf[tmpIndex++] = '0';
  135.             tmpVal >>= 1;
  136.         }
  137.     }
  138.      else if (radix == 16)
  139.     {
  140.         while (tmpVal)
  141.         {
  142.             const unsigned int charInd = (tmpVal & 0xFUL);
  143.             tmpBuf[tmpIndex++] = digitList[charInd];
  144.             tmpVal >>= 4;
  145.         }
  146.     }
  147.      else if ((radix == 8) || (radix == 10))
  148.     {
  149.         while (tmpVal)
  150.         {
  151.             const unsigned int charInd = (tmpVal % radix);
  152.             tmpBuf[tmpIndex++] = digitList[charInd];
  153.             tmpVal /= radix;
  154.         }
  155.     }
  156.      else
  157.     {
  158.         ThrowXML(RuntimeException, XMLExcepts::Str_UnknownRadix);
  159.     }
  160.     // See if have enough room in the caller's buffer
  161.     if (tmpIndex > maxChars)
  162.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall);
  163.     // Reverse the tmp buffer into the caller's buffer
  164.     unsigned int outIndex = 0;
  165.     for (; tmpIndex > 0; tmpIndex--)
  166.         toFill[outIndex++] = tmpBuf[tmpIndex-1];
  167.     // And cap off the caller's buffer
  168.     toFill[outIndex] = char(0);
  169. }
  170. void XMLString::binToText(  const   unsigned int    toFormat
  171.                             ,       char* const     toFill
  172.                             , const unsigned int    maxChars
  173.                             , const unsigned int    radix)
  174. {
  175.     // Just call the unsigned long version
  176.     binToText((unsigned long)toFormat, toFill, maxChars, radix);
  177. }
  178. void XMLString::binToText(  const   long            toFormat
  179.                             ,       char* const     toFill
  180.                             , const unsigned int    maxChars
  181.                             , const unsigned int    radix)
  182. {
  183.     //
  184.     //  If its negative, then put a negative sign into the output and flip
  185.     //  the sign of the local temp value.
  186.     //
  187.     unsigned int startInd = 0;
  188.     unsigned long actualVal;
  189.     if (toFormat < 0)
  190.     {
  191.         toFill[0] = '-';
  192.         startInd++;
  193.         actualVal = (unsigned long)(toFormat * -1);
  194.     }
  195.      else
  196.     {
  197.         actualVal = (unsigned long)(toFormat);
  198.     }
  199.     // And now call the unsigned long version
  200.     binToText(actualVal, &toFill[startInd], maxChars, radix);
  201. }
  202. void XMLString::binToText(  const   int             toFormat
  203.                             ,       char* const     toFill
  204.                             , const unsigned int    maxChars
  205.                             , const unsigned int    radix)
  206. {
  207.     //
  208.     //  If its negative, then put a negative sign into the output and flip
  209.     //  the sign of the local temp value.
  210.     //
  211.     unsigned int startInd = 0;
  212.     unsigned long actualVal;
  213.     if (toFormat < 0)
  214.     {
  215.         toFill[0] = '-';
  216.         startInd++;
  217.         actualVal = (unsigned long)(toFormat * -1);
  218.     }
  219.      else
  220.     {
  221.         actualVal = (unsigned long)(toFormat);
  222.     }
  223.     // And now call the unsigned long version
  224.     binToText(actualVal, &toFill[startInd], maxChars, radix);
  225. }
  226. void XMLString::catString(char* const target, const char* const src)
  227. {
  228.     strcat(target, src);
  229. }
  230. int XMLString::compareIString(const char* const str1, const char* const str2)
  231. {
  232.     return stricmp(str1, str2);
  233. }
  234. int XMLString::compareNString(  const   char* const     str1
  235.                                 , const char* const     str2
  236.                                 , const unsigned int    count)
  237. {
  238.     // Watch for pathological secenario
  239.     if (!count)
  240.         return 0;
  241.     return strncmp(str1, str2, count);
  242. }
  243. int XMLString::compareNIString( const   char* const     str1
  244.                                 , const char* const     str2
  245.                                 , const unsigned int    count)
  246. {
  247.     if (!count)
  248.         return 0;
  249.     return strnicmp(str1, str2, count);
  250. }
  251. int XMLString::compareString(   const   char* const    str1
  252.                                 , const char* const    str2)
  253. {
  254.     return strcmp(str1, str2);
  255. }
  256. void XMLString::copyString(         char* const    target
  257.                             , const char* const    src)
  258. {
  259.     strcpy(target, src);
  260. }
  261. void XMLString::cut(        XMLCh* const    toCutFrom
  262.                     , const unsigned int    count)
  263. {
  264.     #if defined(XML_DEBUG)
  265.     if (count > stringLen(toCutFrom))
  266.     {
  267.         // <TBD> This is bad of course
  268.     }
  269.     #endif
  270.     // If count is zero, then nothing to do
  271.     if (!count)
  272.         return;
  273.     XMLCh* targetPtr = toCutFrom;
  274.     XMLCh* srcPtr = toCutFrom + count;
  275.     while (*srcPtr)
  276.         *targetPtr++ = *srcPtr++;
  277.     // Cap it off at the new end
  278.     *targetPtr = 0;
  279. }
  280. unsigned int XMLString::hash(   const   char* const     tohash
  281.                                 , const unsigned int    hashModulus)
  282. {
  283.     if (!hashModulus)
  284.         ThrowXML(IllegalArgumentException, XMLExcepts::Pool_ZeroModulus);
  285.     unsigned int hashVal = 0;
  286.     if (tohash) {
  287.         const char* curCh = tohash;
  288.         while (*curCh)
  289.         {
  290.             unsigned int top = hashVal >> 24;
  291.             hashVal += (hashVal * 37) + top + (unsigned int)(*curCh);
  292.             curCh++;
  293.         }
  294.     }
  295.     // Divide by modulus
  296.     return hashVal % hashModulus;
  297. }
  298. int XMLString::indexOf(const char* const toSearch, const char ch)
  299. {
  300.     const unsigned int len = strlen(toSearch);
  301.     for (unsigned int i = 0; i < len; i++)
  302.     {
  303.         if (toSearch[i] == ch)
  304.             return i;
  305.     }
  306.     return -1;
  307. }
  308. int XMLString::indexOf( const   char* const     toSearch
  309.                         , const char            ch
  310.                         , const unsigned int    fromIndex)
  311. {
  312.     const unsigned int len = strlen(toSearch);
  313.     // Make sure the start index is within the XMLString bounds
  314. if ((int)fromIndex > len-1)
  315.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  316.     for (unsigned int i = fromIndex; i < len; i++)
  317.     {
  318.         if (toSearch[i] == ch)
  319.             return i;
  320.     }
  321.     return -1;
  322. }
  323. int XMLString::lastIndexOf(const char* const toSearch, const char ch)
  324. {
  325.     const int len = strlen(toSearch);
  326.     for (int i = len-1; i >= 0; i--)
  327.     {
  328.         if (toSearch[i] == ch)
  329.             return i;
  330.     }
  331.     return -1;
  332. }
  333. int XMLString::lastIndexOf( const   char* const     toSearch
  334.                             , const char            ch
  335.                             , const unsigned int    fromIndex)
  336. {
  337.     const int len = strlen(toSearch);
  338.     // Make sure the start index is within the XMLString bounds
  339. if ((int)fromIndex > len-1)
  340.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  341.     for (int i = (int)fromIndex; i >= 0; i--)
  342.     {
  343.         if (toSearch[i] == ch)
  344.             return i;
  345.     }
  346.     return -1;
  347. }
  348. unsigned int XMLString::replaceTokens(          XMLCh* const    errText
  349.                                         , const unsigned int    maxChars
  350.                                         , const XMLCh* const    text1
  351.                                         , const XMLCh* const    text2
  352.                                         , const XMLCh* const    text3
  353.                                         , const XMLCh* const    text4)
  354. {
  355.     //
  356.     //  We have to build the string back into the source string, so allocate
  357.     //  a temp string and copy the orignal text to it. We'll then treat the
  358.     //  incoming buffer as a target buffer. Put a janitor on it to make sure
  359.     //  it gets cleaned up.
  360.     //
  361.     XMLCh* orgText = replicate(errText);
  362.     ArrayJanitor<XMLCh> janText(orgText);
  363.     XMLCh* pszSrc = orgText;
  364.     unsigned int curOutInd = 0;
  365.     while (*pszSrc && (curOutInd < maxChars))
  366.     {
  367.         //
  368.         //  Loop until we see a { character. Until we do, just copy chars
  369.         //  from src to target, being sure not to overrun the output buffer.
  370.         //
  371.         while ((*pszSrc != chOpenCurly) && (curOutInd < maxChars))
  372.         {
  373.             if (!*pszSrc)
  374.                 break;
  375.             errText[curOutInd++] = *pszSrc++;
  376.         }
  377.         // If we did not find a curly, then we are done
  378.         if (*pszSrc != chOpenCurly)
  379.             break;
  380.         //
  381.         //  Probe this one to see if it matches our pattern of {x}. If not
  382.         //  then copy over those chars and go back to the first loop.
  383.         //
  384.         if ((*(pszSrc+1) >= chDigit_0)
  385.         &&  (*(pszSrc+1) <= chDigit_3)
  386.         &&  (*(pszSrc+2) == chCloseCurly))
  387.         {
  388.             //
  389.             //  Its one of our guys, so move the source pointer up past the
  390.             //  token we are replacing. First though get out the token number
  391.             //  character.
  392.             //
  393.             XMLCh tokCh = *(pszSrc+1);
  394.             pszSrc += 3;
  395.             // Now copy over the replacement text
  396.             const XMLCh* repText = 0;
  397.             if (tokCh == chDigit_0)
  398.                 repText = text1;
  399.             else if (tokCh == chDigit_1)
  400.                 repText = text2;
  401.             else if (tokCh == chDigit_2)
  402.                 repText = text3;
  403.             else if (tokCh == chDigit_3)
  404.                 repText = text4;
  405.             // If this one is null, copy over a null string
  406.             if (!repText)
  407.                 repText = gNullStr;
  408.             while (*repText && (curOutInd < maxChars))
  409.                 errText[curOutInd++] = *repText++;
  410.         }
  411.          else
  412.         {
  413.             // Escape the curly brace character and continue
  414.             errText[curOutInd++] = *pszSrc++;
  415.         }
  416.     }
  417.     // Copy over a null terminator
  418.     errText[curOutInd] = 0;
  419.     // And return the count of chars we output
  420.     return curOutInd;
  421. }
  422. char* XMLString::replicate(const char* const toRep)
  423. {
  424.     // If a null string, return a null string
  425.     if (!toRep)
  426.         return 0;
  427.     //
  428.     //  Get the len of the source and allocate a new buffer. Make sure to
  429.     //  account for the nul terminator.
  430.     //
  431.     const unsigned int srcLen = strlen(toRep);
  432.     char* ret = new char[srcLen+1];
  433.     // Copy over the text, adjusting for the size of a char
  434.     memcpy(ret, toRep, (srcLen+1) * sizeof(char));
  435.     return ret;
  436. }
  437. bool XMLString::startsWith(const char* const toTest, const char* const prefix)
  438. {
  439.     return (strncmp(toTest, prefix, strlen(prefix)) == 0);
  440. }
  441. bool XMLString::startsWithI(const   char* const toTest
  442.                             , const char* const prefix)
  443. {
  444.     return (strnicmp(toTest, prefix, strlen(prefix)) == 0);
  445. }
  446. unsigned int XMLString::stringLen(const char* const src)
  447. {
  448.     return strlen(src);
  449. }
  450. char* XMLString::transcode(const XMLCh* const toTranscode)
  451. {
  452.     return gTranscoder->transcode(toTranscode);
  453. }
  454. bool XMLString::transcode(  const   XMLCh* const    toTranscode
  455.                             ,       char* const     toFill
  456.                             , const unsigned int    maxChars)
  457. {
  458.     if (!gTranscoder->transcode(toTranscode, toFill, maxChars))
  459.         return false;
  460.     return true;
  461. }
  462. XMLCh* XMLString::transcode(const char* const toTranscode)
  463. {
  464.     return gTranscoder->transcode(toTranscode);
  465. }
  466. bool XMLString::transcode(  const   char* const     toTranscode
  467.                             ,       XMLCh* const    toFill
  468.                             , const unsigned int    maxChars)
  469. {
  470.     if (!gTranscoder->transcode(toTranscode, toFill, maxChars))
  471.         return false;
  472.     return true;
  473. }
  474. void XMLString::trim(char* const toTrim)
  475. {
  476.     const unsigned int len = strlen(toTrim);
  477.     unsigned int skip, scrape;
  478.     for (skip = 0; skip < len; skip++)
  479.     {
  480.         if (! isspace(toTrim[skip]))
  481.             break;
  482.     }
  483.     for (scrape = len; scrape > skip; scrape--)
  484.     {
  485.         if (! isspace(toTrim[scrape - 1] ))
  486.             break;
  487.     }
  488.     // Cap off at the scrap point
  489.     if (scrape != len)
  490.         toTrim[scrape] = 0;
  491.     if (skip)
  492.     {
  493.         // Copy the chars down
  494.         unsigned int index = 0;
  495.         while (toTrim[skip])
  496.             toTrim[index++] = toTrim[skip++];
  497.         toTrim[index] = 0;
  498.     }
  499. }
  500. void XMLString::subString(char* const targetStr, const char* const srcStr
  501.                           , const int startIndex, const int endIndex)
  502. {
  503. //if (startIndex < 0 || endIndex < 0)
  504.     //    ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_NegativeIndex);
  505. if (targetStr == 0)
  506.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf);
  507.     const int srcLen = strlen(srcStr);
  508. const int copySize = endIndex - startIndex;
  509.     // Make sure the start index is within the XMLString bounds
  510. if (startIndex > srcLen-1 || endIndex > srcLen )
  511.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  512. for (int i= startIndex; i < endIndex; i++) {
  513. targetStr[i-startIndex] = srcStr[i];
  514. }
  515. targetStr[copySize] = 0;
  516. }
  517. /**
  518.   * isValidNCName
  519.   *
  520.   *    NCName::= (Letter | '_') (NCNameChar)*
  521.   *    NCNameChar ::= Letter | Digit | '.' | '-' | '_'
  522.   *                   | CombiningChar | Extender
  523.   */
  524. bool XMLString::isValidNCName(const XMLCh* const name) {
  525.     if (XMLString::stringLen(name) == 0
  526.         || XMLString::indexOf(name, chColon) != -1) {
  527.         return false;
  528.     }
  529.     const XMLCh* tempName = name;
  530.     XMLCh firstChar = *tempName++;
  531.     if (!XMLReader::isXMLLetter(firstChar) && firstChar != chUnderscore) {
  532.         return false;
  533.     }
  534.     while(*tempName) {
  535.         if (*tempName == chColon || !XMLReader::isNameChar(*tempName++)) {
  536.             return false;
  537.         }
  538.     }
  539.     return true;
  540. }
  541. /**
  542.   * isValidName
  543.   *
  544.   *    Name::= (Letter | '_' | ':') (NameChar)*
  545.   *    NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
  546.   *                 | CombiningChar | Extender
  547.   */
  548. bool XMLString::isValidName(const XMLCh* const name) {
  549.     if (!name ||
  550.         (XMLString::stringLen(name) == 0))
  551.         return false;
  552.     const XMLCh* tempName = name;
  553.     XMLCh firstChar = *tempName++;
  554.     if (!XMLReader::isXMLLetter(firstChar) &&
  555.         (firstChar != chUnderscore)        &&
  556.         (firstChar != chColon)              )
  557.         return false;
  558.     while(*tempName)
  559.         if (!XMLReader::isNameChar(*tempName++))
  560.             return false;
  561.     return true;
  562. }
  563. /**
  564.   * isValidEncName
  565.   *
  566.   * [80] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
  567.   *
  568.   */
  569. bool XMLString::isValidEncName(const XMLCh* const name)
  570. {
  571.     if ( ( !name) ||
  572.          ( XMLString::stringLen(name) == 0 ))
  573.         return false;
  574.     const XMLCh* tempName = name;
  575.     XMLCh firstChar = *tempName++;
  576.     if (!isAlpha(firstChar))
  577.         return false;
  578.     while(*tempName)
  579.     {
  580.         if (( !isAlpha(*tempName))       &&
  581.             ( !isDigit(*tempName))       &&
  582.             ( *tempName != chPeriod)     &&
  583.             ( *tempName != chUnderscore) &&
  584.             ( *tempName != chDash)        )
  585.             return false;
  586.         tempName++;
  587.     }
  588.     return true;
  589. }
  590. /**
  591.   * isValidQName
  592.   *
  593.   * [6]  QName ::=  (Prefix ':')? LocalPart
  594.   * [7]  Prefix ::=  NCName
  595.   * [8]  LocalPart ::=  NCName
  596.   *
  597.   */
  598. bool XMLString::isValidQName(const XMLCh* const name)
  599. {
  600.     if (!name)
  601.         return false;
  602.     int strLen = XMLString::stringLen(name);
  603.     if (strLen == 0)
  604.         return false;
  605.     int colonPos = XMLString::indexOf(name, chColon);
  606.     if ((colonPos == 0) ||         // ":abcd"
  607.         (colonPos == strLen-1))    // "abcd:"
  608.         return false;
  609.     //
  610.     // prefix
  611.     //
  612.     if (colonPos != -1)
  613.     {
  614.         XMLCh *prefix = new XMLCh[colonPos+1];
  615.         XMLString::subString(prefix, name, 0, colonPos);
  616.         ArrayJanitor<XMLCh> janName(prefix);
  617.         if (XMLString::isValidNCName(prefix)==false)
  618.             return false;
  619.     }
  620.     //
  621.     // LocalPart
  622.     //
  623.     return XMLString::isValidNCName(name+colonPos+1);
  624. }
  625. bool XMLString::isAlpha(XMLCh const theChar)
  626. {
  627.     if ((( theChar >= chLatin_a ) && ( theChar <= chLatin_z )) ||
  628.         (( theChar >= chLatin_A ) && ( theChar <= chLatin_Z )) )
  629.         return true;
  630.     return false;
  631. }
  632. bool XMLString::isDigit(XMLCh const theChar)
  633. {
  634.     if (( theChar >= chDigit_0 ) && ( theChar <= chDigit_9 ))
  635.         return true;
  636.     return false;
  637. }
  638. bool XMLString::isAlphaNum(XMLCh const theChar)
  639. {
  640.     return (isAlpha(theChar) || isDigit(theChar));
  641. }
  642. bool XMLString::isHex(XMLCh const theChar)
  643. {
  644. return (isDigit(theChar) ||
  645. (theChar >= chLatin_a && theChar <= chLatin_f) ||
  646. (theChar >= chLatin_A && theChar <= chLatin_F));
  647. }
  648. bool XMLString::isAllWhiteSpace(const XMLCh* const toCheck)
  649. {
  650.     if ( !toCheck )
  651.         return true;
  652.     const XMLCh* startPtr = toCheck;
  653.     while (*startPtr)
  654.     {
  655.         if (!XMLPlatformUtils::fgTransService->isSpace(*startPtr))
  656.             return false;
  657.         startPtr++;
  658.     }
  659.     return true;
  660. }
  661. // ---------------------------------------------------------------------------
  662. //  Wide char versions of most of the string methods
  663. // ---------------------------------------------------------------------------
  664. void XMLString::binToText(  const   unsigned long   toFormat
  665.                             ,       XMLCh* const    toFill
  666.                             , const unsigned int    maxChars
  667.                             , const unsigned int    radix)
  668. {
  669.     static const XMLCh digitList[16] =
  670.     {
  671.             chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, chDigit_5
  672.         ,   chDigit_6, chDigit_7, chDigit_8, chDigit_9, chLatin_A, chLatin_B
  673.         ,   chLatin_C, chLatin_D, chLatin_e, chLatin_F
  674.     };
  675.     if (!maxChars)
  676.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf);
  677.     // Handle special case
  678.     if (!toFormat)
  679.     {
  680.         toFill[0] = chDigit_0;
  681.         toFill[1] = chNull;
  682.         return;
  683.     }
  684.     // This is used to fill the temp buffer
  685.     unsigned int tmpIndex = 0;
  686.     // A copy of the conversion value that we can modify
  687.     unsigned int tmpVal = toFormat;
  688.     //
  689.     //  Convert into a temp buffer that we know is large enough. This avoids
  690.     //  having to check for overflow in the inner loops, and we have to flip
  691.     //  the resulting sring anyway.
  692.     //
  693.     XMLCh tmpBuf[128];
  694.     //
  695.     //  For each radix, do the optimal thing. For bin and hex, we can special
  696.     //  case them and do shift and mask oriented stuff. For oct and decimal
  697.     //  there isn't much to do but bull through it with divides.
  698.     //
  699.     if (radix == 2)
  700.     {
  701.         while (tmpVal)
  702.         {
  703.             if (tmpVal & 0x1UL)
  704.                 tmpBuf[tmpIndex++] = chDigit_1;
  705.             else
  706.                 tmpBuf[tmpIndex++] = chDigit_0;
  707.             tmpVal >>= 1;
  708.         }
  709.     }
  710.      else if (radix == 16)
  711.     {
  712.         while (tmpVal)
  713.         {
  714.             const unsigned int charInd = (tmpVal & 0xFUL);
  715.             tmpBuf[tmpIndex++] = digitList[charInd];
  716.             tmpVal >>= 4;
  717.         }
  718.     }
  719.      else if ((radix == 8) || (radix == 10))
  720.     {
  721.         while (tmpVal)
  722.         {
  723.             const unsigned int charInd = (tmpVal % radix);
  724.             tmpBuf[tmpIndex++] = digitList[charInd];
  725.             tmpVal /= radix;
  726.         }
  727.     }
  728.      else
  729.     {
  730.         ThrowXML(RuntimeException, XMLExcepts::Str_UnknownRadix);
  731.     }
  732.     // See if have enough room in the caller's buffer
  733.     if (tmpIndex > maxChars)
  734.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall);
  735.     // Reverse the tmp buffer into the caller's buffer
  736.     unsigned int outIndex = 0;
  737.     for (; tmpIndex > 0; tmpIndex--)
  738.         toFill[outIndex++] = tmpBuf[tmpIndex-1];
  739.     // And cap off the caller's buffer
  740.     toFill[outIndex] = chNull;
  741. }
  742. void XMLString::binToText(  const   unsigned int    toFormat
  743.                             ,       XMLCh* const    toFill
  744.                             , const unsigned int    maxChars
  745.                             , const unsigned int    radix)
  746. {
  747.     // Just call the unsigned long version
  748.     binToText((unsigned long)toFormat, toFill, maxChars, radix);
  749. }
  750. void XMLString::binToText(  const   long            toFormat
  751.                             ,       XMLCh* const    toFill
  752.                             , const unsigned int    maxChars
  753.                             , const unsigned int    radix)
  754. {
  755.     //
  756.     //  If its negative, then put a negative sign into the output and flip
  757.     //  the sign of the local temp value.
  758.     //
  759.     unsigned int startInd = 0;
  760.     unsigned long actualVal;
  761.     if (toFormat < 0)
  762.     {
  763.         toFill[0] = chDash;
  764.         startInd++;
  765.         actualVal = (unsigned long)(toFormat * -1);
  766.     }
  767.      else
  768.     {
  769.         actualVal = (unsigned long)(toFormat);
  770.     }
  771.     // And now call the unsigned long version
  772.     binToText(actualVal, &toFill[startInd], maxChars, radix);
  773. }
  774. void XMLString::binToText(  const   int             toFormat
  775.                             ,       XMLCh* const    toFill
  776.                             , const unsigned int    maxChars
  777.                             , const unsigned int    radix)
  778. {
  779.     //
  780.     //  If its negative, then put a negative sign into the output and flip
  781.     //  the sign of the local temp value.
  782.     //
  783.     unsigned int startInd = 0;
  784.     unsigned long actualVal;
  785.     if (toFormat < 0)
  786.     {
  787.         toFill[0] = chDash;
  788.         startInd++;
  789.         actualVal = (unsigned long)(toFormat * -1);
  790.     }
  791.      else
  792.     {
  793.         actualVal = (unsigned long)(toFormat);
  794.     }
  795.     // And now call the unsigned long version
  796.     binToText(actualVal, &toFill[startInd], maxChars, radix);
  797. }
  798. void XMLString::catString(XMLCh* const target, const XMLCh* const src)
  799. {
  800.     // Get the starting point for the cat on the target XMLString
  801.     unsigned int index = stringLen(target);
  802.     // While the source is not zero, add them to target and bump
  803.     const XMLCh* pszTmp = src;
  804.     while (*pszTmp)
  805.         target[index++] = *pszTmp++;
  806.     // Cap off the target where we ended
  807.     target[index] = chNull;
  808. }
  809. int XMLString::compareIString(  const   XMLCh* const    str1
  810.                                 , const XMLCh* const    str2)
  811. {
  812.     // Refer this one to the transcoding service
  813.     return XMLPlatformUtils::fgTransService->compareIString(str1, str2);
  814. }
  815. int XMLString::compareNString(  const   XMLCh* const    str1
  816.                                 , const XMLCh* const    str2
  817.                                 , const unsigned int    maxChars)
  818. {
  819.     const XMLCh* psz1 = str1;
  820.     const XMLCh* psz2 = str2;
  821.     unsigned int curCount = 0;
  822.     while (true)
  823.     {
  824.         // If an inequality, then return difference
  825.         if (*psz1 != *psz2)
  826.             return int(*psz1) - int(*psz2);
  827.         // If either ended, then both ended, so equal
  828.         if (!*psz1 || !*psz2)
  829.             break;
  830.         // Move upwards to next chars
  831.         psz1++;
  832.         psz2++;
  833.         //
  834.         //  Bump the count of chars done. If it equals the max then we are
  835.         //  equal for the requested count, so break out and return equal.
  836.         //
  837.         curCount++;
  838.         if (curCount == maxChars)
  839.             break;
  840.     }
  841.     return 0;
  842. }
  843. int XMLString::compareNIString( const   XMLCh* const    str1
  844.                                 , const XMLCh* const    str2
  845.                                 , const unsigned int    maxChars)
  846. {
  847.     // Refer this oneto the transcoding service
  848.     return XMLPlatformUtils::fgTransService->compareNIString(str1, str2, maxChars);
  849. }
  850. int XMLString::compareString(   const   XMLCh* const    str1
  851.                                 , const XMLCh* const    str2)
  852. {
  853.     const XMLCh* psz1 = str1;
  854.     const XMLCh* psz2 = str2;
  855.     if (psz1 == 0 || psz2 == 0) {
  856.         if (psz1 == 0) {
  857.             return 0 - XMLString::stringLen(psz2);
  858.         }
  859. else if (psz2 == 0) {
  860.             return XMLString::stringLen(psz1);
  861.         }
  862.     }
  863.     while (true)
  864.     {
  865.         // If an inequality, then return the difference
  866.         if (*psz1 != *psz2)
  867.             return int(*psz1) - int(*psz2);
  868.         // If either has ended, then they both ended, so equal
  869.         if (!*psz1 || !*psz2)
  870.             break;
  871.         // Move upwards for the next round
  872.         psz1++;
  873.         psz2++;
  874.     }
  875.     return 0;
  876. }
  877. bool XMLString::regionMatches(const   XMLCh* const str1
  878.   , const int offset1
  879.   , const XMLCh* const str2
  880.   , const int offset2
  881.   , const unsigned int charCount)
  882. {
  883. if (!validateRegion(str1, offset1,str2, offset2, charCount))
  884. return false;
  885. if (compareNString(str1+offset1, str2+offset2, charCount) != 0)
  886. return false;
  887. return true;
  888. }
  889. bool XMLString::regionIMatches(const   XMLCh* const str1
  890.      , const int offset1
  891.    , const XMLCh* const str2
  892.    , const int offset2
  893.    , const unsigned int charCount)
  894. {
  895. if (!validateRegion(str1, offset1,str2, offset2, charCount))
  896. return false;
  897. if (compareNIString(str1+offset1, str2+offset2, charCount) != 0)
  898. return false;
  899. return true;
  900. }
  901. void XMLString::copyString(XMLCh* const target, const XMLCh* const src)
  902. {
  903.     if (!src)
  904.     {
  905.         *target = 0;
  906.         return;
  907.     }
  908.     XMLCh* pszOut = target;
  909.     const XMLCh* pszIn = src;
  910.     while (*pszIn)
  911.         *pszOut++ = *pszIn++;
  912.     // Capp off the target where we ended
  913.     *pszOut = 0;
  914. }
  915. bool XMLString::copyNString(        XMLCh* const    target
  916.                             , const XMLCh* const    src
  917.                             , const unsigned int    maxChars)
  918. {
  919.     XMLCh* outPtr = target;
  920.     const XMLCh* srcPtr = src;
  921.     const XMLCh* endPtr = target + maxChars - 1;
  922.     while (*srcPtr && (outPtr <= endPtr))
  923.         *outPtr++ = *srcPtr++;
  924.     // Cap it off here
  925.     *outPtr = 0;
  926.     // Return whether we copied it all or hit the max
  927.     return (*srcPtr == 0);
  928. }
  929. unsigned int XMLString::hash(   const   XMLCh* const    tohash
  930.                                 , const unsigned int    hashModulus)
  931. {
  932.     if (!hashModulus)
  933.         ThrowXML(IllegalArgumentException, XMLExcepts::Pool_ZeroModulus);
  934.     unsigned int hashVal = 0;
  935.     if (tohash) {
  936.         const XMLCh* curCh = tohash;
  937.         while (*curCh)
  938.         {
  939.             unsigned int top = hashVal >> 24;
  940.             hashVal += (hashVal * 37) + top + (unsigned int)(*curCh);
  941.             curCh++;
  942.         }
  943.     }
  944.     // Divide by modulus
  945.     return hashVal % hashModulus;
  946. }
  947. const XMLCh* XMLString::findAny(const   XMLCh* const    toSearch
  948.                                 , const XMLCh* const    searchList)
  949. {
  950.     const XMLCh* srcPtr = toSearch;
  951.     while (*srcPtr)
  952.     {
  953.         const XMLCh* listPtr = searchList;
  954.         const XMLCh  curCh = *srcPtr;
  955.         while (*listPtr)
  956.         {
  957.             if (curCh == *listPtr++)
  958.                 return srcPtr;
  959.         }
  960.         srcPtr++;
  961.     }
  962.     return 0;
  963. }
  964. XMLCh* XMLString::findAny(          XMLCh* const    toSearch
  965.                             , const XMLCh* const    searchList)
  966. {
  967.     XMLCh* srcPtr = toSearch;
  968.     while (*srcPtr)
  969.     {
  970.         const XMLCh* listPtr = searchList;
  971.         const XMLCh  curCh = *srcPtr;
  972.         while (*listPtr)
  973.         {
  974.             if (curCh == *listPtr++)
  975.                 return srcPtr;
  976.         }
  977.         srcPtr++;
  978.     }
  979.     return 0;
  980. }
  981. int XMLString::patternMatch(        XMLCh* const    toSearch
  982.                             , const XMLCh* const    pattern)
  983. {
  984.     if (!toSearch || !pattern )
  985.         return -1;
  986.     XMLCh* srcPtr = toSearch;
  987.     const int patnLen = XMLString::stringLen(pattern);
  988.     int  patnIndex = 0;
  989.     while (*srcPtr)
  990.     {
  991.         if (*srcPtr++ != pattern[patnIndex++])
  992.         {
  993.             patnIndex = 0;
  994.         }
  995.         else
  996.         {
  997.             if (patnIndex == patnLen)
  998.                 // full pattern match found
  999.                 return (srcPtr - patnLen - toSearch);
  1000.         }
  1001.     }
  1002.     return -1;
  1003. }
  1004. unsigned int XMLString::hashN(  const   XMLCh* const    tohash
  1005.                                 , const unsigned int    n
  1006.                                 , const unsigned int    hashModulus)
  1007. {
  1008.     if (!hashModulus)
  1009.         ThrowXML(IllegalArgumentException, XMLExcepts::Pool_ZeroModulus);
  1010.     unsigned int hashVal = 0;
  1011.     if (tohash) {
  1012.         const XMLCh* curCh = tohash;
  1013.         int i = n;
  1014.         while (i--)
  1015.         {
  1016.             unsigned int top = hashVal >> 24;
  1017.             hashVal += (hashVal * 37) + top + (unsigned int)(*curCh);
  1018.             curCh++;
  1019.         }
  1020.     }
  1021.     // Divide by modulus
  1022.     return hashVal % hashModulus;
  1023. }
  1024. int XMLString::indexOf(const XMLCh* const toSearch, const XMLCh ch)
  1025. {
  1026.     const unsigned int len = stringLen(toSearch);
  1027.     for (unsigned int i = 0; i < len; i++)
  1028.     {
  1029.         if (toSearch[i] == ch)
  1030.             return i;
  1031.     }
  1032.     return -1;
  1033. }
  1034. int XMLString::indexOf( const   XMLCh* const    toSearch
  1035.                         , const XMLCh           ch
  1036.                         , const unsigned int    fromIndex)
  1037. {
  1038.     const int len = stringLen(toSearch);
  1039.     // Make sure the start index is within the XMLString bounds
  1040. if ((int)fromIndex > len-1)
  1041.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  1042.     for (int i = (int)fromIndex; i < len; i++)
  1043.     {
  1044.         if (toSearch[i] == ch)
  1045.             return i;
  1046.     }
  1047.     return -1;
  1048. }
  1049. int XMLString::lastIndexOf(const XMLCh* const toSearch, const XMLCh ch)
  1050. {
  1051.     const int len = stringLen(toSearch);
  1052.     for (int i = len-1; i >= 0; i--)
  1053.     {
  1054.         if (toSearch[i] == ch)
  1055.             return i;
  1056.     }
  1057.     return -1;
  1058. }
  1059. int XMLString::lastIndexOf( const   XMLCh* const    toSearch
  1060.                             , const XMLCh           ch
  1061.                             , const unsigned int    fromIndex)
  1062. {
  1063.     const int len = stringLen(toSearch);
  1064. if ((int)fromIndex > len-1)
  1065.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  1066.     for (int i = (int)fromIndex; i >= 0; i--)
  1067.     {
  1068.         if (toSearch[i] == ch)
  1069.             return i;
  1070.     }
  1071.     return -1;
  1072. }
  1073. XMLCh*
  1074. XMLString::makeUName(const XMLCh* const pszURI, const XMLCh* const pszName)
  1075. {
  1076.     //
  1077.     //  If there is a URI, then format out the full name in the {uri}name
  1078.     //  form. Otherwise, just set it to the same thing as the base name.
  1079.     //
  1080.     XMLCh* pszRet = 0;
  1081.     const unsigned int uriLen = stringLen(pszURI);
  1082.     if (uriLen)
  1083.     {
  1084.         pszRet = new XMLCh[uriLen + stringLen(pszName) + 3];
  1085.         XMLCh szTmp[2];
  1086.         szTmp[1] = 0;
  1087.         szTmp[0] = chOpenCurly;
  1088.         copyString(pszRet, szTmp);
  1089.         catString(pszRet, pszURI);
  1090.         szTmp[0] = chCloseCurly;
  1091.         catString(pszRet, szTmp);
  1092.         catString(pszRet, pszName);
  1093.     }
  1094.      else
  1095.     {
  1096.         pszRet = replicate(pszName);
  1097.     }
  1098.     return pszRet;
  1099. }
  1100. bool XMLString::textToBin(const XMLCh* const toConvert, unsigned int& toFill)
  1101. {
  1102.     toFill = 0;
  1103.     // If no string, then its a failure
  1104.     if (!toConvert)
  1105.         return false;
  1106.     if (!*toConvert)
  1107.         return false;
  1108.     // Scan past any whitespace. If we hit the end, then return failure
  1109.     const XMLCh* startPtr = toConvert;
  1110.     while (XMLPlatformUtils::fgTransService->isSpace(*startPtr))
  1111.         startPtr++;
  1112.     if (!*startPtr)
  1113.         return false;
  1114.     // Start at the end and work back through any whitespace
  1115.     const XMLCh* endPtr = toConvert + stringLen(toConvert);
  1116.     while (XMLPlatformUtils::fgTransService->isSpace(*(endPtr - 1)))
  1117.         endPtr--;
  1118.     //
  1119.     //  Work through what remains and convert each char to a digit. Any
  1120.     //  space or non-digit here is now an error.
  1121.     //
  1122.     unsigned long tmpVal = 0;
  1123.     while (startPtr < endPtr)
  1124.     {
  1125.         // If not valid decimal digit, then an error
  1126.         if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
  1127.             return false;
  1128.         const unsigned int nextVal = (unsigned int)(*startPtr - chDigit_0);
  1129.         tmpVal = (tmpVal * 10) + nextVal;
  1130.         startPtr++;
  1131.     }
  1132.     // Make sure it didn't overflow
  1133.     if (tmpVal > ~0UL)
  1134.         ThrowXML(RuntimeException, XMLExcepts::Str_ConvertOverflow);
  1135.     toFill = (unsigned int)tmpVal;
  1136.     return true;
  1137. }
  1138. int XMLString::parseInt(const XMLCh* const toConvert)
  1139. {
  1140.     // If no string, then its a failure
  1141.     if ((!toConvert) ||
  1142.         (!*toConvert))
  1143.         ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_null_ptr);
  1144.     // Scan past any whitespace. If we hit the end, then return failure
  1145.     const XMLCh* startPtr = toConvert;
  1146.     while (XMLPlatformUtils::fgTransService->isSpace(*startPtr))
  1147.         startPtr++;
  1148.     if (!*startPtr)
  1149.         ThrowXML(NumberFormatException, XMLExcepts::CM_UnaryOpHadBinType);
  1150.         //ThrowXML(NumberFormatException, XMLExcepts::XMLINT_Invalid);
  1151.     // Start at the end and work back through any whitespace
  1152.     const XMLCh* endPtr = toConvert + XMLString::stringLen(toConvert);
  1153.     while (XMLPlatformUtils::fgTransService->isSpace(*(endPtr - 1)))
  1154.         endPtr--;
  1155.     //
  1156.     //  Work through what remains and convert each char to a digit.
  1157.     //
  1158.     int signValue = 1;
  1159.     //
  1160.     // '+' or '-' is allowed only at the first position
  1161.     //
  1162.     if (*startPtr == chDash)
  1163.     {
  1164.         signValue = -1;
  1165.         startPtr++;  // skip the '-'
  1166.     }
  1167.     else if (*startPtr == chPlus)
  1168.         startPtr++;  // skip the '+'
  1169.     unsigned long tmpVal = 0;
  1170.     while (startPtr < endPtr)
  1171.     {
  1172.         // If not valid decimal digit, then an error
  1173.         if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
  1174.             ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars);
  1175.         const unsigned int nextVal = (unsigned int)(*startPtr - chDigit_0);
  1176.         tmpVal = (tmpVal * 10) + nextVal;
  1177.         startPtr++;
  1178.     }
  1179.     // Make sure it didn't overflow
  1180.     if (tmpVal > ~0UL)
  1181.         ThrowXML(NumberFormatException, XMLExcepts::Str_ConvertOverflow);
  1182.     return (int) signValue*tmpVal;
  1183. }
  1184. void XMLString::trim(XMLCh* const toTrim)
  1185. {
  1186.     const unsigned int len = stringLen(toTrim);
  1187.     unsigned int skip, scrape;
  1188.     for (skip = 0; skip < len; skip++)
  1189.     {
  1190.         if (!XMLPlatformUtils::fgTransService->isSpace(toTrim[skip]))
  1191.             break;
  1192.     }
  1193.     for (scrape = len; scrape > skip; scrape--)
  1194.     {
  1195.         if (!XMLPlatformUtils::fgTransService->isSpace(toTrim[scrape - 1]))
  1196.             break;
  1197.     }
  1198.     // Cap off at the scrap point
  1199.     if (scrape != len)
  1200.         toTrim[scrape] = 0;
  1201.     if (skip)
  1202.     {
  1203.         // Copy the chars down
  1204.         unsigned int index = 0;
  1205.         while (toTrim[skip])
  1206.             toTrim[index++] = toTrim[skip++];
  1207.         toTrim[index] = 0;
  1208.     }
  1209. }
  1210. void XMLString::upperCase(XMLCh* const toUpperCase)
  1211. {
  1212.     // Refer this one to the transcoding service
  1213.     XMLPlatformUtils::fgTransService->upperCase(toUpperCase);
  1214. }
  1215. void XMLString::lowerCase(XMLCh* const toLowerCase)
  1216. {
  1217.     // Refer this one to the transcoding service
  1218.     //XMLPlatformUtils::fgTransService->lowerCase(toLowerCase);
  1219. }
  1220. void XMLString::subString(XMLCh* const targetStr, const XMLCh* const srcStr
  1221.                           , const int startIndex, const int endIndex)
  1222. {
  1223. //if (startIndex < 0 || endIndex < 0)
  1224.     //    ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_NegativeIndex);
  1225. if (targetStr == 0)
  1226.         ThrowXML(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf);
  1227.     const int srcLen = stringLen(srcStr);
  1228. const int copySize = endIndex - startIndex;
  1229.     // Make sure the start index is within the XMLString bounds
  1230. if (startIndex > srcLen-1 || endIndex > srcLen )
  1231.         ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd);
  1232. for (int i= startIndex; i < endIndex; i++) {
  1233. targetStr[i-startIndex] = srcStr[i];
  1234. }
  1235. targetStr[copySize] = 0;
  1236. }
  1237. RefVectorOf<XMLCh>* XMLString::tokenizeString(const XMLCh* const tokenizeSrc)
  1238. {
  1239.     XMLCh* orgText = replicate(tokenizeSrc);
  1240.     ArrayJanitor<XMLCh> janText(orgText);
  1241.     XMLCh* tokenizeStr = orgText;
  1242.     RefVectorOf<XMLCh>* tokenStack = new RefVectorOf<XMLCh>(16, true);
  1243.     unsigned int len = stringLen(tokenizeStr);
  1244.     unsigned int skip;
  1245.     unsigned int index = 0;
  1246.     while (index != len) {
  1247.         // find the first non-space character
  1248.         for (skip = index; skip < len; skip++)
  1249.         {
  1250.             if (!XMLPlatformUtils::fgTransService->isSpace(tokenizeStr[skip]))
  1251.                 break;
  1252.         }
  1253.         index = skip;
  1254.         // find the delimiter (space character)
  1255.         for (; skip < len; skip++)
  1256.         {
  1257.             if (XMLPlatformUtils::fgTransService->isSpace(tokenizeStr[skip]))
  1258.                 break;
  1259.         }
  1260.         // we reached the end of the string
  1261.         if (skip == index)
  1262.             break;
  1263.         // these tokens are adopted in the RefVector and will be deleted
  1264.         // when the vector is deleted by the caller
  1265.         XMLCh* token = new XMLCh[skip+1-index];
  1266.         XMLString::subString(token, tokenizeStr, index, skip);
  1267.         tokenStack->addElement(token);
  1268.         index = skip;
  1269.     }
  1270.     return tokenStack;
  1271. }
  1272. //
  1273. //  This method is called when we get a notation or enumeration type attribute
  1274. //  to validate. We have to confirm that the passed value to find is one of
  1275. //  the values in the passed list. The list is a space separated string of
  1276. //  values to match against.
  1277. //
  1278. bool XMLString::isInList(const XMLCh* const toFind, const XMLCh* const enumList)
  1279. {
  1280.     //
  1281.     //  We loop through the values in the list via this outer loop. We end
  1282.     //  when we hit the end of the enum list or get a match.
  1283.     //
  1284.     const XMLCh* listPtr = enumList;
  1285.     const unsigned int findLen = XMLString::stringLen(toFind);
  1286.     while (*listPtr)
  1287.     {
  1288.         unsigned int testInd;
  1289.         for (testInd = 0; testInd < findLen; testInd++)
  1290.         {
  1291.             //
  1292.             //  If they don't match, then reset and try again. Note that
  1293.             //  hitting the end of the current item will cause a mismatch
  1294.             //  because there can be no spaces in the toFind string.
  1295.             //
  1296.             if (listPtr[testInd] != toFind[testInd])
  1297.                 break;
  1298.         }
  1299.         //
  1300.         //  If we went the distance, see if we matched. If we did, the current
  1301.         //  list character has to be null or space.
  1302.         //
  1303.         if (testInd == findLen)
  1304.         {
  1305.             if ((listPtr[testInd] == chSpace) || !listPtr[testInd])
  1306.                 return true;
  1307.         }
  1308.         // Run the list pointer up to the next substring
  1309.         while ((*listPtr != chSpace) && *listPtr)
  1310.             listPtr++;
  1311.         // If we hit the end, then we failed
  1312.         if (!*listPtr)
  1313.             return false;
  1314.         // Else move past the space and try again
  1315.         listPtr++;
  1316.     }
  1317.     // We never found it
  1318.     return false;
  1319. }
  1320. //
  1321. // a string is whitespace:replaced, is having no
  1322. //    #xD  Carriage Return
  1323. //    #xA  Line Feed
  1324. //    #x9  TAB
  1325. //
  1326. bool XMLString::isWSReplaced(const XMLCh* const toCheck)
  1327. {
  1328.     // If no string, then its a OK
  1329.     if (( !toCheck ) || ( !*toCheck ))
  1330.         true;
  1331.     const XMLCh* startPtr = toCheck;
  1332.     while ( *startPtr )
  1333.     {
  1334.         if ( ( *startPtr == chCR) ||
  1335.              ( *startPtr == chLF) ||
  1336.              ( *startPtr == chHTab))
  1337.         return false;
  1338.         startPtr++;
  1339.     }
  1340.     return true;
  1341. }
  1342. //
  1343. //   to replace characters listed below to #x20
  1344. //    #xD  Carriage Return
  1345. //    #xA  Line Feed
  1346. //    #x9  TAB
  1347. //
  1348. void XMLString::replaceWS(XMLCh* const toConvert)
  1349. {
  1350.     // If no string, then its a failure
  1351.     if (( !toConvert ) || ( !*toConvert ))
  1352.         return;
  1353.     int strLen = XMLString::stringLen(toConvert);
  1354.     XMLCh* retBuf = new XMLCh[strLen+1];
  1355.     XMLCh* retPtr = &(retBuf[0]);
  1356.     XMLCh* startPtr = toConvert;
  1357.     while ( *startPtr )
  1358.     {
  1359.         if ( ( *startPtr == chCR) ||
  1360.              ( *startPtr == chLF) ||
  1361.              ( *startPtr == chHTab))
  1362.             *retPtr = chSpace;
  1363.         else
  1364.             *retPtr = *startPtr;
  1365.         retPtr++;
  1366.         startPtr++;
  1367.     }
  1368.     retBuf[strLen] = chNull;
  1369.     XMLString::moveChars(toConvert, retBuf, strLen);
  1370.     delete[] retBuf;
  1371.     return;
  1372. }
  1373. //
  1374. // a string is whitespace:collapsed, is whitespace::replaced
  1375. // and no
  1376. //    leading space (#x20)
  1377. //    trailing space
  1378. //    no contiguous sequences of spaces
  1379. //
  1380. bool XMLString::isWSCollapsed(const XMLCh* const toCheck)
  1381. {
  1382.     // shall be whitespace::replaced first
  1383.     if ( !isWSReplaced(toCheck) )
  1384.         return false;
  1385.     // no leading or trailing space
  1386.     if ((*toCheck == chSpace) ||
  1387.         (toCheck[XMLString::stringLen(toCheck)-1] == chSpace))
  1388.         return false;
  1389.     const XMLCh* startPtr = toCheck;
  1390.     XMLCh theChar;
  1391.     bool  inSpace = false;
  1392.     while ( (theChar = *startPtr) != 0 )
  1393.     {
  1394.         if ( theChar == chSpace)
  1395.         {
  1396.             if (inSpace)
  1397.                 return false;
  1398.             else
  1399.                 inSpace = true;
  1400.         }
  1401.         else
  1402.             inSpace = false;
  1403.         startPtr++;
  1404.     }
  1405.     return true;
  1406. }
  1407. //
  1408. // no leading and/or trailing spaces
  1409. // no continuous sequences of spaces
  1410. //
  1411. void XMLString::collapseWS(XMLCh* const toConvert)
  1412. {
  1413.     // If no string, then its a failure
  1414.     if (( !toConvert ) || ( !*toConvert ))
  1415.         return;
  1416.     // replace whitespace first
  1417.     replaceWS(toConvert);
  1418.     // remove leading spaces
  1419.     const XMLCh* startPtr = toConvert;
  1420.     while ( *startPtr == chSpace )
  1421.         startPtr++;
  1422.     if (!*startPtr)
  1423.         return;
  1424.     // remove trailing spaces
  1425.     const XMLCh* endPtr = toConvert + stringLen(toConvert);
  1426.     while (*(endPtr - 1) == chSpace)
  1427.         endPtr--;
  1428.     //
  1429.     //  Work through what remains and chop continuous spaces
  1430.     //
  1431.     XMLCh* retBuf = new XMLCh[endPtr - startPtr + 1];
  1432.     XMLCh* retPtr = &(retBuf[0]);
  1433.     bool  inSpace = false;
  1434.     while (startPtr < endPtr)
  1435.     {
  1436.         if ( *startPtr == chSpace)
  1437.         {
  1438.             if (inSpace)
  1439.             {
  1440.                 //discard it;
  1441.             }
  1442.             else
  1443.             {
  1444.                 inSpace = true;
  1445.                 *retPtr = chSpace;  //copy the first chSpace
  1446.                 retPtr++;
  1447.             }
  1448.         }
  1449.         else
  1450.         {
  1451.             inSpace = false;
  1452.             *retPtr = *startPtr;
  1453.             retPtr++;
  1454.         }
  1455.         startPtr++;
  1456.     }
  1457.     *retPtr = chNull;
  1458.     XMLString::moveChars(toConvert, retBuf, stringLen(retBuf)+1); //copy the last chNull as well
  1459.     delete[] retBuf;
  1460.     return;
  1461. }
  1462. // ---------------------------------------------------------------------------
  1463. //  XMLString: Private static methods
  1464. // ---------------------------------------------------------------------------
  1465. void XMLString::initString(XMLLCPTranscoder* const defToUse)
  1466. {
  1467.     // Store away the default transcoder that we are to use
  1468.     gTranscoder = defToUse;
  1469. }
  1470. void XMLString::termString()
  1471. {
  1472.     // Just clean up our local code page transcoder
  1473.     delete gTranscoder;
  1474.     gTranscoder = 0;
  1475. }