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

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

Initial check-in of icXML 0.8 source files

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