source: icXML/icXML-devel/src/xercesc/framework/XMLFormatter.cpp @ 2722

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

Original Xerces files with import mods for icxercesc

File size: 22.3 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: XMLFormatter.cpp 901107 2010-01-20 08:45:02Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <icxercesc/util/PlatformUtils.hpp>
27#include <xercesc/util/XMLUniDefs.hpp>
28#include <icxercesc/util/XMLString.hpp>
29#include <icxercesc/util/TransService.hpp>
30#include <xercesc/util/TranscodingException.hpp>
31#include <xercesc/util/XMLExceptMsgs.hpp>
32#include <xercesc/framework/XMLFormatter.hpp>
33#include <xercesc/util/Janitor.hpp>
34#include <xercesc/util/XMLChar.hpp>
35
36#include <string.h>
37
38XERCES_CPP_NAMESPACE_BEGIN
39
40// ---------------------------------------------------------------------------
41//  Local data
42//
43//  gXXXRef
44//      These are hard coded versions of the char refs we put out for the
45//      standard char refs.
46//
47//  gEscapeChars
48//      For each style of escape, we have a list of the chars that must
49//      be escaped for that style. The first null hit in each list indicates
50//      no more valid entries in that list. The first entry is a dummy for
51//      the NoEscapes style.
52// ---------------------------------------------------------------------------
53static const XMLCh  gAmpRef[] =
54{
55    chAmpersand, chLatin_a, chLatin_m, chLatin_p, chSemiColon, chNull
56};
57
58static const XMLCh  gAposRef[] =
59{
60    chAmpersand, chLatin_a, chLatin_p, chLatin_o, chLatin_s, chSemiColon, chNull
61};
62
63static const XMLCh  gGTRef[] =
64{
65    chAmpersand, chLatin_g, chLatin_t, chSemiColon, chNull
66};
67
68static const XMLCh  gLTRef[] =
69{
70    chAmpersand, chLatin_l, chLatin_t, chSemiColon, chNull
71};
72
73static const XMLCh  gQuoteRef[] =
74{
75    chAmpersand, chLatin_q, chLatin_u, chLatin_o, chLatin_t, chSemiColon, chNull
76};
77
78static const unsigned int kEscapeCount = 7;
79static const XMLCh gEscapeChars[XMLFormatter::EscapeFlags_Count][kEscapeCount] =
80{
81        { chNull      , chNull       , chNull        , chNull       , chNull        , chNull    , chNull }
82    ,   { chAmpersand , chCloseAngle , chDoubleQuote , chOpenAngle  , chSingleQuote , chNull    , chNull }
83    ,   { chAmpersand , chOpenAngle  , chDoubleQuote , chLF         , chCR          , chHTab    , chNull }
84    ,   { chAmpersand , chOpenAngle  , chCloseAngle  , chNull       , chNull        , chNull    , chNull }
85};
86
87// ---------------------------------------------------------------------------
88//  Local methods
89// ---------------------------------------------------------------------------
90bool XMLFormatter::inEscapeList(const XMLFormatter::EscapeFlags escStyle
91                              , const XMLCh                     toCheck)
92{
93    const XMLCh* escList = gEscapeChars[escStyle];
94    while (*escList)
95    {
96        if (*escList++ == toCheck)
97            return true;
98    }
99
100    /***
101     *  XML1.1
102     *
103     *  Finally, there is considerable demand to define a standard representation of
104     *  arbitrary Unicode characters in XML documents. Therefore, XML 1.1 allows the
105     *  use of character references to the control characters #x1 through #x1F,
106     *  most of which are forbidden in XML 1.0. For reasons of robustness, however,
107     *  these characters still cannot be used directly in documents.
108     *  In order to improve the robustness of character encoding detection, the
109     *  additional control characters #x7F through #x9F, which were freely allowed in
110     *  XML 1.0 documents, now must also appear only as character references.
111     *  (Whitespace characters are of course exempt.) The minor sacrifice of backward
112     *  compatibility is considered not significant.
113     *  Due to potential problems with APIs, #x0 is still forbidden both directly and
114     *  as a character reference.
115     *
116    ***/
117    if (fIsXML11)
118    {
119        // for XML11
120        if ( XMLChar1_1::isControlChar(toCheck, 0) &&
121            !XMLChar1_1::isWhitespace(toCheck, 0)   )
122        {
123            return true;
124        }
125        else
126        {
127            return false;
128        }
129    }
130    else
131    {
132        return false;
133    }
134
135}
136
137
138// ---------------------------------------------------------------------------
139//  XMLFormatter: Constructors and Destructor
140// ---------------------------------------------------------------------------
141XMLFormatter::XMLFormatter( const   char* const             outEncoding
142                            , const char* const             docVersion
143                            ,       XMLFormatTarget* const  target
144                            , const EscapeFlags             escapeFlags
145                            , const UnRepFlags              unrepFlags
146                            ,       MemoryManager* const    manager)
147    : fEscapeFlags(escapeFlags)
148    , fOutEncoding(0)
149    , fTarget(target)
150    , fUnRepFlags(unrepFlags)
151    , fXCoder(0)
152    , fAposRef(0)
153    , fAposLen(0)
154    , fAmpRef(0)
155    , fAmpLen(0)
156    , fGTRef(0)
157    , fGTLen(0)
158    , fLTRef(0)
159    , fLTLen(0)
160    , fQuoteRef(0)
161    , fQuoteLen(0)
162    , fIsXML11(false)
163    , fMemoryManager(manager)
164{
165    // Transcode the encoding string
166    fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager);
167
168    // Try to create a transcoder for this encoding
169    XMLTransService::Codes resCode;
170    fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
171    (
172        fOutEncoding
173        , resCode
174        , kTmpBufSize
175        , fMemoryManager
176    );
177
178    if (!fXCoder)
179    {
180        fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding;
181        ThrowXMLwithMemMgr1
182        (
183            TranscodingException
184            , XMLExcepts::Trans_CantCreateCvtrFor
185            , outEncoding
186            , fMemoryManager
187        );
188    }
189
190    XMLCh* const tmpDocVer = XMLString::transcode(docVersion, fMemoryManager);
191    ArrayJanitor<XMLCh> jname(tmpDocVer, fMemoryManager);
192    fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1);
193}
194
195
196XMLFormatter::XMLFormatter( const   XMLCh* const            outEncoding
197                            , const XMLCh* const            docVersion
198                            ,       XMLFormatTarget* const  target
199                            , const EscapeFlags             escapeFlags
200                            , const UnRepFlags              unrepFlags
201                            ,       MemoryManager* const    manager)
202    : fEscapeFlags(escapeFlags)
203    , fOutEncoding(0)
204    , fTarget(target)
205    , fUnRepFlags(unrepFlags)
206    , fXCoder(0)
207    , fAposRef(0)
208    , fAposLen(0)
209    , fAmpRef(0)
210    , fAmpLen(0)
211    , fGTRef(0)
212    , fGTLen(0)
213    , fLTRef(0)
214    , fLTLen(0)
215    , fQuoteRef(0)
216    , fQuoteLen(0)
217    , fIsXML11(false)
218    , fMemoryManager(manager)
219{
220    // Try to create a transcoder for this encoding
221    XMLTransService::Codes resCode;
222    fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
223    (
224        outEncoding
225        , resCode
226        , kTmpBufSize
227        , fMemoryManager
228    );
229
230    if (!fXCoder)
231    {
232        ThrowXMLwithMemMgr1
233        (
234            TranscodingException
235            , XMLExcepts::Trans_CantCreateCvtrFor
236            , outEncoding
237            , fMemoryManager
238        );
239    }
240
241    // Copy the encoding string
242    fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager);
243
244
245    fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1);
246}
247
248XMLFormatter::XMLFormatter( const   char* const             outEncoding
249                            ,       XMLFormatTarget* const  target
250                            , const EscapeFlags             escapeFlags
251                            , const UnRepFlags              unrepFlags
252                            ,       MemoryManager* const    manager)
253    : fEscapeFlags(escapeFlags)
254    , fOutEncoding(0)
255    , fTarget(target)
256    , fUnRepFlags(unrepFlags)
257    , fXCoder(0)
258    , fAposRef(0)
259    , fAposLen(0)
260    , fAmpRef(0)
261    , fAmpLen(0)
262    , fGTRef(0)
263    , fGTLen(0)
264    , fLTRef(0)
265    , fLTLen(0)
266    , fQuoteRef(0)
267    , fQuoteLen(0)
268    , fIsXML11(false)
269    , fMemoryManager(manager)
270{
271    // this constructor uses "1.0" for the docVersion
272
273    // Transcode the encoding string
274    fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager);
275
276    // Try to create a transcoder for this encoding
277    XMLTransService::Codes resCode;
278    fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
279    (
280        fOutEncoding
281        , resCode
282        , kTmpBufSize
283        , fMemoryManager
284    );
285
286    if (!fXCoder)
287    {
288        fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding;
289        ThrowXMLwithMemMgr1
290        (
291            TranscodingException
292            , XMLExcepts::Trans_CantCreateCvtrFor
293            , outEncoding
294            , fMemoryManager
295        );
296    }
297
298    //XMLCh* const tmpDocVer = XMLString::transcode("1.0", fMemoryManager);
299    //ArrayJanitor<XMLCh> jname(tmpDocVer, fMemoryManager);
300    //fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1);
301    fIsXML11 = false;  // docVersion 1.0 is not 1.1!
302}
303
304
305XMLFormatter::XMLFormatter( const   XMLCh* const            outEncoding
306                            ,       XMLFormatTarget* const  target
307                            , const EscapeFlags             escapeFlags
308                            , const UnRepFlags              unrepFlags
309                            ,       MemoryManager* const    manager)
310    : fEscapeFlags(escapeFlags)
311    , fOutEncoding(0)
312    , fTarget(target)
313    , fUnRepFlags(unrepFlags)
314    , fXCoder(0)
315    , fAposRef(0)
316    , fAposLen(0)
317    , fAmpRef(0)
318    , fAmpLen(0)
319    , fGTRef(0)
320    , fGTLen(0)
321    , fLTRef(0)
322    , fLTLen(0)
323    , fQuoteRef(0)
324    , fQuoteLen(0)
325    , fIsXML11(false)
326    , fMemoryManager(manager)
327{
328    // this constructor uses XMLUni::fgVersion1_0 for the docVersion
329
330    // Try to create a transcoder for this encoding
331    XMLTransService::Codes resCode;
332    fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
333    (
334        outEncoding
335        , resCode
336        , kTmpBufSize
337        , fMemoryManager
338    );
339
340    if (!fXCoder)
341    {
342        ThrowXMLwithMemMgr1
343        (
344            TranscodingException
345            , XMLExcepts::Trans_CantCreateCvtrFor
346            , outEncoding
347            , fMemoryManager
348        );
349    }
350
351    // Copy the encoding string
352    fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager);
353
354    //fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1);
355    fIsXML11 = false;  // docVersion 1.0 is not 1.1!
356}
357
358XMLFormatter::~XMLFormatter()
359{
360    fMemoryManager->deallocate(fAposRef); //delete [] fAposRef;
361    fMemoryManager->deallocate(fAmpRef); //delete [] fAmpRef;
362    fMemoryManager->deallocate(fGTRef); //delete [] fGTRef;
363    fMemoryManager->deallocate(fLTRef); //delete [] fLTRef;
364    fMemoryManager->deallocate(fQuoteRef); //delete [] fQuoteRef;
365    fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding;
366    delete fXCoder;
367
368    // We DO NOT own the target object!
369}
370
371
372// ---------------------------------------------------------------------------
373//  XMLFormatter: Formatting methods
374// ---------------------------------------------------------------------------
375void
376XMLFormatter::formatBuf(const   XMLCh* const    toFormat
377                        , const XMLSize_t       count
378                        , const EscapeFlags     escapeFlags
379                        , const UnRepFlags      unrepFlags)
380{
381    //
382    //  Figure out the actual escape flag value. If the parameter is not
383    //  the default, then take it. Else take the current default.
384    //
385    const EscapeFlags actualEsc = (escapeFlags == DefaultEscape)
386                                ? fEscapeFlags : escapeFlags;
387
388    // And do the same for the unrep flags
389    const UnRepFlags  actualUnRep = (unrepFlags == DefaultUnRep)
390                                    ? fUnRepFlags : unrepFlags;
391
392    //
393    //  If the actual unrep action is that they want to provide char refs
394    //  for unrepresentable chars, then this one is a much more difficult
395    //  one to do cleanly, and we handle it separately.
396    //
397    if (actualUnRep == UnRep_CharRef)
398    {
399        specialFormat(toFormat, count, actualEsc);
400        return;
401    }
402
403    //
404    //  If we don't have any escape flags set, then we can do the most
405    //  efficient loop, else we have to do it the hard way.
406    //
407    const XMLCh*    srcPtr = toFormat;
408    const XMLCh*    endPtr = toFormat + count;
409    if (actualEsc == NoEscapes)
410    {
411        //
412        //  Just do a whole buffer at a time into the temp buffer, cap
413        //  it off, and send it to the target.
414        //
415        if (srcPtr < endPtr)
416           srcPtr += handleUnEscapedChars(srcPtr, endPtr - srcPtr, actualUnRep);
417    }
418     else
419    {
420        //
421        //  Escape chars that require it according tot he scale flags
422        //  we were given. For the others, try to accumulate them and
423        //  format them in as big as bulk as we can.
424        //
425        while (srcPtr < endPtr)
426        {
427            //
428            //  Run a temp pointer up until we hit a character that we have
429            //  to escape. Then we can convert all the chars between our
430            //  current source pointer and here all at once.
431            //
432            const XMLCh* tmpPtr = srcPtr;
433            while ((tmpPtr < endPtr) && !inEscapeList(actualEsc, *tmpPtr))
434                tmpPtr++;
435
436            //
437            //  If we got any chars, then lets convert them and write them
438            //  out.
439            //
440            if (tmpPtr > srcPtr)
441               srcPtr += handleUnEscapedChars(srcPtr, tmpPtr - srcPtr,
442                                              actualUnRep);
443
444             else if (tmpPtr < endPtr)
445            {
446                //
447                //  Ok, so we've hit a char that must be escaped. So do
448                //  this one specially.
449                //
450                const XMLByte * theChars;
451                switch (*srcPtr) {
452                    case chAmpersand :
453                        theChars = getCharRef(fAmpLen, fAmpRef, gAmpRef);
454                        fTarget->writeChars(theChars, fAmpLen, this);
455                        break;
456
457                    case chSingleQuote :
458                        theChars = getCharRef(fAposLen, fAposRef, gAposRef);
459                        fTarget->writeChars(theChars, fAposLen, this);
460                        break;
461
462                    case chDoubleQuote :
463                        theChars = getCharRef(fQuoteLen, fQuoteRef, gQuoteRef);
464                        fTarget->writeChars(theChars, fQuoteLen, this);
465                        break;
466
467                    case chCloseAngle :
468                        theChars = getCharRef(fGTLen, fGTRef, gGTRef);
469                        fTarget->writeChars(theChars, fGTLen, this);
470                        break;
471
472                    case chOpenAngle :
473                        theChars = getCharRef(fLTLen, fLTRef, gLTRef);
474                        fTarget->writeChars(theChars, fLTLen, this);
475                        break;
476
477                    default:
478                        // control characters
479                        writeCharRef(*srcPtr);
480                        break;
481                }
482                srcPtr++;
483            }
484        }
485    }
486}
487
488
489XMLSize_t
490XMLFormatter::handleUnEscapedChars(const XMLCh *                  srcPtr,
491                                   const XMLSize_t                oCount,
492                                   const UnRepFlags               actualUnRep)
493{
494   //
495   //  Use that to figure out what I should pass to the transcoder. If we
496   //  are doing character references or failing for unrepresentable chars,
497   //  then we just throw, since we should never get a call for something
498   //  we cannot represent. Else, we tell it to just use the replacement
499   //  char.
500   //
501   const XMLTranscoder::UnRepOpts unRepOpts = (actualUnRep == UnRep_Replace)
502                                             ? XMLTranscoder::UnRep_RepChar
503                                             : XMLTranscoder::UnRep_Throw;
504
505   XMLSize_t charsEaten;
506   XMLSize_t count = oCount;
507
508   while (count) {
509     const XMLSize_t srcChars = (count > XMLSize_t (kTmpBufSize))
510       ? XMLSize_t (kTmpBufSize) : count;
511
512      const XMLSize_t outBytes
513         = fXCoder->transcodeTo(srcPtr, srcChars,
514                                fTmpBuf, kTmpBufSize,
515                                charsEaten, unRepOpts);
516
517      if (outBytes) {
518         fTmpBuf[outBytes]     = 0; fTmpBuf[outBytes + 1] = 0;
519         fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
520         fTarget->writeChars(fTmpBuf, outBytes, this);
521      }
522
523      srcPtr += charsEaten;
524      count  -= charsEaten;
525   }
526
527   return oCount; // This should be an assertion that count == 0.
528}
529
530
531XMLFormatter& XMLFormatter::operator<<(const XMLCh* const toFormat)
532{
533    const XMLSize_t len = XMLString::stringLen(toFormat);
534    formatBuf(toFormat, len);
535    return *this;
536}
537
538XMLFormatter& XMLFormatter::operator<<(const XMLCh toFormat)
539{
540    // Make a temp string format that
541    XMLCh szTmp[2];
542    szTmp[0] = toFormat;
543    szTmp[1] = 0;
544
545    formatBuf(szTmp, 1);
546    return *this;
547}
548
549/**
550 * the parameter, count, is needed since stringLen()
551 * does not work on a BOM like "0xFE0xFF0x000x00" or
552 * "0x000x000xFF0xFE"
553 **/
554void XMLFormatter::writeBOM(const XMLByte* const toFormat
555                          , const XMLSize_t      count)
556{
557    fTarget->writeChars(toFormat, count, this);
558}
559
560// ---------------------------------------------------------------------------
561//  XMLFormatter: Private helper methods
562// ---------------------------------------------------------------------------
563void XMLFormatter::writeCharRef(const XMLCh &toWrite)
564{
565    XMLCh tmpBuf[32];
566    tmpBuf[0] = chAmpersand;
567    tmpBuf[1] = chPound;
568    tmpBuf[2] = chLatin_x;
569
570    // Build a char ref for the current char
571    XMLString::binToText(toWrite, &tmpBuf[3], 8, 16, fMemoryManager);
572    const XMLSize_t bufLen = XMLString::stringLen(tmpBuf);
573    tmpBuf[bufLen] = chSemiColon;
574    tmpBuf[bufLen+1] = chNull;
575
576    // write it out
577    formatBuf(tmpBuf
578            , bufLen + 1
579            , XMLFormatter::NoEscapes
580            , XMLFormatter::UnRep_Fail);
581
582}
583
584void XMLFormatter::writeCharRef(XMLSize_t toWrite)
585{
586    XMLCh tmpBuf[64];
587    tmpBuf[0] = chAmpersand;
588    tmpBuf[1] = chPound;
589    tmpBuf[2] = chLatin_x;
590
591    // Build a char ref for the current char
592    XMLString::sizeToText(toWrite, &tmpBuf[3], 32, 16, fMemoryManager);
593    const XMLSize_t bufLen = XMLString::stringLen(tmpBuf);
594    tmpBuf[bufLen] = chSemiColon;
595    tmpBuf[bufLen+1] = chNull;
596
597    // write it out
598    formatBuf(tmpBuf
599            , bufLen + 1
600            , XMLFormatter::NoEscapes
601            , XMLFormatter::UnRep_Fail);
602
603}
604
605
606const XMLByte* XMLFormatter::getCharRef(XMLSize_t     &count,
607                                        XMLByte*      &ref,
608                                        const XMLCh *  stdRef)
609{
610   if (!ref) {
611
612       XMLSize_t charsEaten;
613       const XMLSize_t outBytes =
614           fXCoder->transcodeTo(stdRef, XMLString::stringLen(stdRef),
615                                fTmpBuf, kTmpBufSize, charsEaten,
616                                XMLTranscoder::UnRep_Throw);
617
618       fTmpBuf[outBytes] = 0;
619       fTmpBuf[outBytes + 1] = 0;
620       fTmpBuf[outBytes + 2] = 0;
621       fTmpBuf[outBytes + 3] = 0;
622
623       ref = (XMLByte*) fMemoryManager->allocate
624       (
625           (outBytes + 4) * sizeof(XMLByte)
626       );//new XMLByte[outBytes + 4];
627       memcpy(ref, fTmpBuf, outBytes + 4);
628       count = outBytes;
629   }
630
631   return ref;
632}
633
634void XMLFormatter::specialFormat(const  XMLCh* const    toFormat
635                                , const XMLSize_t       count
636                                , const EscapeFlags     escapeFlags)
637{
638    //
639    //  We have to check each character and see if it could be represented.
640    //  As long as it can, we just keep up with where we started and how
641    //  many chars we've checked. When we hit an unrepresentable one, we
642    //  stop, transcode everything we've collected, then start handling
643    //  the unrepresentables via char refs. We repeat this until we get all
644    //  the chars done.
645    //
646    const XMLCh*    srcPtr = toFormat;
647    const XMLCh*    endPtr = toFormat + count;
648
649    while (srcPtr < endPtr)
650    {
651        const XMLCh* tmpPtr = srcPtr;
652        while (tmpPtr < endPtr)
653        {
654            if (fXCoder->canTranscodeTo(*tmpPtr))
655                tmpPtr++;
656            else
657                break;
658        }
659
660        if (tmpPtr > srcPtr)
661        {
662            // We got at least some chars that can be done normally
663            formatBuf
664            (
665                srcPtr
666                , tmpPtr - srcPtr
667                , escapeFlags
668                , XMLFormatter::UnRep_Fail
669            );
670
671            // Update the source pointer to our new spot
672            srcPtr = tmpPtr;
673        }
674         else
675        {
676
677            //  We hit something unrepresentable. So continue forward doing
678            //  char refs until we hit something representable again or the
679            //  end of input.
680            //
681            while (srcPtr < endPtr)
682            {
683                if ((*srcPtr & 0xFC00) == 0xD800) {
684                    // we have encountered a surrogate, need to recombine before printing out
685                    // use writeCharRef that takes XMLSize_t to get values larger than
686                    // hex 0xFFFF printed.
687                    tmpPtr = srcPtr;
688                    tmpPtr++; // point at low surrogate
689                    writeCharRef((XMLSize_t) (0x10000+((*srcPtr-0xD800)<<10)+*tmpPtr-0xDC00));
690                    srcPtr++; // advance to low surrogate (will advance again below)
691                }
692                else {
693                    writeCharRef(*srcPtr);
694                }
695
696                // Move up the source pointer and break out if needed
697                srcPtr++;
698                if (fXCoder->canTranscodeTo(*srcPtr))
699                    break;
700            }
701        }
702    }
703}
704
705XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.