source: icXML/icXML-devel/src/icxercesc/util/XMLString.cpp

Last change on this file was 3564, checked in by cameron, 6 years ago

Changes to icxercesc files

File size: 47.9 KB
RevLine 
[2720]1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: XMLString.cpp 901107 2010-01-20 08:45:02Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#if HAVE_CONFIG_H
27#       include <config.h>
28#endif
29
30#if !HAVE_STRICMP
31#       include <stricmp.h>
32#endif
33#if !HAVE_STRNICMP
34#       include <strnicmp.h>
35#endif
36
37#include <string.h>
38#include <ctype.h>
39#include <stdlib.h>
40#include <errno.h>
41#include <assert.h>
42#include <iostream>
43
[2721]44#include <icxercesc/util/XMLString.hpp>
[2720]45#include <xercesc/util/ArrayIndexOutOfBoundsException.hpp>
46#include <xercesc/util/IllegalArgumentException.hpp>
47#include <xercesc/util/NumberFormatException.hpp>
48#include <xercesc/util/OutOfMemoryException.hpp>
49#include <xercesc/util/RuntimeException.hpp>
50#include <xercesc/util/TranscodingException.hpp>
51#include <xercesc/util/Janitor.hpp>
[2721]52#include <icxercesc/util/PlatformUtils.hpp>
[2720]53#include <xercesc/util/RefArrayVectorOf.hpp>
[2721]54#include <icxercesc/util/TransService.hpp>
[2720]55#include <xercesc/util/XMLUniDefs.hpp>
56#include <xercesc/util/XMLUni.hpp>
57#include <xercesc/util/XMLUri.hpp>
58#include <xercesc/util/XMLURL.hpp>
[2721]59#include <icxercesc/internal/XMLReader.hpp>
60#include <icxercesc/framework/XMLBuffer.hpp>
[2720]61
62XERCES_CPP_NAMESPACE_BEGIN
63
64// ---------------------------------------------------------------------------
65//  Local static data
66//
67//  gConverter
68//      This is initialized when the user calls the platform init method,
69//      which calls our init method. This is the converter used for default
70//      conversion to/from the local code page.
71// ---------------------------------------------------------------------------
72static XMLLCPTranscoder*    gTranscoder = 0;
73static XMLCh                gNullStr[] =
74{
75        chOpenCurly, chLatin_n, chLatin_u, chLatin_l, chLatin_l, chCloseCurly, chNull
76};
77
78MemoryManager* XMLString::fgMemoryManager = 0;
79
80// ---------------------------------------------------------------------------
81//  XMLString: Public static methods
82// ---------------------------------------------------------------------------
83
84void XMLString::sizeToText(  const  XMLSize_t           toFormat
85                                                        ,       char* const          toFill
86                                                        , const XMLSize_t            maxChars
87                                                        , const unsigned int         radix
88                                                        , MemoryManager* const       manager)
89{
90        static const char digitList[16] =
91        {
92                  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
93                , 'A', 'B', 'C', 'D', 'E', 'F'
94        };
95
96        if (!maxChars)
97                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
98
99        // Handle special case
100        if (!toFormat)
101        {
102                toFill[0] = '0';
103                toFill[1] = 0;
104                return;
105        }
106
107        // This is used to fill the temp buffer
108        XMLSize_t tmpIndex = 0;
109
110        // A copy of the conversion value that we can modify
111        XMLSize_t tmpVal = toFormat;
112
113        //
114        //  Convert into a temp buffer that we know is large enough. This avoids
115        //  having to check for overflow in the inner loops, and we have to flip
116        //  the resulting XMLString anyway.
117        //
118        char   tmpBuf[128];
119
120        //
121        //  For each radix, do the optimal thing. For bin and hex, we can special
122        //  case them and do shift and mask oriented stuff. For oct and decimal
123        //  there isn't much to do but bull through it with divides.
124        //
125        if (radix == 2)
126        {
127                while (tmpVal)
128                {
129                        if (tmpVal & 0x1UL)
130                                tmpBuf[tmpIndex++] = '1';
131                        else
132                                tmpBuf[tmpIndex++] = '0';
133                        tmpVal >>= 1;
134                }
135        }
136         else if (radix == 16)
137        {
138                while (tmpVal)
139                {
140                        const XMLSize_t charInd = (tmpVal & 0xFUL);
141                        tmpBuf[tmpIndex++] = digitList[charInd];
142                        tmpVal >>= 4;
143                }
144        }
145         else if ((radix == 8) || (radix == 10))
146        {
147                while (tmpVal)
148                {
149                        const XMLSize_t charInd = (tmpVal % radix);
150                        tmpBuf[tmpIndex++] = digitList[charInd];
151                        tmpVal /= radix;
152                }
153        }
154        else
155        {
156                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager);
157        }
158
159        // See if have enough room in the caller's buffer
160        if (tmpIndex > maxChars)
161        {
[3564]162        generateCallstack();
[2720]163                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager);
164        }
165
166        // Reverse the tmp buffer into the caller's buffer
167        XMLSize_t outIndex = 0;
168        for (; tmpIndex > 0; tmpIndex--)
169                toFill[outIndex++] = tmpBuf[tmpIndex-1];
170
171        // And cap off the caller's buffer
172        toFill[outIndex] = char(0);
173}
174
175void XMLString::binToText(  const   unsigned long   toFormat
176                                                        ,       char* const     toFill
177                                                        , const XMLSize_t       maxChars
178                                                        , const unsigned int    radix
179                                                        , MemoryManager* const  manager)
180{
181        static const char digitList[16] =
182        {
183                  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
184                , 'A', 'B', 'C', 'D', 'E', 'F'
185        };
186
187        if (!maxChars)
188                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
189
190        // Handle special case
191        if (!toFormat)
192        {
193                toFill[0] = '0';
194                toFill[1] = 0;
195                return;
196        }
197
198        // This is used to fill the temp buffer
199        XMLSize_t tmpIndex = 0;
200
201        // A copy of the conversion value that we can modify
202        unsigned long tmpVal = toFormat;
203
204        //
205        //  Convert into a temp buffer that we know is large enough. This avoids
206        //  having to check for overflow in the inner loops, and we have to flip
207        //  the resulting XMLString anyway.
208        //
209        char   tmpBuf[128];
210
211        //
212        //  For each radix, do the optimal thing. For bin and hex, we can special
213        //  case them and do shift and mask oriented stuff. For oct and decimal
214        //  there isn't much to do but bull through it with divides.
215        //
216        if (radix == 2)
217        {
218                while (tmpVal)
219                {
220                        if (tmpVal & 0x1UL)
221                                tmpBuf[tmpIndex++] = '1';
222                        else
223                                tmpBuf[tmpIndex++] = '0';
224                        tmpVal >>= 1;
225                }
226        }
227         else if (radix == 16)
228        {
229                while (tmpVal)
230                {
231                        const unsigned long charInd = (tmpVal & 0xFUL);
232                        tmpBuf[tmpIndex++] = digitList[charInd];
233                        tmpVal >>= 4;
234                }
235        }
236         else if ((radix == 8) || (radix == 10))
237        {
238                while (tmpVal)
239                {
240                        const unsigned long charInd = (tmpVal % radix);
241                        tmpBuf[tmpIndex++] = digitList[charInd];
242                        tmpVal /= radix;
243                }
244        }
245        else
246        {
247                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager);
248        }
249
250        // See if have enough room in the caller's buffer
251        if (tmpIndex > maxChars)
252        {
[3564]253        generateCallstack();
[2720]254                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager);
255        }
256
257        // Reverse the tmp buffer into the caller's buffer
258        XMLSize_t outIndex = 0;
259        for (; tmpIndex > 0; tmpIndex--)
260                toFill[outIndex++] = tmpBuf[tmpIndex-1];
261
262        // And cap off the caller's buffer
263        toFill[outIndex] = char(0);
264}
265
266void XMLString::binToText(  const   unsigned int    toFormat
267                                                        ,       char* const     toFill
268                                                        , const XMLSize_t       maxChars
269                                                        , const unsigned int    radix
270                                                        , MemoryManager* const  manager)
271{
272        // Just call the unsigned long version
273        binToText((unsigned long)toFormat, toFill, maxChars, radix, manager);
274}
275
276void XMLString::binToText(  const   long            toFormat
277                                                        ,       char* const     toFill
278                                                        , const XMLSize_t       maxChars
279                                                        , const unsigned int    radix
280                                                        , MemoryManager* const  manager)
281{
282        //
283        //  If its negative, then put a negative sign into the output and flip
284        //  the sign of the local temp value.
285        //
286        XMLSize_t startInd = 0;
287        unsigned long actualVal;
288        if (toFormat < 0)
289        {
290                toFill[0] = '-';
291                startInd++;
292                // Signed integers can represent one extra negative value
293                // compared to the positive values. If we simply do (v * -1)
294                // we will overflow on that extra value.
295                //
296                long v = toFormat;
297                v++;
298                actualVal = (unsigned long)(v * -1);
299                actualVal++;
300        }
301         else
302        {
303                actualVal = (unsigned long)(toFormat);
304        }
305
306        // And now call the unsigned long version
307        binToText(actualVal, &toFill[startInd], maxChars, radix, manager);
308}
309
310void XMLString::binToText(  const   int             toFormat
311                                                        ,       char* const     toFill
312                                                        , const XMLSize_t       maxChars
313                                                        , const unsigned int    radix
314                                                        , MemoryManager* const  manager)
315{
316        // Just call the long version
317        binToText((long)toFormat, toFill, maxChars, radix, manager);
318}
319
320
321void XMLString::catString(char* const target, const char* const src)
322{
323        strcat(target, src);
324}
325
326
327int XMLString::compareIString(const char* const str1, const char* const str2)
328{
329        return stricmp(str1, str2);
330}
331
332
333int XMLString::compareNString(  const   char* const     str1
334                                                                , const char* const     str2
335                                                                , const XMLSize_t       count)
336{
337        // Watch for pathological secenario
338        if (!count)
339                return 0;
340
341        return strncmp(str1, str2, count);
342}
343
344
345int XMLString::compareNIString( const   char* const     str1
346                                                                , const char* const     str2
347                                                                , const XMLSize_t       count)
348{
349        if (!count)
350                return 0;
351
352        return strnicmp(str1, str2, count);
353}
354
355
356int XMLString::compareString(   const   char* const    str1
357                                                                , const char* const    str2)
358{
359        return strcmp(str1, str2);
360}
361
362
363void XMLString::copyString(         char* const    target
364                                                        , const char* const    src)
365{
366        strcpy(target, src);
367}
368
369
370void XMLString::cut(        XMLCh* const    toCutFrom
371                                        , const XMLSize_t       count)
372{
373        #if defined(XML_DEBUG)
374        if (count > stringLen(toCutFrom))
375        {
376                // <TBD> This is bad of course
377        }
378        #endif
379
380        // If count is zero, then nothing to do
381        if (!count)
382                return;
383
384        XMLCh* targetPtr = toCutFrom;
385        XMLCh* srcPtr = toCutFrom + count;
386        while (*srcPtr)
387                *targetPtr++ = *srcPtr++;
388
389        // Cap it off at the new end
390        *targetPtr = 0;
391}
392
393
394XMLSize_t XMLString::hash(   const   char* const    tohash
395                                                        , const XMLSize_t       hashModulus)
396{
397        XMLSize_t hashVal = 0;
398        if (tohash) {
399                const char* curCh = tohash;
400                while (*curCh)
401                {
402                        XMLSize_t top = hashVal >> 24;
403                        hashVal += (hashVal * 37) + top + (XMLSize_t)(*curCh);
404                        curCh++;
405                }
406        }
407
408        // Divide by modulus
409        return hashVal % hashModulus;
410}
411
412
413int XMLString::indexOf(const char* const toSearch, const char ch)
414{
415        const XMLSize_t len = strlen(toSearch);
416        for (XMLSize_t i = 0; i < len; i++)
417        {
418                if (toSearch[i] == ch)
419                        return (int)i;
420        }
421        return -1;
422}
423
424
425int XMLString::indexOf( const   char* const     toSearch
426                                                , const char            ch
427                                                , const XMLSize_t       fromIndex
428                                                , MemoryManager* const  manager)
429{
430        const XMLSize_t len = strlen(toSearch);
431
432        // Make sure the start index is within the XMLString bounds
433                if ((int)fromIndex > ((int)len)-1)
434                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
435
436        for (XMLSize_t i = fromIndex; i < len; i++)
437        {
438                if (toSearch[i] == ch)
439                        return (int)i;
440        }
441        return -1;
442}
443
444int XMLString::lastIndexOf(const char* const toSearch, const char ch)
445{
446        const int len = (int)strlen(toSearch);
447        for (int i = len-1; i >= 0; i--)
448        {
449                if (toSearch[i] == ch)
450                        return i;
451        }
452        return -1;
453}
454
455int XMLString::lastIndexOf( const   char* const     toSearch
456                                                        , const char            ch
457                                                        , const XMLSize_t       fromIndex
458                                                        , MemoryManager* const  manager)
459{
460        const XMLSize_t len = strlen(toSearch);
461
462        // Make sure the start index is within the XMLString bounds
463                if ((int)fromIndex > ((int)len)-1)
464                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
465
466        for (int i = (int)fromIndex; i >= 0; i--)
467        {
468                if (toSearch[i] == ch)
469                        return i;
470        }
471        return -1;
472}
473
474
475XMLSize_t XMLString::replaceTokens(          XMLCh* const    errText
476                                                                                , const XMLSize_t       maxChars
477                                                                                , const XMLCh* const    text1
478                                                                                , const XMLCh* const    text2
479                                                                                , const XMLCh* const    text3
480                                                                                , const XMLCh* const    text4
481                                                                                , MemoryManager* const  manager)
482{
483        //
484        //  We have to build the string back into the source string, so allocate
485        //  a temp string and copy the orignal text to it. We'll then treat the
486        //  incoming buffer as a target buffer. Put a janitor on it to make sure
487        //  it gets cleaned up.
488        //
489        XMLCh* orgText = replicate(errText, manager);
490        ArrayJanitor<XMLCh> janText(orgText, manager);
491
492        XMLCh* pszSrc = orgText;
493        XMLSize_t curOutInd = 0;
494
495        while (*pszSrc && (curOutInd < maxChars))
496        {
497                //
498                //  Loop until we see a { character. Until we do, just copy chars
499                //  from src to target, being sure not to overrun the output buffer.
500                //
501                while ((*pszSrc != chOpenCurly) && (curOutInd < maxChars))
502                {
503                        if (!*pszSrc)
504                                break;
505                        errText[curOutInd++] = *pszSrc++;
506                }
507
508                // If we did not find a curly, then we are done
509                if (*pszSrc != chOpenCurly)
510                        break;
511
512                //
513                //  Probe this one to see if it matches our pattern of {x}. If not
514                //  then copy over those chars and go back to the first loop.
515                //
516                if ((*(pszSrc+1) >= chDigit_0)
517                &&  (*(pszSrc+1) <= chDigit_3)
518                &&  (*(pszSrc+2) == chCloseCurly))
519                {
520                        //
521                        //  Its one of our guys, so move the source pointer up past the
522                        //  token we are replacing. First though get out the token number
523                        //  character.
524                        //
525                        XMLCh tokCh = *(pszSrc+1);
526                        pszSrc += 3;
527
528                        // Now copy over the replacement text
529                        const XMLCh* repText = 0;
530                        if (tokCh == chDigit_0)
531                                repText = text1;
532                        else if (tokCh == chDigit_1)
533                                repText = text2;
534                        else if (tokCh == chDigit_2)
535                                repText = text3;
536                        else if (tokCh == chDigit_3)
537                                repText = text4;
538
539                        // If this one is null, copy over a null string
540                        if (!repText)
541                                repText = gNullStr;
542
543                        while (*repText && (curOutInd < maxChars))
544                                errText[curOutInd++] = *repText++;
545                }
546                 else
547                {
548                        // Escape the curly brace character and continue
549                        errText[curOutInd++] = *pszSrc++;
550                }
551        }
552
553        // Copy over a null terminator
554        errText[curOutInd] = 0;
555
556        // And return the count of chars we output
557        return curOutInd;
558}
559
560
561char* XMLString::replicate( const char* const    toRep
562                                                  , MemoryManager* const manager)
563{
564        // If a null string, return a null string
565        if (!toRep)
566                return 0;
567
568        //
569        //  Get the len of the source and allocate a new buffer. Make sure to
570        //  account for the nul terminator.
571        //
572        const XMLSize_t srcLen = strlen(toRep);
573        char* ret = (char*) manager->allocate((srcLen+1) * sizeof(char)); //new char[srcLen+1];
574
575        // Copy over the text, adjusting for the size of a char
576        memcpy(ret, toRep, (srcLen+1) * sizeof(char));
577        return ret;
578}
579
580
581bool XMLString::startsWith(const char* const toTest, const char* const prefix)
582{
583        return (strncmp(toTest, prefix, strlen(prefix)) == 0);
584}
585
586
587bool XMLString::startsWithI(const   char* const toTest
588                                                        , const char* const prefix)
589{
590        return (strnicmp(toTest, prefix, strlen(prefix)) == 0);
591}
592
593
594XMLSize_t XMLString::stringLen(const char* const src)
595{
596        return strlen(src);
597}
598
599char* XMLString::transcode(const XMLCh* const toTranscode,
600                                                   MemoryManager* const manager)
601{
602        return gTranscoder->transcode(toTranscode, manager);
603}
604
605
606bool XMLString::transcode(  const   XMLCh* const    toTranscode
607                                                        ,       char* const     toFill
608                                                        , const XMLSize_t       maxChars
609                                                        , MemoryManager* const  manager)
610{
611        return gTranscoder->transcode(toTranscode, toFill, maxChars, manager);
612}
613
614XMLCh* XMLString::transcode(const char* const toTranscode,
615                                                        MemoryManager* const manager)
616{
617        return gTranscoder->transcode(toTranscode, manager);
618}
619
620bool XMLString::transcode(  const   char* const     toTranscode
621                                                        ,       XMLCh* const    toFill
622                                                        , const XMLSize_t       maxChars
623                                                        , MemoryManager* const  manager)
[3564]624{   
[2720]625        return gTranscoder->transcode(toTranscode, toFill, maxChars, manager);
626}
627
628
629void XMLString::trim(char* const toTrim)
630{
631        const XMLSize_t len = strlen(toTrim);
632
633        XMLSize_t skip, scrape;
634        for (skip = 0; skip < len; skip++)
635        {
636                if (! isspace(toTrim[skip]))
637                        break;
638        }
639
640        for (scrape = len; scrape > skip; scrape--)
641        {
642                if (! isspace(toTrim[scrape - 1] ))
643                        break;
644        }
645
646        // Cap off at the scrap point
647        if (scrape != len)
648                toTrim[scrape] = 0;
649
650        if (skip)
651        {
652                // Copy the chars down
653                XMLSize_t index = 0;
654                while (toTrim[skip])
655                        toTrim[index++] = toTrim[skip++];
656
657                toTrim[index] = 0;
658        }
659}
660
661
662void XMLString::subString(char* const targetStr, const char* const srcStr
663                                                  , const XMLSize_t startIndex, const XMLSize_t endIndex
664                                                  , MemoryManager* const manager)
665{
666        if (targetStr == 0)
667                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
668
669        const XMLSize_t srcLen = strlen(srcStr);
670
671        // Make sure the start index is within the XMLString bounds
672        if (startIndex > endIndex || endIndex > srcLen)
673                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
674
675        const XMLSize_t copySize = endIndex - startIndex;
676
677        for (XMLSize_t i= startIndex; i < endIndex; i++) {
678                targetStr[i-startIndex] = srcStr[i];
679        }
680
681        targetStr[copySize] = 0;
682}
683
684bool XMLString::isValidNOTATION(const XMLCh*         const name
685                                                          ,       MemoryManager* const manager )
686{
687        //
688        //  NOTATATION: <URI>:<localPart>
689        //  where URI is optional
690        //        ':' and localPart must be present
691        //
692        XMLSize_t nameLen = XMLString::stringLen(name);
693        int colPos = XMLString::lastIndexOf(name, chColon);
694
695        if ((colPos == 0)         ||      // no ':'
696                (colPos == ((int)nameLen) - 1)  )     // <URI>':'
697                return false;
698
699
700        // Examine localpart
701        if (!XMLChar1_0::isValidNCName(&name[colPos+1], nameLen - colPos -1))
702        {
703                return false;
704        }
705        else if (colPos == -1)
706        {
707                return true;
708        }
709        else
710        {
711                // Examine URI
712                XMLCh* const temp =
713                        (XMLCh*) manager->allocate((colPos + 1) * sizeof(XMLCh));
714                const ArrayJanitor<XMLCh> jan(temp, manager);
715
716                copyNString(temp, name, colPos);
717                temp[colPos] = 0;
718
719                try
720                {
721                        XMLUri  newURI(temp, manager); // no relative uri support here
722                }
723                catch (const MalformedURLException&)
724                {
725                        return false;
726                }
727
728                return true;
729        }
730}
731
732/**
733  * isValidEncName
734  *
735  * [80] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
736  *
737  */
738bool XMLString::isValidEncName(const XMLCh* const name)
739{
740                if (name == 0 || *name == 0)
741                return false;
742
743        const XMLCh* tempName = name;
744        XMLCh firstChar = *tempName++;
745
746        if (!isAlpha(firstChar))
747                return false;
748
749        while(*tempName)
750        {
751                if (( !isAlpha(*tempName))       &&
752                        ( !isDigit(*tempName))       &&
753                        ( *tempName != chPeriod)     &&
754                        ( *tempName != chUnderscore) &&
755                        ( *tempName != chDash)        )
756                        return false;
757
758                tempName++;
759        }
760
761        return true;
762}
763
764bool XMLString::isAlpha(XMLCh const theChar)
765{
766        if ((( theChar >= chLatin_a ) && ( theChar <= chLatin_z )) ||
767                (( theChar >= chLatin_A ) && ( theChar <= chLatin_Z )) )
768                return true;
769
770        return false;
771}
772
773bool XMLString::isDigit(XMLCh const theChar)
774{
775        if (( theChar >= chDigit_0 ) && ( theChar <= chDigit_9 ))
776                return true;
777
778        return false;
779}
780
781bool XMLString::isAlphaNum(XMLCh const theChar)
782{
783        return (isAlpha(theChar) || isDigit(theChar));
784}
785
786bool XMLString::isHex(XMLCh const theChar)
787{
788                return (isDigit(theChar) ||
789                                                (theChar >= chLatin_a && theChar <= chLatin_f) ||
790                                                (theChar >= chLatin_A && theChar <= chLatin_F));
791}
792
793// ---------------------------------------------------------------------------
794//  Wide char versions of most of the string methods
795// ---------------------------------------------------------------------------
796
797void XMLString::sizeToText(  const  XMLSize_t            toFormat
798                                                        ,       XMLCh* const         toFill
799                                                        , const XMLSize_t            maxChars
800                                                        , const unsigned int         radix
801                                                        , MemoryManager* const       manager)
802{
803        static const XMLCh digitList[16] =
804        {
805                        chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, chDigit_5
806                ,   chDigit_6, chDigit_7, chDigit_8, chDigit_9, chLatin_A, chLatin_B
[3157]807                ,   chLatin_C, chLatin_D, chLatin_E, chLatin_F
[2720]808        };
809
810        if (!maxChars)
811                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
812
813        // Handle special case
814        if (!toFormat)
815        {
816                toFill[0] = chDigit_0;
817                toFill[1] = chNull;
818                return;
819        }
820
821        // This is used to fill the temp buffer
822        XMLSize_t tmpIndex = 0;
823
824        // A copy of the conversion value that we can modify
825        XMLSize_t tmpVal = toFormat;
826
827        //
828        //  Convert into a temp buffer that we know is large enough. This avoids
829        //  having to check for overflow in the inner loops, and we have to flip
830        //  the resulting sring anyway.
831        //
832        XMLCh   tmpBuf[128];
833
834        //
835        //  For each radix, do the optimal thing. For bin and hex, we can special
836        //  case them and do shift and mask oriented stuff. For oct and decimal
837        //  there isn't much to do but bull through it with divides.
838        //
839        if (radix == 2)
840        {
841                while (tmpVal)
842                {
843                        if (tmpVal & 0x1UL)
844                                tmpBuf[tmpIndex++] = chDigit_1;
845                        else
846                                tmpBuf[tmpIndex++] = chDigit_0;
847                        tmpVal >>= 1;
848                }
849        }
850         else if (radix == 16)
851        {
852                while (tmpVal)
853                {
854                        const XMLSize_t charInd = (tmpVal & 0xFUL);
855                        tmpBuf[tmpIndex++] = digitList[charInd];
856                        tmpVal >>= 4;
857                }
858        }
859         else if ((radix == 8) || (radix == 10))
860        {
861                while (tmpVal)
862                {
863                        const XMLSize_t charInd = (tmpVal % radix);
864                        tmpBuf[tmpIndex++] = digitList[charInd];
865                        tmpVal /= radix;
866                }
867        }
868         else
869        {
870                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager);
871        }
872
873        // See if have enough room in the caller's buffer
874        if (tmpIndex > maxChars)
875        {
[3564]876        generateCallstack();
[2720]877                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager);
878        }
879
880        // Reverse the tmp buffer into the caller's buffer
881        XMLSize_t outIndex = 0;
882        for (; tmpIndex > 0; tmpIndex--)
883                toFill[outIndex++] = tmpBuf[tmpIndex-1];
884
885        // And cap off the caller's buffer
886        toFill[outIndex] = chNull;
887}
888
889void XMLString::binToText(  const   unsigned long   toFormat
890                                                        ,       XMLCh* const    toFill
891                                                        , const XMLSize_t       maxChars
892                                                        , const unsigned int    radix
893                                                        , MemoryManager* const  manager)
894{
895        static const XMLCh digitList[16] =
896        {
897                        chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, chDigit_5
898                ,   chDigit_6, chDigit_7, chDigit_8, chDigit_9, chLatin_A, chLatin_B
[3157]899                ,   chLatin_C, chLatin_D, chLatin_E, chLatin_F
[2720]900        };
901
902        if (!maxChars)
903                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
904
905        // Handle special case
906        if (!toFormat)
907        {
908                toFill[0] = chDigit_0;
909                toFill[1] = chNull;
910                return;
911        }
912
913        // This is used to fill the temp buffer
914        XMLSize_t tmpIndex = 0;
915
916        // A copy of the conversion value that we can modify
917        unsigned long tmpVal = toFormat;
918
919        //
920        //  Convert into a temp buffer that we know is large enough. This avoids
921        //  having to check for overflow in the inner loops, and we have to flip
922        //  the resulting sring anyway.
923        //
924        XMLCh   tmpBuf[128];
925
926        //
927        //  For each radix, do the optimal thing. For bin and hex, we can special
928        //  case them and do shift and mask oriented stuff. For oct and decimal
929        //  there isn't much to do but bull through it with divides.
930        //
931        if (radix == 2)
932        {
933                while (tmpVal)
934                {
935                        if (tmpVal & 0x1UL)
936                                tmpBuf[tmpIndex++] = chDigit_1;
937                        else
938                                tmpBuf[tmpIndex++] = chDigit_0;
939                        tmpVal >>= 1;
940                }
941        }
942         else if (radix == 16)
943        {
944                while (tmpVal)
945                {
946                        const unsigned long charInd = (tmpVal & 0xFUL);
947                        tmpBuf[tmpIndex++] = digitList[charInd];
948                        tmpVal >>= 4;
949                }
950        }
951         else if ((radix == 8) || (radix == 10))
952        {
953                while (tmpVal)
954                {
955                        const unsigned long charInd = (tmpVal % radix);
956                        tmpBuf[tmpIndex++] = digitList[charInd];
957                        tmpVal /= radix;
958                }
959        }
960         else
961        {
962                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Str_UnknownRadix, manager);
963        }
964
965        // See if have enough room in the caller's buffer
966        if (tmpIndex > maxChars)
967        {
[3564]968        generateCallstack();
[2720]969                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_TargetBufTooSmall, manager);
970        }
971
972        // Reverse the tmp buffer into the caller's buffer
973        XMLSize_t outIndex = 0;
974        for (; tmpIndex > 0; tmpIndex--)
975                toFill[outIndex++] = tmpBuf[tmpIndex-1];
976
977        // And cap off the caller's buffer
978        toFill[outIndex] = chNull;
979}
980
981void XMLString::binToText(  const   unsigned int    toFormat
982                                                        ,       XMLCh* const    toFill
983                                                        , const XMLSize_t       maxChars
984                                                        , const unsigned int    radix
985                                                        , MemoryManager* const  manager)
986{
987        // Just call the unsigned long version
988        binToText((unsigned long)toFormat, toFill, maxChars, radix, manager);
989}
990
991void XMLString::binToText(  const   long            toFormat
992                                                        ,       XMLCh* const    toFill
993                                                        , const XMLSize_t       maxChars
994                                                        , const unsigned int    radix
995                                                        , MemoryManager* const  manager)
996{
997        //
998        //  If its negative, then put a negative sign into the output and flip
999        //  the sign of the local temp value.
1000        //
1001        XMLSize_t startInd = 0;
1002        unsigned long actualVal;
1003        if (toFormat < 0)
1004        {
1005                toFill[0] = chDash;
1006                startInd++;
1007                // Signed integers can represent one extra negative value
1008                // compared to the positive values. If we simply do (v * -1)
1009                // we will overflow on that extra value.
1010                //
1011                long v = toFormat;
1012                v++;
1013                actualVal = (unsigned long)(v * -1);
1014                actualVal++;
1015        }
1016         else
1017        {
1018                actualVal = (unsigned long)(toFormat);
1019        }
1020
1021        // And now call the unsigned long version
1022        binToText(actualVal, &toFill[startInd], maxChars, radix, manager);
1023}
1024
1025void XMLString::binToText(  const   int             toFormat
1026                                                        ,       XMLCh* const    toFill
1027                                                        , const XMLSize_t       maxChars
1028                                                        , const unsigned int    radix
1029                                                        , MemoryManager* const  manager)
1030{
1031        // Just call the long version
1032        binToText((long)toFormat, toFill, maxChars, radix, manager);
1033}
1034
1035void XMLString::catString(XMLCh* const target, const XMLCh* const src)
1036{
1037        // Get the starting point for the cat on the target XMLString
1038        XMLSize_t index = stringLen(target);
1039
1040        // While the source is not zero, add them to target and bump
1041        const XMLCh* pszTmp = src;
1042        while (*pszTmp)
1043                target[index++] = *pszTmp++;
1044
1045        // Cap off the target where we ended
1046        target[index] = chNull;
1047}
1048
1049
1050int XMLString::compareIString(  const   XMLCh* const    str1
1051                                                                , const XMLCh* const    str2)
1052{
1053        // Refer this one to the transcoding service
1054        return XMLPlatformUtils::fgTransService->compareIString(str1, str2);
1055}
1056
1057int XMLString::compareIStringASCII(  const   XMLCh* const    str1
1058                                                                         , const XMLCh* const    str2)
1059{
1060        const XMLCh* psz1 = str1;
1061        const XMLCh* psz2 = str2;
1062
1063        if (psz1 == 0 || psz2 == 0) {
1064
1065                if (psz1 == 0) {
1066                        return 0 - (int)XMLString::stringLen(psz2);
1067                }
1068                                else if (psz2 == 0) {
1069                        return (int)XMLString::stringLen(psz1);
1070                }
1071        }
1072
1073        XMLCh ch1;
1074        XMLCh ch2;
1075
1076        for (;;) {
1077                if (*psz1 >= chLatin_A && *psz1 <= chLatin_Z)
1078                        ch1 = *psz1 - chLatin_A + chLatin_a;
1079                else
1080                        ch1 = *psz1;
1081                if (*psz2 >= chLatin_A && *psz2 <= chLatin_Z)
1082                        ch2 = *psz2 - chLatin_A + chLatin_a;
1083                else
1084                        ch2 = *psz2;
1085
1086                // If an inequality, then return difference
1087                if (ch1 != ch2)
1088                        return int(ch1) - int(ch2);
1089
1090                // If either ended, then both ended, so equal
1091                if (!ch1)
1092                        break;
1093
1094                // Move upwards to next chars
1095                psz1++;
1096                psz2++;
1097        }
1098        return 0;
1099}
1100
1101int XMLString::compareNString(  const   XMLCh* const    str1
1102                                                                , const XMLCh* const    str2
1103                                                                , const XMLSize_t       maxChars)
1104{
1105        const XMLCh* psz1 = str1;
1106        const XMLCh* psz2 = str2;
1107
1108        XMLSize_t curCount = 0;
1109        while (curCount < maxChars)
1110        {
1111                // If an inequality, then return difference
1112                if (*psz1 != *psz2)
1113                        return int(*psz1) - int(*psz2);
1114
1115                // If either ended, then both ended, so equal
1116                if (!*psz1)
1117                        break;
1118
1119                // Move upwards to next chars
1120                psz1++;
1121                psz2++;
1122
1123                //
1124                //  Bump the count of chars done.
1125                //
1126                curCount++;
1127        }
1128        // If we inspected all the maxChars, then we are equal.
1129        return 0;
1130}
1131
1132
1133int XMLString::compareNIString( const   XMLCh* const    str1
1134                                                                , const XMLCh* const    str2
1135                                                                , const XMLSize_t       maxChars)
1136{
1137        // Refer this oneto the transcoding service
1138        return XMLPlatformUtils::fgTransService->compareNIString(str1, str2, maxChars);
1139}
1140
1141
1142int XMLString::compareString(   const   XMLCh* const    str1
1143                                                                , const XMLCh* const    str2)
1144{
1145        const XMLCh* psz1 = str1;
1146        const XMLCh* psz2 = str2;
1147
1148        if (psz1 == 0 || psz2 == 0) {
1149
1150                if (psz1 == 0) {
1151                        return 0 - (int)XMLString::stringLen(psz2);
1152                }
1153                                else if (psz2 == 0) {
1154                        return (int)XMLString::stringLen(psz1);
1155                }
1156        }
1157
1158        for (;;)
1159        {
1160                // If an inequality, then return the difference
1161                if (*psz1 != *psz2)
1162                        return int(*psz1) - int(*psz2);
1163
1164                // If either has ended, then they both ended, so equal
1165                if (!*psz1)
1166                        break;
1167
1168                // Move upwards for the next round
1169                psz1++;
1170                psz2++;
1171        }
1172        return 0;
1173}
1174
1175
1176bool XMLString::regionMatches(const   XMLCh* const      str1
1177                                                                                                                  , const int                   offset1
1178                                                                                                                  , const XMLCh* const  str2
1179                                                                                                                  , const int                   offset2
1180                                                                                                                  , const XMLSize_t     charCount)
1181{
1182                if (!validateRegion(str1, offset1,str2, offset2, charCount))
1183                                return false;
1184
1185                if (compareNString(str1+offset1, str2+offset2, charCount) != 0)
1186                                return false;
1187
1188                return true;
1189}
1190
1191bool XMLString::regionIMatches(const   XMLCh* const     str1
1192                                                                                                                   , const int                  offset1
1193                                                                                                                   , const XMLCh* const str2
1194                                                                                                                   , const int                  offset2
1195                                                                                                                   , const XMLSize_t    charCount)
1196{
1197                if (!validateRegion(str1, offset1,str2, offset2, charCount))
1198                                return false;
1199
1200                if (compareNIString(str1+offset1, str2+offset2, charCount) != 0)
1201                                return false;
1202
1203                return true;
1204}
1205
1206void XMLString::copyString(XMLCh* const target, const XMLCh* const src)
1207{
1208        if (!src)
1209        {
1210                *target = 0;
1211                return;
1212        }
1213
1214        XMLCh* pszOut = target;
1215        const XMLCh* pszIn = src;
1216        while (*pszIn)
1217                *pszOut++ = *pszIn++;
1218
1219        // Cap off the target where we ended
1220        *pszOut = 0;
1221}
1222
1223
1224bool XMLString::copyNString(        XMLCh* const    target
1225                                                        , const XMLCh* const    src
1226                                                        , const XMLSize_t       maxChars)
1227{
1228        // Return whether we copied it all or hit the max
1229        XMLSize_t len = stringLen(src);
1230        if (len > maxChars)
1231        {
1232                XMLString::moveChars(target, src, maxChars);
1233                target[maxChars] = 0;
1234                return false;
1235        }
1236        XMLString::moveChars(target, src, len+1);
1237        return true;
1238}
1239
1240const XMLCh* XMLString::findAny(const   XMLCh* const    toSearch
1241                                                                , const XMLCh* const    searchList)
1242{
1243        const XMLCh* srcPtr = toSearch;
1244        while (*srcPtr)
1245        {
1246                const XMLCh* listPtr = searchList;
1247                const XMLCh  curCh = *srcPtr;
1248
1249                while (*listPtr)
1250                {
1251                        if (curCh == *listPtr++)
1252                                return srcPtr;
1253                }
1254                srcPtr++;
1255        }
1256        return 0;
1257}
1258
1259XMLCh* XMLString::findAny(          XMLCh* const    toSearch
1260                                                        , const XMLCh* const    searchList)
1261{
1262        XMLCh* srcPtr = toSearch;
1263        while (*srcPtr)
1264        {
1265                const XMLCh* listPtr = searchList;
1266                const XMLCh  curCh = *srcPtr;
1267
1268                while (*listPtr)
1269                {
1270                        if (curCh == *listPtr++)
1271                                return srcPtr;
1272                }
1273                srcPtr++;
1274        }
1275        return 0;
1276}
1277
1278int XMLString::patternMatch(  const XMLCh* const    toSearch
1279                                                        , const XMLCh* const    pattern)
1280{
1281        if (!toSearch || !*toSearch )
1282                return -1;
1283
1284        const XMLSize_t patnLen = XMLString::stringLen(pattern);
1285                if ( !patnLen )
1286                                return -1;
1287
1288        const XMLCh* srcPtr    = toSearch;
1289        const XMLCh* patnStart = toSearch;
1290        XMLSize_t patnIndex = 0;
1291
1292        while (*srcPtr)
1293        {
1294                if ( !(*srcPtr++ == pattern[patnIndex]))
1295                {
1296                        patnIndex = 0;
1297                        srcPtr = ++patnStart;
1298                }
1299                else
1300                {
1301                        if (++patnIndex == patnLen)
1302                                // full pattern match found
1303                                return (int)(srcPtr - patnLen - toSearch);
1304
1305                }
1306        }
1307
1308        return -1;
1309}
1310
1311
1312int XMLString::indexOf(const XMLCh* const toSearch, const XMLCh ch)
1313{
1314        if (!toSearch || !*toSearch) return -1;
1315
1316        const XMLCh* srcPtr = toSearch;
1317        while (*srcPtr)
1318                if (ch == *srcPtr++)
1319                        return (int)(srcPtr - toSearch - 1);
1320        return -1;
1321}
1322
1323
1324int XMLString::indexOf( const   XMLCh* const    toSearch
1325                                                , const XMLCh           ch
1326                                                , const XMLSize_t       fromIndex
1327                                                , MemoryManager* const  manager)
1328{
1329        const XMLSize_t len = stringLen(toSearch);
1330
1331        // Make sure the start index is within the XMLString bounds
1332                if (fromIndex >= len)
1333                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
1334
1335        const XMLCh* srcPtr = toSearch+fromIndex;
1336        while (*srcPtr)
1337                if (ch == *srcPtr++)
1338                        return (int)(srcPtr - toSearch - 1);
1339        return -1;
1340}
1341
1342int XMLString::lastIndexOf(const XMLCh ch,
1343                                                   const XMLCh* const toSearch,
1344                                                   const XMLSize_t    toSearchLen)
1345{
1346        const XMLCh* srcPtr = toSearch+toSearchLen;
1347        while (srcPtr >= toSearch)
1348                if (ch == *srcPtr--)
1349                        return (int)(srcPtr + 1 - toSearch);
1350        return -1;
1351}
1352
1353int XMLString::lastIndexOf( const   XMLCh* const    toSearch
1354                                                        , const XMLCh           ch
1355                                                        , const XMLSize_t       fromIndex
1356                                                        , MemoryManager* const  manager)
1357{
1358        const XMLSize_t len = stringLen(toSearch);
1359                if (fromIndex >= len)
1360                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
1361
1362        const XMLCh* srcPtr = toSearch+fromIndex;
1363        while (srcPtr >= toSearch)
1364                if (ch == *srcPtr--)
1365                        return (int)(srcPtr + 1 - toSearch);
1366        return -1;
1367}
1368
1369
1370XMLCh*
1371XMLString::makeUName(const XMLCh* const pszURI, const XMLCh* const pszName)
1372{
1373        //
1374        //  If there is a URI, then format out the full name in the {uri}name
1375        //  form. Otherwise, just set it to the same thing as the base name.
1376        //
1377        XMLCh* pszRet = 0;
1378        const XMLSize_t uriLen = stringLen(pszURI);
1379        if (uriLen)
1380        {
1381                pszRet = new XMLCh[uriLen + stringLen(pszName) + 3];
1382
1383                XMLCh szTmp[2];
1384                szTmp[1] = 0;
1385
1386                szTmp[0] = chOpenCurly;
1387                copyString(pszRet, szTmp);
1388                catString(pszRet, pszURI);
1389                szTmp[0] = chCloseCurly;
1390                catString(pszRet, szTmp);
1391                catString(pszRet, pszName);
1392        }
1393         else
1394        {
1395                pszRet = replicate(pszName);
1396        }
1397        return pszRet;
1398}
1399
1400
1401bool XMLString::textToBin(const XMLCh* const toConvert, unsigned int& toFill
1402                                                  , MemoryManager* const manager)
1403{
1404        toFill = 0;
1405
1406        // If no string, then its a failure
1407        if ((!toConvert) || (!*toConvert))
1408                return false;
1409
1410                XMLCh* trimmedStr = XMLString::replicate(toConvert, manager);
1411                ArrayJanitor<XMLCh> jan1(trimmedStr, manager);
1412                XMLString::trim(trimmedStr);
1413        XMLSize_t trimmedStrLen = XMLString::stringLen(trimmedStr);
1414
1415                if ( !trimmedStrLen )
1416                                return false;
1417
1418                // we don't allow '-' sign
1419                if (XMLString::indexOf(trimmedStr, chDash, 0, manager) != -1)
1420                                return false;
1421
1422                //the errno set by previous run is NOT automatically cleared
1423                errno = 0;
1424
1425                char *nptr = XMLString::transcode(trimmedStr, manager);
1426        ArrayJanitor<char> jan2(nptr, manager);
1427
1428        char *endptr;
1429                 //
1430         // REVISIT: conversion of (unsigned long) to (unsigned int)
1431                 //          may truncate value on IA64
1432        toFill = (unsigned int) strtoul(nptr, &endptr, 10);
1433
1434                // check if all chars are valid char
1435                // check if overflow/underflow occurs
1436                if ( ( (endptr - nptr) != (int) trimmedStrLen) ||
1437                 (errno == ERANGE)                      )
1438                                return false;
1439
1440        return true;
1441}
1442
1443int XMLString::parseInt(const XMLCh* const toConvert
1444                                         , MemoryManager* const manager)
1445{
1446        // If no string, or empty string, then it is a failure
1447        if ((!toConvert) || (!*toConvert))
1448                ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
1449
1450                XMLCh* trimmedStr = XMLString::replicate(toConvert, manager);
1451                ArrayJanitor<XMLCh> jan1(trimmedStr, manager);
1452                XMLString::trim(trimmedStr);
1453        XMLSize_t trimmedStrLen = XMLString::stringLen(trimmedStr);
1454
1455                if ( !trimmedStrLen )
1456                ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
1457
1458                //the errno set by previous run is NOT automatically cleared
1459                errno = 0;
1460
1461                char *nptr = XMLString::transcode(trimmedStr, manager);
1462        ArrayJanitor<char> jan2(nptr, manager);
1463
1464        char *endptr;
1465        long retVal = strtol(nptr, &endptr, 10);
1466
1467                // check if all chars are valid char
1468                if ( (endptr - nptr) != (int) trimmedStrLen)
1469                                ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
1470
1471                // check if overflow/underflow occurs
1472        if (errno == ERANGE)
1473                ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::Str_ConvertOverflow, manager);
1474
1475                 //
1476         // REVISIT: conversion of (long) to (int)
1477                 //          may truncate value on IA64
1478                return (int) retVal;
1479}
1480
1481
1482void XMLString::trim(XMLCh* const toTrim)
1483{
1484        const XMLSize_t len = stringLen(toTrim);
1485
1486        XMLSize_t skip, scrape;
1487        for (skip = 0; skip < len; skip++)
1488        {
1489                if (!XMLChar1_0::isWhitespace(toTrim[skip]))
1490                        break;
1491        }
1492
1493        for (scrape = len; scrape > skip; scrape--)
1494        {
1495                if (!XMLChar1_0::isWhitespace(toTrim[scrape - 1]))
1496                        break;
1497        }
1498
1499        // Cap off at the scrap point
1500        if (scrape != len)
1501                toTrim[scrape] = 0;
1502
1503        if (skip)
1504        {
1505                // Copy the chars down
1506                XMLSize_t index = 0;
1507                while (toTrim[skip])
1508                        toTrim[index++] = toTrim[skip++];
1509
1510                toTrim[index] = 0;
1511        }
1512}
1513
1514
1515void XMLString::upperCase(XMLCh* const toUpperCase)
1516{
1517        // Refer this one to the transcoding service
1518        XMLPlatformUtils::fgTransService->upperCase(toUpperCase);
1519}
1520
1521void XMLString::upperCaseASCII(XMLCh* const toUpperCase)
1522{
1523        XMLCh* psz1 = toUpperCase;
1524
1525        if (!psz1)
1526                return;
1527
1528        while (*psz1) {
1529                if (*psz1 >= chLatin_a && *psz1 <= chLatin_z)
1530                        *psz1 = *psz1 - chLatin_a + chLatin_A;
1531
1532                psz1++;
1533        }
1534}
1535
1536
1537void XMLString::lowerCase(XMLCh* const toLowerCase)
1538{
1539        // Refer this one to the transcoding service
1540        XMLPlatformUtils::fgTransService->lowerCase(toLowerCase);
1541}
1542
1543void XMLString::lowerCaseASCII(XMLCh* const toLowerCase)
1544{
1545        XMLCh* psz1 = toLowerCase;
1546
1547        if (!psz1)
1548                return;
1549
1550        while (*psz1) {
1551                if (*psz1 >= chLatin_A && *psz1 <= chLatin_Z)
1552                        *psz1 = *psz1 - chLatin_A + chLatin_a;
1553
1554                psz1++;
1555        }
1556}
1557
1558void XMLString::subString(XMLCh* const targetStr, const XMLCh* const srcStr
1559                                                  , const XMLSize_t startIndex, const XMLSize_t endIndex
1560                                                  , MemoryManager* const manager)
1561{
1562        subString(targetStr, srcStr, startIndex, endIndex, stringLen(srcStr), manager);
1563}
1564
1565void XMLString::subString(XMLCh* const targetStr, const XMLCh* const srcStr
1566                                                  , const XMLSize_t startIndex, const XMLSize_t endIndex
1567                                                  , const XMLSize_t srcStrLength
1568                                                  , MemoryManager* const manager)
1569{
1570        //if (startIndex < 0 || endIndex < 0)
1571        //    ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_NegativeIndex);
1572
1573        if (targetStr == 0)
1574                ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Str_ZeroSizedTargetBuf, manager);
1575
1576        // Make sure the start index is within the XMLString bounds
1577        if (startIndex > endIndex || endIndex > srcStrLength)
1578                ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Str_StartIndexPastEnd, manager);
1579
1580        const XMLSize_t copySize = endIndex - startIndex;
1581
1582        for (XMLSize_t i= startIndex; i < endIndex; i++) {
1583                targetStr[i-startIndex] = srcStr[i];
1584        }
1585
1586        targetStr[copySize] = 0;
1587}
1588
[3564]1589BaseRefVectorOf<XMLCh>* XMLString::tokenizeString(const XMLCh* const tokenizeSrc
1590                                                , XMLCh delimiter
1591                                                , MemoryManager*    const manager)
1592{
1593    XMLCh* orgText = replicate(tokenizeSrc, manager);
1594    ArrayJanitor<XMLCh> janText(orgText, manager);
1595    XMLCh* tokenizeStr = orgText;
1596
1597    RefArrayVectorOf<XMLCh>* tokenStack = new (manager) RefArrayVectorOf<XMLCh>(16, true, manager);
1598
1599    XMLSize_t len = stringLen(tokenizeStr);
1600    XMLSize_t skip;
1601    XMLSize_t index = 0;
1602
1603    while (index != len) {
1604        // find the first non-space character
1605        for (skip = index; skip < len; skip++)
1606        {
1607            if (tokenizeStr[skip]!=delimiter)
1608                break;
1609        }
1610        index = skip;
1611
1612        // find the delimiter (space character)
1613        for (; skip < len; skip++)
1614        {
1615            if (tokenizeStr[skip]==delimiter)
1616                break;
1617        }
1618
1619        // we reached the end of the string
1620        if (skip == index)
1621            break;
1622
1623        // these tokens are adopted in the RefVector and will be deleted
1624        // when the vector is deleted by the caller
1625        XMLCh* token = (XMLCh*) manager->allocate
1626        (
1627            (skip+1-index) * sizeof(XMLCh)
1628        );//new XMLCh[skip+1-index];
1629
1630        XMLString::subString(token, tokenizeStr, index, skip, len, manager);
1631        tokenStack->addElement(token);
1632        index = skip;
1633    }
1634    return tokenStack;
1635}
1636
[2720]1637BaseRefVectorOf<XMLCh>* XMLString::tokenizeString(const XMLCh*      const   tokenizeSrc
1638                                                                                           ,  MemoryManager*    const   manager)
1639{
1640        XMLCh* orgText = replicate(tokenizeSrc, manager);
1641        ArrayJanitor<XMLCh> janText(orgText, manager);
1642        XMLCh* tokenizeStr = orgText;
1643
1644        RefArrayVectorOf<XMLCh>* tokenStack = new (manager) RefArrayVectorOf<XMLCh>(16, true, manager);
1645
1646        XMLSize_t len = stringLen(tokenizeStr);
1647        XMLSize_t skip;
1648        XMLSize_t index = 0;
1649
1650        while (index != len) {
1651                // find the first non-space character
1652                for (skip = index; skip < len; skip++)
1653                {
1654                        if (!XMLChar1_0::isWhitespace(tokenizeStr[skip]))
1655                                break;
1656                }
1657                index = skip;
1658
1659                // find the delimiter (space character)
1660                for (; skip < len; skip++)
1661                {
1662                        if (XMLChar1_0::isWhitespace(tokenizeStr[skip]))
1663                                break;
1664                }
1665
1666                // we reached the end of the string
1667                if (skip == index)
1668                        break;
1669
1670                // these tokens are adopted in the RefVector and will be deleted
1671                // when the vector is deleted by the caller
1672                XMLCh* token = (XMLCh*) manager->allocate
1673                (
1674                        (skip+1-index) * sizeof(XMLCh)
1675                );//new XMLCh[skip+1-index];
1676
1677                XMLString::subString(token, tokenizeStr, index, skip, len, manager);
1678                tokenStack->addElement(token);
1679                index = skip;
1680        }
1681        return tokenStack;
1682}
1683
1684//
1685//  This method is called when we get a notation or enumeration type attribute
1686//  to validate. We have to confirm that the passed value to find is one of
1687//  the values in the passed list. The list is a space separated string of
1688//  values to match against.
1689//
1690bool XMLString::isInList(const XMLCh* const toFind, const XMLCh* const enumList)
1691{
1692        //
1693        //  We loop through the values in the list via this outer loop. We end
1694        //  when we hit the end of the enum list or get a match.
1695        //
1696        const XMLCh* listPtr = enumList;
1697        const XMLSize_t findLen = XMLString::stringLen(toFind);
1698        while (*listPtr)
1699        {
1700                XMLSize_t testInd;
1701                for (testInd = 0; testInd < findLen; testInd++)
1702                {
1703                        //
1704                        //  If they don't match, then reset and try again. Note that
1705                        //  hitting the end of the current item will cause a mismatch
1706                        //  because there can be no spaces in the toFind string.
1707                        //
1708                        if (listPtr[testInd] != toFind[testInd])
1709                                break;
1710                }
1711
1712                //
1713                //  If we went the distance, see if we matched. If we did, the current
1714                //  list character has to be null or space.
1715                //
1716                if (testInd == findLen)
1717                {
1718                        if ((listPtr[testInd] == chSpace) || !listPtr[testInd])
1719                                return true;
1720                }
1721
1722                // Run the list pointer up to the next substring
1723                while ((*listPtr != chSpace) && *listPtr)
1724                        listPtr++;
1725
1726                // If we hit the end, then we failed
1727                if (!*listPtr)
1728                        return false;
1729
1730                // Else move past the space and try again
1731                listPtr++;
1732        }
1733
1734        // We never found it
1735        return false;
1736}
1737
1738//
1739// a string is whitespace:replaced, is having no
1740//    #xD  Carriage Return
1741//    #xA  Line Feed
1742//    #x9  TAB
1743//
1744bool XMLString::isWSReplaced(const XMLCh* const toCheck)
1745{
1746        // If no string, then its a OK
1747        if (( !toCheck ) || ( !*toCheck ))
1748                return true;
1749
1750        const XMLCh* startPtr = toCheck;
1751        while ( *startPtr )
1752        {
1753                if ( ( *startPtr == chCR) ||
1754                         ( *startPtr == chLF) ||
1755                         ( *startPtr == chHTab))
1756                return false;
1757
1758                startPtr++;
1759        }
1760
1761        return true;
1762}
1763
1764//
1765//   to replace characters listed below to #x20
1766//    #xD  Carriage Return
1767//    #xA  Line Feed
1768//    #x9  TAB
1769//
1770void XMLString::replaceWS(XMLCh* toConvert, MemoryManager* const)
1771{
1772        // If no string, then its a OK
1773        if (( !toConvert ) || ( !*toConvert ))
1774                return;
1775
1776        XMLCh* cursorPtr = toConvert;
1777        while ( *cursorPtr )
1778        {
1779                if ( ( *cursorPtr == chCR) ||
1780                         ( *cursorPtr == chLF) ||
1781                         ( *cursorPtr == chHTab))
1782                        *cursorPtr = chSpace;
1783
1784                cursorPtr++;
1785        }
1786}
1787
1788//
1789// a string is whitespace:collapsed, is whitespace::replaced
1790// and no
1791//    leading space (#x20)
1792//    trailing space
1793//    no contiguous sequences of spaces
1794//
1795bool XMLString::isWSCollapsed(const XMLCh* const toCheck)
1796{
1797        if (( !toCheck ) || ( !*toCheck ))
1798                return true;
1799
1800        // shall be whitespace::replaced first
1801        if ( !isWSReplaced(toCheck) )
1802                return false;
1803
1804        // no leading or trailing space
1805        if ((*toCheck == chSpace) ||
1806                (toCheck[XMLString::stringLen(toCheck)-1] == chSpace))
1807                return false;
1808
1809        const XMLCh* startPtr = toCheck;
1810        XMLCh theChar;
1811        bool  inSpace = false;
1812        while ( (theChar = *startPtr) != 0 )
1813        {
1814                if ( theChar == chSpace)
1815                {
1816                        if (inSpace)
1817                                return false;
1818                        else
1819                                inSpace = true;
1820                }
1821                else
1822                        inSpace = false;
1823
1824                startPtr++;
1825
1826        }
1827
1828        return true;
1829}
1830
1831//
1832// no leading and/or trailing spaces
1833// no continuous sequences of spaces
1834//
1835void XMLString::collapseWS( XMLCh* toConvert
1836                                                  , MemoryManager* const  manager)
1837{
1838        // If no string, then its a failure
1839        if (( !toConvert ) || ( !*toConvert ))
1840                return;
1841
1842        // replace whitespace first
1843        if (!isWSReplaced(toConvert))
1844                replaceWS(toConvert, manager);
1845
1846        // remove leading spaces
1847        XMLCh* startPtr = toConvert;
1848        while ( *startPtr == chSpace )
1849                startPtr++;
1850
1851        if (!*startPtr)
1852        {
1853                *toConvert = chNull;
1854                return;
1855        }
1856
1857        // remove trailing spaces
1858        XMLCh* endPtr = toConvert + stringLen(toConvert);
1859        while (*(endPtr - 1) == chSpace)
1860                endPtr--;
1861        *endPtr = chNull;
1862
1863        // move data to beginning only if there were spaces in front
1864        if (startPtr != toConvert)
1865                XMLString::moveChars(toConvert, startPtr, endPtr - startPtr + 1);
1866
1867        if (!isWSCollapsed(toConvert))
1868        {
1869                //
1870                //  Work through what remains and chop continuous spaces
1871                //
1872                XMLCh* retPtr = toConvert;
1873                startPtr = toConvert;
1874                bool inSpace = false;
1875                while (*startPtr)
1876                {
1877                        if ( *startPtr == chSpace)
1878                        {
1879                                // copy a single space, then ignore subsequent
1880                                if (!inSpace)
1881                                {
1882                                        inSpace = true;
1883                                        *retPtr++ = chSpace;
1884                                }
1885                        }
1886                        else
1887                        {
1888                                inSpace = false;
1889                                *retPtr++ = *startPtr;
1890                        }
1891
1892                        startPtr++;
1893                }
1894
1895                *retPtr = chNull;
1896        }
1897}
1898
1899//
1900// remove whitespace
1901//
1902void XMLString::removeWS(XMLCh* toConvert, MemoryManager* const)
1903{
1904        // If no string, then its a failure
1905        if (( !toConvert ) || ( !*toConvert ))
1906                return;
1907
1908        XMLCh* retPtr = toConvert;
1909        XMLCh* startPtr = toConvert;
1910
1911        while (*startPtr)
1912        {
1913                if ( ( *startPtr != chCR)    &&
1914                         ( *startPtr != chLF)    &&
1915                         ( *startPtr != chHTab)  &&
1916                         ( *startPtr != chSpace)  )
1917                {
1918                        *retPtr++ = *startPtr;
1919                }
1920
1921                startPtr++;
1922        }
1923
1924        *retPtr = chNull;
1925}
1926
1927void XMLString::removeChar(const XMLCh*     const srcString
1928                                                 , const XMLCh&           toRemove
1929                                                 ,       XMLBuffer&       dstBuffer)
1930{
1931        if(!srcString) return;
1932        const XMLCh* pszSrc = srcString;
1933        XMLCh c;
1934
1935        dstBuffer.reset();
1936
1937        while ((c=*pszSrc++)!=0)
1938        {
1939                if (c != toRemove)
1940                        dstBuffer.append(c);
1941        }
1942}
1943
1944/**
1945 * Fixes a platform dependent absolute path filename to standard URI form.
1946 * 1. Windows: fix 'x:' to 'file:///x:' and convert any backslash to forward slash
1947 * 2. UNIX: fix '/blah/blahblah' to 'file:///blah/blahblah'
1948 */
1949void XMLString::fixURI(const XMLCh* const str, XMLCh* const target)
1950{
1951        if (!str || !*str)
1952                return;
1953
1954        int colonIdx = XMLString::indexOf(str, chColon);
1955
1956        // If starts with a '/' we assume
1957        // this is an absolute (UNIX) file path and prefix it with file://
1958        if (colonIdx == -1 && XMLString::indexOf(str, chForwardSlash) == 0) {
1959                unsigned index = 0;
1960                target[index++] = chLatin_f;
1961                target[index++] = chLatin_i;
1962                target[index++] = chLatin_l;
1963                target[index++] = chLatin_e;
1964                target[index++] = chColon;
1965                target[index++] = chForwardSlash;
1966                target[index++] = chForwardSlash;
1967
1968                // copy the string
1969                const XMLCh* inPtr = str;
1970                while (*inPtr)
1971                        target[index++] = *inPtr++;
1972
1973                target[index] = chNull;
1974        }
1975        else if (colonIdx == 1 && XMLString::isAlpha(*str)) {
1976                // If starts with a driver letter 'x:' we assume
1977                // this is an absolute (Windows) file path and prefix it with file:///
1978                unsigned index = 0;
1979                target[index++] = chLatin_f;
1980                target[index++] = chLatin_i;
1981                target[index++] = chLatin_l;
1982                target[index++] = chLatin_e;
1983                target[index++] = chColon;
1984                target[index++] = chForwardSlash;
1985                target[index++] = chForwardSlash;
1986                target[index++] = chForwardSlash;
1987
1988                // copy the string and fix any backward slash
1989                const XMLCh* inPtr = str;
1990                while (*inPtr) {
1991                        if (*inPtr == chYenSign ||
1992                                *inPtr == chWonSign ||
1993                                *inPtr == chBackSlash)
1994                                target[index++] = chForwardSlash;
1995                        else
1996                                target[index++] = *inPtr;
1997                        inPtr++;
1998                }
1999
2000                // cap it with null
2001                target[index] = chNull;
2002        }
2003        else {
2004                // not specific case, so just copy the string over
2005                copyString(target, str);
2006        }
2007}
2008
2009void XMLString::release(char** buf, MemoryManager* const manager)
2010{
2011                manager->deallocate(*buf);
2012                *buf = 0;
2013}
2014
2015void XMLString::release(XMLCh** buf, MemoryManager* const manager)
2016{
2017                manager->deallocate(*buf);
2018                *buf = 0;
2019}
2020
2021// ---------------------------------------------------------------------------
2022//  XMLString: Private static methods
2023// ---------------------------------------------------------------------------
2024void XMLString::initString(XMLLCPTranscoder* const defToUse,
2025                                                   MemoryManager* const manager)
2026{
2027        // Store away the default transcoder that we are to use
2028        gTranscoder = defToUse;
2029
2030        // Store memory manager
2031        fgMemoryManager = manager;
2032}
2033
2034void XMLString::termString()
2035{
2036        // Just clean up our local code page transcoder
2037        delete gTranscoder;
2038        gTranscoder = 0;
2039
2040        // reset memory manager
2041        fgMemoryManager = 0;
2042}
2043
2044XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.