source: icXML/icXML-devel/src/icxercesc/internal/XMLReader.cpp

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

Changes to icxercesc files

File size: 47.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: XMLReader.cpp 901280 2010-01-20 17:06:14Z johns $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <icxercesc/internal/XMLReader.hpp>
26#include <xercesc/util/BitOps.hpp>
27#include <xercesc/util/BinInputStream.hpp>
28#include <icxercesc/util/PlatformUtils.hpp>
29#include <xercesc/util/RuntimeException.hpp>
30#include <icxercesc/util/TransService.hpp>
31#include <xercesc/util/XMLEBCDICTranscoder.hpp>
32#include <icxercesc/util/XMLString.hpp>
33#include <xercesc/util/Janitor.hpp>
34#include <icxercesc/util/XMLUTF8Transcoder.hpp>
35#include <icxercesc/util/XMLUTF16Transcoder.hpp>
36#include <icxmlc/XMLUTF8CharacterSetAdapter.hpp>
37#include <icxmlc/XMLUTF16CharacterSetAdapter.hpp>
38#include <icxmlc/XMLDefaultCharacterSetAdapter.hpp>
39#include <icxmlc/XMLNameChars.hpp>
40#include <icxmlc/XMLWhitespaceNormalizer.hpp>
41#include <icxmlc/XMLParser.hpp>
42
43XERCES_CPP_NAMESPACE_BEGIN
44
45//
46//  This one is not called terribly often, so call the XMLChar utility
47//
48bool XMLReader::isPublicIdChar(const XMLCh toCheck) const
49{
50        if (fXMLVersion == XMLV1_1)
51                return XMLChar1_1::isPublicIdChar(toCheck);
52        else
53                return XMLChar1_0::isPublicIdChar(toCheck);
54}
55
56// ---------------------------------------------------------------------------
57//  XMLReader: Constructors and Destructor
58// ---------------------------------------------------------------------------
59XMLReader::XMLReader(const  XMLCh* const          pubId
60                                        , const XMLCh* const          sysId
61                                        ,       BinInputStream* const streamToAdopt
62                                        , const RefFrom               from
63                                        , const Types                 type
64                                        , const Sources               source
65                                        , const bool                  throwAtEnd
66                                        , const bool                  /* calculateSrcOfs */
67                                        ,       XMLSize_t
68                                        , const XMLVersion            version
69                                        ,       MemoryManager* const  manager) :
70        fCharIndex(0)
71        , fCharsAvail(0)
72        , fCurCol(1)
73        , fCurLine(1)
74        , fEncodingStr(0)
75        , fForcedEncoding(false)
76    , fNoMore(false)
77    , fEOF(false)
78        , fPublicId(XMLString::replicate(pubId, manager))
79        , fRawBufIndex(0)
80        , fRawBytesAvail(0)
81        , fRawBytesRead(0)
82        , fReaderNum(0xFFFFFFFF)
83        , fRefFrom(from)
84        , fSource(source)
85        , fSrcOfsBase(0)
86        , fSystemId(XMLString::replicate(sysId, manager))
87        , fStream(streamToAdopt)
88        , fSwapped(false)
89        , fThrowAtEnd(throwAtEnd)
90        , fTranscoder(0)
91        , fCharacterSetAdapter(0)
92        , fType(type)
93    , fParser(0)
94        , fMemoryManager(manager)
95{
96        // Do an initial load of raw bytes
97        refreshRawBuffer(0);
98
99        setXMLVersion(version);
100
101        //
102        //  Use the recognizer class to get a basic sense of what family of
103        //  encodings this file is in. We'll start off with a reader of that
104        //  type, and update it later if needed when we read the XMLDecl line.
105        //
106        fEncoding = XMLRecognizer::basicEncodingProbe(fRawByteBuf, fRawBytesAvail);
107
108        fEncodingStr = XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager);
109
110        // Check whether the fSwapped flag should be set or not
111        fSwapped = XMLRecognizer::isSwapped(fEncoding);
112
113        //
114        //  This will check to see if the first line is an XMLDecl and, if
115        //  so, decode that first line manually one character at a time. This
116        //  leaves enough characters in the buffer that the high level code
117        //  can get through the Decl and call us back with the real encoding.
118        //
119        doInitDecode();
120
121        //
122        //  NOTE: We won't create a transcoder until we either get a call to
123        //  setEncoding() or we get a call to refreshCharBuffer() and no
124        //  transcoder has been set yet.
125        //
126}
127
128
129XMLReader::XMLReader(const  XMLCh* const          pubId
130                                        , const XMLCh* const          sysId
131                                        ,       BinInputStream* const streamToAdopt
132                                        , const XMLCh* const          encodingStr
133                                        , const RefFrom               from
134                                        , const Types                 type
135                                        , const Sources               source
136                                        , const bool                  throwAtEnd
137                                        , const bool                  /* calculateSrcOfs */
138                                        ,       XMLSize_t
139                                        , const XMLVersion            version
140                                        ,       MemoryManager* const  manager) :
141        fCharIndex(0)
142        , fCharsAvail(0)
143        , fCurCol(1)
144        , fCurLine(1)
145        , fEncoding(XMLRecognizer::UTF_8)
146        , fEncodingStr(0)
147        , fForcedEncoding(true)
148        , fNoMore(false)
149    , fEOF(false)
150        , fPublicId(XMLString::replicate(pubId, manager))
151        , fRawBufIndex(0)
152        , fRawBytesAvail(0)
153        , fRawBytesRead(0)
154        , fReaderNum(0xFFFFFFFF)
155        , fRefFrom(from)
156        , fSource(source)
157        , fSrcOfsBase(0)
158        , fSystemId(XMLString::replicate(sysId, manager))
159        , fStream(streamToAdopt)
160        , fSwapped(false)
161        , fThrowAtEnd(throwAtEnd)
162        , fTranscoder(0)
163        , fCharacterSetAdapter(0)
164        , fType(type)
165    , fParser(0)
166        , fMemoryManager(manager)
167{
168        setXMLVersion(version);
169
170        // Do an initial load of raw bytes
171        refreshRawBuffer(0);
172
173        // Copy the encoding string to our member
174        /*fEncodingStr = XMLString::replicate(encodingStr, fMemoryManager);
175        XMLString::upperCaseASCII(fEncodingStr);*/
176
177        //
178        //  Map the passed encoding name to one of our enums. If it does not
179        //  match one of the intrinsic encodings, it will come back 'other',
180        //  which tells us to create a transcoder based reader.
181        //
182        fEncoding = XMLRecognizer::encodingForName(encodingStr);
183        fEncodingStr = XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager);
184
185        //  test the presence of the BOM and remove it from the source
186        switch (fEncoding)
187        {
188                case XMLRecognizer::UCS_4B :
189                case XMLRecognizer::UCS_4L :
190                {
191                        if (fRawBytesAvail > 4 &&
192                                (((fRawByteBuf[0] == 0x00) && (fRawByteBuf[1] == 0x00) && (fRawByteBuf[2] == 0xFE) && (fRawByteBuf[3] == 0xFF)) ||
193                                 ((fRawByteBuf[0] == 0xFF) && (fRawByteBuf[1] == 0xFE) && (fRawByteBuf[2] == 0x00) && (fRawByteBuf[3] == 0x00)))  )
194                        {
195                                fRawBufIndex += 4;
196                        }
197                        break;
198                }
199                case XMLRecognizer::UTF_8 :
200                {
201                        // Look at the raw buffer as short chars
202                        const char* asChars = (const char*)fRawByteBuf;
203
204                        if (fRawBytesAvail > XMLRecognizer::fgUTF8BOMLen &&
205                                XMLString::compareNString(  asChars
206                                                                                        , XMLRecognizer::fgUTF8BOM
207                                                                                        , XMLRecognizer::fgUTF8BOMLen) == 0)
208                        {
209                                fRawBufIndex += XMLRecognizer::fgUTF8BOMLen;
210                        }
211                        break;
212                }
213                case XMLRecognizer::UTF_16B :
214                case XMLRecognizer::UTF_16L :
215                {
216                        if (fRawBytesAvail < 2)
217                                break;
218
219                        const UTF16Ch* asUTF16 = (const UTF16Ch*)&fRawByteBuf[fRawBufIndex];
220                        if ((*asUTF16 == chUnicodeMarker) || (*asUTF16 == chSwappedUnicodeMarker))
221                        {
222                                fRawBufIndex += sizeof(UTF16Ch);
223                        }
224                        break;
225                }
226                case XMLRecognizer::EBCDIC:
227                case XMLRecognizer::US_ASCII:
228                case XMLRecognizer::XERCES_XMLCH:
229                case XMLRecognizer::OtherEncoding:
230                case XMLRecognizer::Encodings_Count:
231                {
232                        // silence warning about enumeration not being used
233                        break;
234                }
235        }
236
237        // Check whether the fSwapped flag should be set or not
238        fSwapped = XMLRecognizer::isSwapped(fEncoding);
239
240        constructTranscoder();
241
242        if (!fTranscoder)
243        {
244                // We are about to throw which means the d-tor won't be called.
245                // Clean up some memory.
246                //
247                fMemoryManager->deallocate(fPublicId);
248                fMemoryManager->deallocate(fSystemId);
249                //ArrayJanitor<XMLCh> jan (fEncodingStr, fMemoryManager);
250
251                ThrowXMLwithMemMgr1
252                (
253                        TranscodingException
254                        , XMLExcepts::Trans_CantCreateCvtrFor
255                        , fEncodingStr
256                        , fMemoryManager
257                );
258        }
259
260        //
261        //  Note that, unlike above, we do not do an initial decode of the
262        //  first line. We take the caller's word that the encoding is correct
263        //  and just assume that the first bulk decode (kicked off by the first
264        //  get of a character) will work.
265        //
266        //  So we do here the slipping in of the leading space if required.
267        //
268#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
269        if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral))
270        {
271                // This represents no data from the source
272                fCharSizeBuf[fCharsAvail] = 0;
273                fCharBuf[fCharsAvail++] = chSpace;
274        }
275#endif
276}
277
278
279XMLReader::XMLReader(const  XMLCh* const          pubId
280                                        , const XMLCh* const          sysId
281                                        ,       BinInputStream* const streamToAdopt
282                                        , XMLRecognizer::Encodings    encodingEnum
283                                        , const RefFrom               from
284                                        , const Types                 type
285                                        , const Sources               source
286                                        , const bool                  throwAtEnd
287                                        , const bool                  /* calculateSrcOfs */
288                                        ,       XMLSize_t
289                                        , const XMLVersion            version
290                                        ,       MemoryManager* const  manager) :
291        fCharIndex(0)
292        , fCharsAvail(0)
293        , fCurCol(1)
294        , fCurLine(1)
295        , fEncoding(encodingEnum)
296        , fEncodingStr(0)
297        , fForcedEncoding(true)
298        , fNoMore(false)
299    , fEOF(false)
300        , fPublicId(XMLString::replicate(pubId, manager))
301        , fRawBufIndex(0)
302        , fRawBytesAvail(0)
303        , fRawBytesRead(0)
304        , fReaderNum(0xFFFFFFFF)
305        , fRefFrom(from)
306        , fSource(source)
307        , fSrcOfsBase(0)
308        , fSystemId(XMLString::replicate(sysId, manager))
309        , fStream(streamToAdopt)
310        , fSwapped(false)
311        , fThrowAtEnd(throwAtEnd)
312        , fTranscoder(0)
313        , fCharacterSetAdapter(0)
314        , fType(type)
315    , fParser(0)
316        , fMemoryManager(manager)
317{
318        setXMLVersion(version);
319
320        // Do an initial load of raw bytes
321        refreshRawBuffer(0);
322
323        //
324        //  Use the passed encoding code
325        //
326        fEncodingStr = XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager);
327
328        // Check whether the fSwapped flag should be set or not
329        fSwapped = XMLRecognizer::isSwapped(fEncoding);
330
331        //
332        //  Create a transcoder for the encoding. Since the encoding has been
333        //  forced, this will be the one we will use, period.
334        //
335        constructTranscoder();
336
337        if (!fTranscoder)
338        {
339                // We are about to throw which means the d-tor won't be called.
340                // Clean up some memory.
341                //
342                fMemoryManager->deallocate(fPublicId);
343                fMemoryManager->deallocate(fSystemId);
344                //ArrayJanitor<XMLCh> jan (fEncodingStr, fMemoryManager);
345
346                ThrowXMLwithMemMgr1
347                (
348                        TranscodingException
349                        , XMLExcepts::Trans_CantCreateCvtrFor
350                        , fEncodingStr
351                        , fMemoryManager
352                );
353        }
354
355        //
356        //  Note that, unlike above, we do not do an initial decode of the
357        //  first line. We take the caller's word that the encoding is correct
358        //  and just assume that the first bulk decode (kicked off by the first
359        //  get of a character) will work.
360        //
361        //  So we do here the slipping in of the leading space if required.
362        //
363#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
364        if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral))
365        {
366                // This represents no data from the source
367                fCharSizeBuf[fCharsAvail] = 0;
368                fCharBuf[fCharsAvail++] = chSpace;
369        }
370#endif
371}
372
373
374XMLReader::~XMLReader()
375{
376        fMemoryManager->deallocate(fPublicId);
377        fMemoryManager->deallocate(fSystemId);
378        delete fStream;
379        delete fTranscoder;
380        delete fCharacterSetAdapter;
381    if (unlikely(fEncoding == XMLRecognizer::OtherEncoding))
382    {
383        fMemoryManager->deallocate(const_cast<XMLCh*>(fEncodingStr));
384    }
385}
386
387// ---------------------------------------------------------------------------
388//  XMLReader: Character buffer management methods
389// ---------------------------------------------------------------------------
390XMLFilePos XMLReader::getSrcOffset() const
391{
392        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Reader_SrcOfsNotSupported, fMemoryManager);
393}
394
395// ---------------------------------------------------------------------------
396//  XMLReader: Setter methods (most are inlined)
397// ---------------------------------------------------------------------------
398bool XMLReader::setEncoding(const XMLCh* const newEncoding)
399{
400        //
401        //  If the encoding was forced, then we ignore the new value and just
402        //  return with success. If it was forced, then we are to use that
403        //  encoding without question. Note that, if we are forced, we created
404        //  a transcoder up front so there is no need to do one here in that
405        //  case.
406        //
407        if (fForcedEncoding)
408                return true;
409
410    if (unlikely(fEncoding == XMLRecognizer::OtherEncoding))
411    {
412        fMemoryManager->deallocate(const_cast<XMLCh*>(fEncodingStr));
413    }
414
415        //
416        // upperCase the newEncoding first for better performance
417        //
418    XMLCh * inputEncoding = XMLString::replicate(newEncoding, fMemoryManager);
419    XMLString::upperCaseASCII(inputEncoding);
420        XMLRecognizer::Encodings newBaseEncoding;
421
422        //
423        //  Check for non-endian specific UTF-16 or UCS-4. If so, and if we
424        //  are already in one of the endian versions of those encodings,
425        //  then just keep it and go on. Otherwise, its not valid.
426        //
427        if (XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString)
428        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString2)
429        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString3)
430        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString4)
431        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString5)
432        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString6)
433        ||  XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString7))
434        {
435                fMemoryManager->deallocate(inputEncoding);
436
437                if ((fEncoding != XMLRecognizer::UTF_16L) && (fEncoding != XMLRecognizer::UTF_16B))
438                {
439                        return false;
440                }
441
442                // Override with the original endian specific encoding
443                if (fEncoding == XMLRecognizer::UTF_16L)
444                {
445                        fEncodingStr = XMLUni::fgUTF16LEncodingString;
446                }
447                else
448                {
449                        fEncodingStr = XMLUni::fgUTF16BEncodingString;
450                }
451        }
452        else if (XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString)
453                 ||  XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString2)
454                 ||  XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString3)
455                 ||  XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString4)
456                 ||  XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString5))
457        {
458                fMemoryManager->deallocate(inputEncoding);
459                if ((fEncoding != XMLRecognizer::UCS_4L) && (fEncoding != XMLRecognizer::UCS_4B))
460                {
461                        return false;
462                }
463
464                // Override with the original endian specific encoding
465                if (fEncoding == XMLRecognizer::UCS_4L)
466                {
467                        fEncodingStr = XMLUni::fgUCS4LEncodingString;
468                }
469                else
470                {
471                        fEncodingStr = XMLUni::fgUCS4BEncodingString;
472                }
473        }
474        else
475        {
476                //
477                //  Try to map the string to one of our standard encodings. If its not
478                //  one of them, then it has to be one of the non-intrinsic encodings,
479                //  in which case we have to delete our intrinsic encoder and create a
480                //  new one.
481                //
482        fEncoding = XMLRecognizer::encodingForName(inputEncoding);
483                //
484                //  If it does not come back as one of the auto-sensed encodings, then we
485                //  have to possibly replace it and at least check a few things.
486                //
487                if (fEncoding == XMLRecognizer::OtherEncoding)
488                {
489            fEncodingStr = inputEncoding;
490                        // Replace the default UTF-8 transcoder that was
491                        // installed based on the initial basicEncodingProbe.
492                        XMLTransService::Codes failReason;
493                        fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
494                        (
495                                fEncodingStr
496                                , failReason
497                                , kCharBufSize
498                                , fMemoryManager
499                        );
500                }
501        else
502        {
503            fMemoryManager->deallocate(inputEncoding);
504            fEncodingStr = XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager);
505        }
506        }
507
508        //
509        //  Now we can create a transcoder using the recognized fEncoding.  We
510        //  might get back a transcoder for an intrinsically supported encoding,
511        //  or we might get one from the underlying transcoding service.
512        //
513        constructTranscoder();
514
515        if (!fTranscoder)
516                ThrowXMLwithMemMgr1(TranscodingException, XMLExcepts::Trans_CantCreateCvtrFor, fEncodingStr, fMemoryManager);
517
518        // Looks ok to us
519        return true;
520}
521
522// ---------------------------------------------------------------------------
523//  XMLReader: Construct Transcoder and Character Set Adapter methods
524// ---------------------------------------------------------------------------
525
526bool XMLReader::constructTranscoder()
527{
528        delete fTranscoder;
529
530        //
531        //  Create a transcoder for the encoding. Since the encoding has been
532        //  forced, this will be the one we will use, period.
533        //
534        XMLTransService::Codes failReason;
535        if (fEncoding == XMLRecognizer::OtherEncoding)
536        {
537                //
538                //  fEncodingStr not  pre-recognized, use it
539                //  directly for transcoder
540                //
541                fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
542                (
543                        fEncodingStr
544                        , failReason
545                        , kCharBufSize
546                        , fMemoryManager
547                );             
548        }
549        else
550        {
551                //
552                //  Use the recognized fEncoding to create the transcoder
553                //
554                fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
555                (
556                        fEncoding
557                        , failReason
558                        , kCharBufSize
559                        , fMemoryManager
560                );
561        }
562
563    return (fTranscoder != 0);
564}
565
566bool XMLReader::constructCharacterSetAdapter()
567{
568        delete fCharacterSetAdapter;
569
570        switch (fEncoding)
571        {
572                case XMLRecognizer::US_ASCII:
573                case XMLRecognizer::UTF_8:
574            fCharacterSetAdapter = new XMLUTF8CharacterSetAdapter(*fTranscoder, fMemoryManager);
575                        return 1;
576                case XMLRecognizer::UTF_16L:
577                case XMLRecognizer::UTF_16B:           
578            fCharacterSetAdapter = new XMLUTF16CharacterSetAdapter(*fTranscoder, fMemoryManager, fTranscoder->isSwapped());
579                        return 1;
580
581        case XMLRecognizer::OtherEncoding:
582                default:
583            if (likely(fTranscoder != 0))
584            {
585
586
587                fCharacterSetAdapter = new XMLDefaultCharacterSetAdapter(*fTranscoder, fMemoryManager);
588                return 1;
589            }
590        }
591
592    fCharacterSetAdapter = 0;
593        return 0;
594}
595
596// ---------------------------------------------------------------------------
597//  XMLReader: Private helper methods
598// ---------------------------------------------------------------------------
599
600//  This is called from the constructor when the encoding is not forced.
601//  We assume that the encoding has been auto-sensed at this point and that
602//  fSwapped is set correctly.
603//
604//  In the case of UCS-4 and EBCDIC, we don't have to check for a decl.
605//  The fact that we got here, means that there is one, because that's the
606//  only way we can autosense those.
607//
608void XMLReader::doInitDecode()
609{
610        switch(fEncoding)
611        {
612                case XMLRecognizer::UCS_4B :
613                case XMLRecognizer::UCS_4L :
614                {
615                        // Remove bom if any
616                        if (((fRawByteBuf[0] == 0x00) && (fRawByteBuf[1] == 0x00) && (fRawByteBuf[2] == 0xFE) && (fRawByteBuf[3] == 0xFF)) ||
617                                ((fRawByteBuf[0] == 0xFF) && (fRawByteBuf[1] == 0xFE) && (fRawByteBuf[2] == 0x00) && (fRawByteBuf[3] == 0x00))  )
618                        {
619                                fCharSizeBuf[0] = 1;
620                                fCharSizeBuf[1] = 1;
621                                fCharSizeBuf[2] = 1;
622                                fCharSizeBuf[3] = 1;
623                                fRawBufIndex += 4;
624                        }
625
626                        // Look at the raw buffer as UCS4 chars
627                        const UCS4Ch* asUCS = (const UCS4Ch*)fRawByteBuf;
628
629                        while (fRawBufIndex < fRawBytesAvail)
630                        {
631                                // Get out the current 4 byte value and inc our raw buf index
632                                UCS4Ch curVal = *asUCS++;
633                                fRawBufIndex += sizeof(UCS4Ch);
634
635                                // Swap if that is required for this machine
636                                if (fSwapped)
637                                        curVal = BitOps::swapBytes(curVal);
638
639                                // Make sure its at least semi legal. If not, undo and throw
640                                if (curVal > 0xFFFF)
641                                {
642                                        fCharsAvail = 0;
643                                        fRawBufIndex = 0;
644                                        fMemoryManager->deallocate(fPublicId);
645                                        ArrayJanitor<XMLCh> janValue(fSystemId, fMemoryManager);
646                                        ThrowXMLwithMemMgr1
647                                        (
648                                                TranscodingException
649                                                , XMLExcepts::Reader_CouldNotDecodeFirstLine
650                                                , fSystemId
651                                                , fMemoryManager
652                                        );
653                                }
654                                // Convert the value to an XML char and store it
655                                fCharSizeBuf[fCharsAvail] = 4;
656                                fCharBuf[fCharsAvail++] = XMLCh(curVal);
657                                // Break out on the > character
658                                if (curVal == chCloseAngle)
659                                        break;
660                        }
661                        break;
662                }
663
664                case XMLRecognizer::UTF_8 :
665                {
666                        // If there's a utf-8 BOM  (0xEF 0xBB 0xBF), skip past it.
667                        //   Don't move to char buf - no one wants to see it.
668                        //   Note: this causes any encoding= declaration to override
669                        //         the BOM's attempt to say that the encoding is utf-8.
670
671                        // Look at the raw buffer as short chars
672                        const char* asChars = (const char*)fRawByteBuf;
673
674                        if (fRawBytesAvail > XMLRecognizer::fgUTF8BOMLen &&
675                                XMLString::compareNString(  asChars
676                                                                                        , XMLRecognizer::fgUTF8BOM
677                                                                                        , XMLRecognizer::fgUTF8BOMLen) == 0)
678                        {
679                                fRawBufIndex += XMLRecognizer::fgUTF8BOMLen;
680                                asChars      += XMLRecognizer::fgUTF8BOMLen;
681                        }
682
683                        //
684                        //  First check that there are enough bytes to even see the
685                        //  decl indentifier. If not, get out now with no action since
686                        //  there is no decl.
687                        //
688                        if (fRawBytesAvail < XMLRecognizer::fgASCIIPreLen)
689                                break;
690
691                        // Check for the opening sequence. If not, then no decl
692                        if (XMLString::compareNString(  asChars
693                                                                                        , XMLRecognizer::fgASCIIPre
694                                                                                        , XMLRecognizer::fgASCIIPreLen))
695                        {
696                                break;
697                        }
698
699                        while (fRawBufIndex < fRawBytesAvail)
700                        {
701                                const char curCh = *asChars++;
702                                fRawBufIndex++;
703                                // Looks ok, so store it
704                                fCharSizeBuf[fCharsAvail] = 1;
705                                fCharBuf[fCharsAvail++] = XMLCh(curCh);
706                                // Break out on a > character
707                                if (curCh == chCloseAngle)
708                                        break;
709
710                                //
711                                //  A char greater than 0x7F is not allowed in this case. If
712                                //  so, undo and throw.
713                                //
714                                if (curCh & 0x80)
715                                {
716                                        fCharsAvail = 0;
717                                        fRawBufIndex = 0;
718                                        fMemoryManager->deallocate(fPublicId);
719//                    fMemoryManager->deallocate(fEncodingStr);
720                                        ArrayJanitor<XMLCh> janValue(fSystemId, fMemoryManager);
721                                        ThrowXMLwithMemMgr1
722                                        (
723                                                TranscodingException
724                                                , XMLExcepts::Reader_CouldNotDecodeFirstLine
725                                                , fSystemId
726                                                , fMemoryManager
727                                        );
728                                }
729                        }
730                        break;
731                }
732
733                case XMLRecognizer::UTF_16B :
734                case XMLRecognizer::UTF_16L :
735                {
736                        //
737                        //  If there is a decl here, we just truncate back the characters
738                        //  as we go. No surrogate creation would be allowed here in legal
739                        //  XML, so we consider it a transoding error if we find one.
740                        //
741                        if (fRawBytesAvail < 2)
742                                break;
743
744            const UTF16Ch * utf16src = (const UTF16Ch*)&fRawByteBuf[fRawBufIndex];
745            const UTF16Ch * utf16Ptr = utf16src;
746            if ((*utf16Ptr == chUnicodeMarker) || (*utf16Ptr == chSwappedUnicodeMarker))
747            {
748                fRawBufIndex += sizeof(UTF16Ch);
749                utf16Ptr++;
750            }
751
752//            //  First check that there are enough raw bytes for there to even
753//            //  be a decl indentifier. If not, then nothing to do.
754//            //
755//            if (unlikely((fRawBytesAvail - fRawBufIndex) < XMLRecognizer::fgUTF16PreLen))
756//            {
757//                break;
758//            }
759//            //
760//            //  See we get a match on the prefix. If not, then reset and
761//            //  break out.
762//            //
763//            else if (fEncoding == XMLRecognizer::UTF_16B)
764//            {
765//                if (unlikely(memcmp(utf16Ptr, XMLRecognizer::fgUTF16BPre, XMLRecognizer::fgUTF16PreLen) != 0))
766//                {
767//                    break;
768//                }
769//            }
770//            else
771//            {
772//                if (unlikely(memcmp(utf16Ptr, XMLRecognizer::fgUTF16LPre, XMLRecognizer::fgUTF16PreLen) != 0))
773//                {
774//                    break;
775//                }
776//            }
777
778//            while (fRawBufIndex < fRawBytesAvail)
779//            {
780//                // Get out the current 2 byte value
781//                UTF16Ch ch = *utf16Ptr++;
782
783//                // Swap if that is required for this machine
784//                if (fSwapped)
785//                    ch = BitOps::swapBytes(ch);
786
787//                //
788//                //  Store it and bump the target index, implicitly converting
789//                //  if UTF16Ch and XMLCh are not the same size.
790//                //
791//                fCharSizeBuf[fCharsAvail] = 2;
792//                fCharBuf[fCharsAvail++] = ch;
793
794//                // Break out on a > char
795//                if (ch == chCloseAngle)
796//                    break;
797//            }
798
799//            fRawBufIndex = (utf16Ptr - utf16src) * sizeof(XMLCh);
800
801                        break;
802                }
803
804                case XMLRecognizer::EBCDIC :
805                {
806                        //
807                        //  We use special support in the intrinsic EBCDIC-US transcoder
808                        //  to go through one char at a time.
809                        //
810                        const XMLByte* srcPtr = fRawByteBuf;
811                        while (1)
812                        {
813                                // Transcode one char from the source
814                                const XMLCh chCur = XMLEBCDICTranscoder::xlatThisOne(*srcPtr++);
815                                fRawBufIndex++;
816#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
817                                //
818                                //  And put it into the character buffer. This stuff has to
819                                //  look like it was normally transcoded.
820                                //
821                                fCharSizeBuf[fCharsAvail] = 1;
822                                fCharBuf[fCharsAvail++] = chCur;
823#endif
824                                // If its a > char, then break out
825                                if (chCur == chCloseAngle)
826                                        break;
827
828                                // Watch for using up all input and get out
829                                if (fRawBufIndex == fRawBytesAvail)
830                                        break;
831                        }
832                        break;
833                }
834
835                default :
836                        // It should never be anything else here
837                        fMemoryManager->deallocate(fPublicId);
838//          fMemoryManager->deallocate(fEncodingStr);
839                        fMemoryManager->deallocate(fSystemId);
840                        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Reader_BadAutoEncoding, fMemoryManager);
841                        break;
842        }
843#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
844        //
845        //  Ok, by the time we get here, if its a legal XML file we have eaten
846        //  the XML/TextDecl. So, if we are a PE and are being referenced from
847        //  outside a literal, then we need to throw in an arbitrary space that
848        //  is required by XML.
849        //
850        if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral))
851                fCharBuf[fCharsAvail++] = chSpace;
852#endif
853
854
855}
856
857// ---------------------------------------------------------------------------
858//  XMLReader: Refresh Raw Buffer Methods
859// ---------------------------------------------------------------------------
860void XMLReader::refreshRawBuffer(const XMLSize_t from, const XMLSize_t to)
861{
862    #ifdef PRINT_DEBUG_MESSAGE
863    // clear out the "used" data from the buffer if and only if we're going to print it out
864    Array<XMLByte>::memzero(&fRawByteBuf[0], to);
865    #endif
866
867    //
868    //  If there are any bytes left, move them down to the start. There
869    //  should only ever be (max bytes per char - 1) at the most.
870    //
871    Array<XMLByte>::move(&fRawByteBuf[from], &fRawByteBuf[to], (fRawBytesRead - from));
872
873    // instruct the XMLReader to update its raw data buffer
874    refreshRawBuffer(to + (fRawBytesRead - from));
875}
876
877void XMLReader::refreshRawBuffer(const XMLSize_t offset)
878{
879    fRawBytesRead = fStream->readBytes(&fRawByteBuf[offset], (kRawBufSize + sizeof(BytePack)) - offset) + offset;
880    if (likely(fRawBytesRead > kRawBufSize))
881    {
882        fRawBytesAvail = kRawBufSize;
883    }
884    else // we're at the end of file once we finish processing this
885    {
886        fRawBytesAvail = fRawBytesRead;
887        fEOF = true;
888        #ifdef PRINT_DEBUG_MESSAGE
889        // clear out the "used" data from the buffer if and only if we're going to print it out
890        Array<XMLByte>::memzero(&fRawByteBuf[fRawBytesRead], (kRawBufSize - fRawBytesRead));
891        #endif
892    }
893    fRawBufIndex = 0;
894}
895
896//
897//  This method is called internally when we run out of bytes in the raw
898//  buffer. We just read as many bytes as we can into the raw buffer again
899//  and store the number of bytes we got.
900//
901void XMLReader::refreshRawBuffer()
902{
903    //
904    //  If there are any bytes left, move them down to the start. There
905    //  should only ever be (max bytes per char - 1) at the most.
906    //
907    const XMLSize_t bytesLeft = fRawBytesRead - fRawBufIndex;
908    // Move the existing ones down
909    Array<XMLByte>::move(&fRawByteBuf[fRawBufIndex], &fRawByteBuf[0], bytesLeft);
910    fRawBytesRead = fStream->readBytes(&fRawByteBuf[bytesLeft], (kRawBufSize + sizeof(BytePack)) - bytesLeft) + bytesLeft;
911    if (likely(fRawBytesRead >= kRawBufSize))
912    {
913        fRawBytesAvail = kRawBufSize;
914    }
915    else
916    {
917        fRawBytesAvail = fRawBytesRead;
918        fEOF = true;
919    }
920    fRawBufIndex = 0;
921}
922
923bool XMLReader::refreshCharBuffer()
924{
925    // If the no more flag is set, then don't bother doing anything.
926    if (unlikely(fNoMore))
927    {
928        return false;
929    }
930
931    //
932        //  If no transcoder has been created yet, then we never saw the
933        //  any encoding="" string and the encoding was not forced, so lets
934        //  create one now. We know that it won't change now.
935        //
936        //  However, note that if we autosensed EBCDIC, then we have to
937        //  consider it an error if we never got an encoding since we don't
938        //  know what variant of EBCDIC it is.
939        //
940    if (unlikely(!fTranscoder))
941        {
942                constructTranscoder();
943        }
944
945    //
946    //  If there are spare chars, then adjust the raw buffer index
947    //
948    fRawBufIndex = calculateRawBufIndex();
949
950    //
951        //  And then get more chars, starting after any spare chars that were
952        //  left over from the last time.
953        //
954    fCharsAvail = xcodeMoreChars(&fCharBuf[0], &fCharSizeBuf[0], kCharBufSize);
955
956    fNoMore = (fCharsAvail == 0);
957
958    // Reset the buffer index to zero, so we start from the 0th char again
959    fCharIndex = 0;
960
961    //
962    //  If no chars available, then we have to check for one last thing. If
963    //  this is reader for a PE and its not being expanded inside a literal,
964    //  then unget a trailing space.
965    //
966    if (unlikely(fNoMore && (fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral)))
967    {
968        fCharBuf[0] = chSpace;
969        fCharsAvail = 1;
970        return true;
971    }
972
973    return !fNoMore;
974}
975
976//
977//  This method is called internally when we run out of characters in the
978//  trancoded character buffer. We transcode up to another maxChars chars
979//  from the
980//
981XMLSize_t
982XMLReader::xcodeMoreChars(       XMLCh* const            bufToFill
983                         ,       unsigned char* const    charSizes
984                         , const XMLSize_t               maxChars)
985{
986    XMLSize_t charsDone = 0;
987    XMLSize_t bytesEaten = 0;
988    bool needMore = false;
989
990    do
991    {
992        // If our raw buffer is low, then lets load up another batch of
993        // raw bytes now.
994        //
995        XMLSize_t bytesLeft = fRawBytesAvail - fRawBufIndex;
996
997        if (unlikely(needMore || bytesLeft < kCharBufSize))
998        {
999            // If there are no characters or if we need more but didn't get any, return zero.
1000            if (unlikely(needMore && fEOF))
1001            {
1002                return 0;
1003            }
1004            refreshRawBuffer();
1005        }
1006
1007        fSrcOfsBase = fRawBufIndex;
1008
1009
1010        // Ask the transcoder to internalize another batch of chars. It is
1011        // possible that there is data in the raw buffer but the transcoder
1012        // is unable to produce anything because transcoding of multi-byte
1013        // encodings may have left a few bytes representing a partial
1014        // character in the buffer that can't be used until the next chunk
1015        // (and the rest of the character) is read. In this case set the
1016        // needMore flag and try again.
1017        //
1018
1019        charsDone = fTranscoder->transcodeFrom
1020        (
1021            &fRawByteBuf[fRawBufIndex]
1022            , fRawBytesAvail - fRawBufIndex
1023            , bufToFill
1024            , maxChars
1025            , bytesEaten
1026            , charSizes
1027        );
1028
1029        normalizeEOL(bufToFill, charSizes, charsDone, bytesEaten);
1030
1031        needMore = (bytesEaten == 0);
1032        fRawBufIndex += bytesEaten;
1033    }
1034    while (unlikely(needMore));
1035
1036    return charsDone;
1037}
1038
1039// ---------------------------------------------------------------------------
1040//  XMLReader: Scanning methods
1041// ---------------------------------------------------------------------------
1042bool XMLReader::getName(XMLBuffer & toFill, const bool token)
1043{
1044    //  Ok, first lets see if we have chars in the buffer. If not, then lets
1045    //  reload.
1046    if (fCharIndex == fCharsAvail && !refreshCharBuffer())
1047    {
1048        return false;
1049    }
1050
1051    XMLSize_t charIndex = fCharIndex;
1052    // Check the name start char
1053    if (!token)
1054    {
1055        if (unlikely(charIndex >= fCharsAvail))
1056        {
1057            if (unlikely(!refreshCharBuffer()))
1058            {
1059                return false;
1060            }
1061            charIndex = fCharIndex;
1062        }
1063
1064        if (unlikely(!XMLNameChar::testNameStart(fCharBuf, charIndex)))
1065        {
1066            return false;
1067        }
1068    }
1069
1070    // Loop until we run out of data in this reader or we hit a non-name char.
1071        while (true)
1072        {
1073        bool done = false;
1074        while (charIndex < fCharsAvail)
1075        {
1076            if (unlikely(!XMLNameChar::testNameChar(fCharBuf, charIndex)))
1077            {
1078                done = true;
1079                break;
1080            }
1081        }
1082
1083        // we have to copy the accepted character(s), and update column
1084        fCurCol += (XMLFileLoc)(charIndex - fCharIndex);
1085        toFill.append(&fCharBuf[fCharIndex], charIndex - fCharIndex);
1086        fCharIndex = charIndex;
1087
1088        if (likely(done))
1089        {
1090            break;
1091        }
1092
1093        // we ran out of transcoded characters; attempt to refresh the buffer.
1094        // if we've hit the end of the input, then this is an error.
1095        if (unlikely(!refreshCharBuffer()))
1096        {
1097            break;
1098        }
1099        charIndex = fCharIndex;
1100        }
1101
1102    return !toFill.isEmpty();
1103}
1104
1105bool XMLReader::getNCName(XMLBuffer& toFill)
1106{
1107    // Ok, first lets see if we have chars in the buffer. If not, then reload.
1108    if (fCharIndex == fCharsAvail && !refreshCharBuffer())
1109    {
1110        return false;
1111    }
1112
1113    XMLSize_t charIndex = fCharIndex;
1114
1115    // Check the name start char
1116    if (!XMLNameChar::testNameStart(fCharBuf, charIndex))
1117    {
1118        return false;
1119    }
1120
1121    //  And now we loop until we run out of data in this reader or we hit
1122    //  a non-name char.
1123    while (true)
1124    {
1125        bool done = false;
1126        while (charIndex < fCharsAvail)
1127        {
1128            if ((fCharBuf[charIndex] == chColon) || !XMLNameChar::testNameChar(fCharBuf, charIndex))
1129            {
1130                done = true;
1131                break;
1132            }
1133        }
1134
1135        // we have to copy the accepted character(s), and update column
1136        fCurCol += (XMLFileLoc)(charIndex - fCharIndex);
1137        toFill.append(&fCharBuf[fCharIndex], charIndex - fCharIndex);
1138        fCharIndex = charIndex;
1139
1140        if (likely(done))
1141        {
1142            break;
1143        }
1144
1145        // we ran out of transcoded characters; attempt to refresh the buffer.
1146        // if we've hit the end of the input, then this is an error.
1147        if (!refreshCharBuffer())
1148        {
1149            break;
1150        }
1151        charIndex = fCharIndex;
1152    }
1153
1154        return true;
1155}
1156
1157bool XMLReader::getQName(XMLBuffer& toFill, int* colonPosition)
1158{
1159        // We are only looking for two iterations (i.e. 'NCNAME':'NCNAME').
1160        // We will stop when we finished scanning for a QName (i.e. either a second
1161        // colon or an invalid char).
1162        if(!getNCName(toFill))
1163        {
1164                *colonPosition = -1;
1165                return false;
1166        }
1167    if (fCharIndex == fCharsAvail && !refreshCharBuffer())
1168        {
1169                *colonPosition = -1;
1170                return true;
1171        }
1172        if (fCharBuf[fCharIndex] != chColon)
1173        {
1174                *colonPosition = -1;
1175                return true;
1176        }
1177
1178        *colonPosition = (int)toFill.getLen();
1179        toFill.append(chColon);
1180        fCharIndex++;
1181        fCurCol++;
1182        return getNCName(toFill);
1183}
1184
1185bool XMLReader::getSpaces(XMLBuffer& toFill)
1186{
1187        //
1188        //  We just loop until we either hit a non-space or the end of this
1189        //  entity. We return true if we returned because of a non-space and
1190        //  false if because of end of entity.
1191        //
1192        //  NOTE:   We have to maintain line/col info here and we have to do
1193        //          whitespace normalization if we are not already internalized.
1194        //
1195        while (true)
1196        {
1197                // Loop through the current chars in the buffer
1198                while (fCharIndex < fCharsAvail)
1199                {
1200                        // Get the current char out of the buffer
1201                        XMLCh curCh = fCharBuf[fCharIndex];
1202
1203                        //
1204                        //  See if its a white space char. If so, then process it. Else
1205                        //  we've hit a non-space and need to return.
1206                        //
1207            if (XMLNameChar::isWhitespace(curCh, true))
1208                        {
1209                                // Eat this char
1210                                fCharIndex++;
1211                handleEOL(curCh, false);
1212                                // Ok we can add this guy to our buffer
1213                                toFill.append(curCh);
1214                        }
1215                        else
1216                        {
1217                                // Return true to indicate we broke out due to a whitespace
1218                                return true;
1219                        }
1220                }
1221
1222                //
1223                //  We've eaten up the current buffer, so lets try to reload it. If
1224                //  we don't get anything new, then break out. If we do, then we go
1225                //  back to the top to keep getting spaces.
1226                //
1227                if (!refreshCharBuffer())
1228                        break;
1229        }
1230        return false;
1231}
1232
1233
1234bool XMLReader::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck)
1235{
1236        while (true)
1237        {
1238                // Loop through the current chars in the buffer
1239                while (fCharIndex < fCharsAvail)
1240                {
1241                        // Get the current char out of the buffer
1242                        XMLCh curCh = fCharBuf[fCharIndex];
1243
1244                        //
1245                        //  See if its not a white space or our target char, then process
1246                        //  it. Else, we need to return.
1247                        //
1248            if (!XMLNameChar::isWhitespace(curCh, false) && (curCh != toCheck))
1249                        {
1250                                // Eat this char
1251                                fCharIndex++;
1252                handleEOL(curCh, false);
1253                                // Add it to our buffer
1254                                toFill.append(curCh);
1255                        }
1256                        else
1257                        {
1258                                return true;
1259                        }
1260                }
1261
1262                //
1263                //  We've eaten up the current buffer, so lets try to reload it. If
1264                //  we don't get anything new, then break out. If we do, then we go
1265                //  back to the top to keep getting spaces.
1266                //
1267                if (!refreshCharBuffer())
1268                        break;
1269        }
1270
1271        // We never hit any non-space and ate up the whole reader
1272        return false;
1273}
1274
1275bool XMLReader::skipIfQuote(XMLCh& chGotten)
1276{
1277    if (fCharIndex == fCharsAvail && !refreshCharBuffer())
1278                return false;
1279
1280        chGotten = fCharBuf[fCharIndex];
1281        if ((chGotten == chDoubleQuote) || (chGotten == chSingleQuote))
1282        {
1283                fCharIndex++;
1284                fCurCol++;
1285                return true;
1286        }
1287        return false;
1288}
1289
1290
1291bool XMLReader::skipSpaces(bool& skippedSomething, bool inDecl)
1292{
1293        //  DO NOT set the skippedSomething to 'false', but change it to be 'true' only
1294
1295        //  We enter a loop where we skip over spaces until we hit the end of
1296        //  this reader or a non-space value. The return indicates whether we
1297        //  hit the non-space (true) or the end (false).
1298        do
1299        {
1300                // Loop through the current chars in the buffer
1301                while (fCharIndex < fCharsAvail)
1302                {
1303                        //  See if its a white space char. If so, then process it. Else
1304                        //  we've hit a non-space and need to return.
1305            XMLCh Char = fCharBuf[fCharIndex];
1306            if (XMLNameChar::isWhitespace(Char, false))
1307                        {
1308                                // Get the current char out of the buffer and eat it
1309                                skippedSomething = true;
1310                handleEOL(Char, inDecl);
1311                fCharIndex++;
1312                        }
1313                        else
1314                                return true;
1315                }
1316
1317                //  We've eaten up the current buffer, so lets try to reload it. If
1318                //  we don't get anything new, then break out. If we do, then we go
1319                //  back to the top to keep getting spaces.
1320        }
1321    while (likely(refreshCharBuffer()));
1322
1323        // We never hit any non-space and ate up the whole reader
1324        return false;
1325}
1326
1327bool XMLReader::skippedChar(const XMLCh toSkip)
1328{
1329        //
1330        //  If the buffer is empty, then try to reload it. If we still get
1331        //  nothing, then return false.
1332        //
1333    if (unlikely(fCharIndex == fCharsAvail))
1334        {
1335                if (!refreshCharBuffer())
1336                        return false;
1337        }
1338
1339        //
1340        //  See if the current char is the one we want. If so, then we need
1341        //  to eat it and return true.
1342        //
1343        if (fCharBuf[fCharIndex] == toSkip)
1344        {
1345                fCharIndex++;
1346                fCurCol++;
1347                return true;
1348        }
1349        return false;
1350}
1351
1352
1353bool XMLReader::skippedSpace()
1354{
1355        //
1356        //  If the buffer is empty, then try to reload it. If we still get
1357        //  nothing, then return false.
1358        //
1359    if (fCharIndex == fCharsAvail)
1360        {
1361                if (!refreshCharBuffer())
1362                        return false;
1363        }
1364
1365        //
1366        //  See if the current char is a whitespace. If so, then we need to eat
1367        //  it and return true.
1368        //
1369    XMLCh curCh = fCharBuf[fCharIndex];
1370    if (XMLNameChar::isWhitespace(curCh, false))
1371        {
1372                // Eat the character
1373                fCharIndex++;
1374        handleEOL(curCh, false);
1375                return true;
1376        }
1377        return false;
1378}
1379
1380bool XMLReader::skippedString(const XMLCh* const toSkip)
1381{
1382        // This function works on strings that are smaller than kCharBufSize.
1383        // This function guarantees that in case the comparison is unsuccessful
1384        // the fCharIndex will point to the original data.
1385        //
1386
1387        // Get the length of the string to skip.
1388        //
1389        const XMLSize_t srcLen = XMLString::stringLen(toSkip);
1390        XMLSize_t charsLeft = charsLeftInBuffer();
1391
1392        //  See if the current reader has enough chars to test against this
1393        //  string. If not, then ask it to reload its buffer. If that does not
1394        //  get us enough, then it cannot match.
1395        //
1396        //  NOTE: This works because strings never have to cross a reader! And
1397        //  a string to skip will never have a new line in it, so we will never
1398        //  miss adjusting the current line.
1399        //
1400        while (charsLeft < srcLen)
1401        {
1402          if (!refreshCharBuffer())
1403                return false;
1404
1405          XMLSize_t tmp = charsLeftInBuffer();
1406          if (tmp == charsLeft) // if the refreshCharBuf() did not add anything new
1407                return false;     // give up and return.
1408
1409          charsLeft = tmp;
1410        }
1411
1412        //  Ok, now we now that the current reader has enough chars in its
1413        //  buffer and that its index is back at zero. So we can do a quick and
1414        //  dirty comparison straight to its buffer with no requirement to unget
1415        //  if it fails.
1416        //
1417        if (memcmp(&fCharBuf[fCharIndex], toSkip, srcLen * sizeof(XMLCh)))
1418          return false;
1419
1420        // Add the source length to the current column to get it back right.
1421        //
1422        fCurCol += (XMLFileLoc)srcLen;
1423
1424        //  And get the character buffer index back right by just adding the
1425        //  source len to it.
1426        //
1427        fCharIndex += srcLen;
1428
1429        return true;
1430}
1431
1432bool XMLReader::skippedStringLong(const XMLCh* toSkip)
1433{
1434        // This function works on strings that are potentially longer than
1435        // kCharBufSize (e.g., end tag). This function does not guarantee
1436        // that in case the comparison is unsuccessful the fCharIndex will
1437        // point to the original data.
1438        //
1439
1440        XMLSize_t srcLen = XMLString::stringLen(toSkip);
1441        XMLSize_t charsLeft = charsLeftInBuffer();
1442
1443        while (srcLen != 0)
1444        {
1445          // Fill up the buffer with as much data as possible.
1446          //
1447          while (charsLeft < srcLen && charsLeft != kCharBufSize)
1448          {
1449                if (!refreshCharBuffer())
1450                  return false;
1451
1452                XMLSize_t tmp = charsLeftInBuffer();
1453                if (tmp == charsLeft) // if the refreshCharBuf() did not add anything
1454                  return false;       // new give up and return.
1455
1456                charsLeft = tmp;
1457          }
1458
1459          XMLSize_t n = charsLeft < srcLen ? charsLeft : srcLen;
1460
1461          if (memcmp(&fCharBuf[fCharIndex], toSkip, n * sizeof(XMLCh)))
1462                return false;
1463
1464          toSkip += n;
1465          srcLen -= n;
1466
1467          fCharIndex += n;
1468          fCurCol += (XMLFileLoc)n;
1469          charsLeft -= n;
1470        }
1471
1472        return true;
1473}
1474
1475//
1476// This is just to peek if the next coming buffer
1477// matches the string toPeek.
1478// Similar to skippedString, but just the fCharIndex and fCurCol are not updated
1479//
1480bool XMLReader::peekString(const XMLCh* const toPeek)
1481{
1482        // Get the length of the string to skip
1483        const XMLSize_t srcLen = XMLString::stringLen(toPeek);
1484
1485        //
1486        //  See if the current reader has enough chars to test against this
1487        //  string. If not, then ask it to reload its buffer. If that does not
1488        //  get us enough, then it cannot match.
1489        //
1490        //  NOTE: This works because strings never have to cross a reader! And
1491        //  a string to skip will never have a new line in it, so we will never
1492        //  miss adjusting the current line.
1493        //
1494        XMLSize_t charsLeft = charsLeftInBuffer();
1495    while (charsLeft < srcLen)
1496        {
1497         refreshCharBuffer();
1498         XMLSize_t t = charsLeftInBuffer();
1499                 if (t == charsLeft)   // if the refreshCharBuf() did not add anything new
1500                         return false;     //   give up and return.
1501                 charsLeft = t;
1502        }
1503
1504    //
1505        //  Ok, now we now that the current reader has enough chars in its
1506        //  buffer and that its index is back at zero. So we can do a quick and
1507        //  dirty comparison straight to its buffer with no requirement to unget
1508        //  if it fails.
1509        //
1510        if (memcmp(&fCharBuf[fCharIndex], toPeek, srcLen*sizeof(XMLCh)))
1511                return false;
1512
1513        return true;
1514}
1515
1516const XMLCh * XMLReader::peekString(XMLSize_t length)
1517{
1518    XMLSize_t charsLeft = charsLeftInBuffer();
1519    while (charsLeft < length)
1520    {
1521         refreshCharBuffer();
1522         const XMLSize_t t = charsLeftInBuffer();
1523         if (t == charsLeft)    // if the refreshCharBuf() did not add anything new
1524             return NULL;       //   give up and return.
1525         charsLeft = t;
1526    }
1527    return fCharBuf + fCharIndex;
1528}
1529
1530//
1531// This is just to peek if the next coming buffer
1532// matches the string toPeek.
1533// Similar to skippedString, but just the fCharIndex and fCurCol are not updated
1534//
1535bool XMLReader::peekString(const XMLCh* const toPeek, XMLSize_t length, bool mustBeFollowedByWhitespace)
1536{
1537    // Get the length of the string to skip
1538    const XMLSize_t srcLen = length + mustBeFollowedByWhitespace;
1539
1540    //
1541    //  See if the current reader has enough chars to test against this
1542    //  string. If not, then ask it to reload its buffer. If that does not
1543    //  get us enough, then it cannot match.
1544    //
1545    //  NOTE: This works because strings never have to cross a reader! And
1546    //  a string to skip will never have a new line in it, so we will never
1547    //  miss adjusting the current line.
1548    //
1549    XMLSize_t charsLeft = charsLeftInBuffer();
1550    while (charsLeft < srcLen)
1551    {
1552         refreshCharBuffer();
1553         XMLSize_t t = charsLeftInBuffer();
1554         if (t == charsLeft)   // if the refreshCharBuf() did not add anything new
1555             return false;     //   give up and return.
1556         charsLeft = t;
1557    }
1558
1559    //
1560    //  Ok, now we now that the current reader has enough chars in its
1561    //  buffer and that its index is back at zero. So we can do a quick and
1562    //  dirty comparison straight to its buffer with no requirement to unget
1563    //  if it fails.
1564    //
1565    if (XMLStringU::equals(&fCharBuf[fCharIndex], toPeek, length))
1566    {
1567        return mustBeFollowedByWhitespace ? isWhitespace(fCharBuf[fCharIndex + length]) : true;
1568    }
1569
1570    return false;
1571}
1572
1573// ---------------------------------------------------------------------------
1574//  XMLReader: Query Methods
1575// ---------------------------------------------------------------------------
1576//  Checks whether all of the chars in the passed buffer are whitespace or
1577//  not. Breaks out on the first non-whitespace.
1578//
1579bool XMLReader::isAllSpaces(const   XMLCh* const    toCheck
1580                                                   , const XMLSize_t       count) const
1581{
1582#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1583        const XMLCh* curCh = toCheck;
1584        const XMLCh* endPtr = toCheck + count;
1585        while (curCh < endPtr)
1586        {
1587        if (!isWhitespace(*curCh++))
1588                        return false;
1589        }
1590        return true;
1591#else
1592        return false;
1593#endif
1594}
1595
1596
1597//
1598//  Checks whether at least one of the chars in the passed buffer are whitespace or
1599//  not.
1600//
1601bool XMLReader::containsWhiteSpace(const   XMLCh* const    toCheck
1602                                                        , const XMLSize_t     count) const
1603{
1604#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1605        const XMLCh* curCh = toCheck;
1606        const XMLCh* endPtr = toCheck + count;
1607        while (curCh < endPtr)
1608        {
1609        if (isWhitespace(*curCh++))
1610                        return true;
1611        }
1612#endif
1613        return false;
1614}
1615
1616void XMLReader::handleEOL(XMLCh & curCh, bool inDecl)
1617{
1618    // Handle line/col tracking for any character-at-a-time parsing modes.
1619    if (unlikely(inDecl))
1620    {
1621        if (unlikely(curCh == chNEL || curCh == chLineSeparator))
1622        {
1623            /***
1624             * XML1.1
1625             *
1626             * 2.11 End-of-Line Handling
1627             *  ...
1628             *   The characters #x85 and #x2028 cannot be reliably recognized and translated
1629             *   until an entity's encoding declaration (if present) has been read.
1630             *   Therefore, it is a fatal error to use them within the XML declaration or
1631             *   text declaration.
1632             *
1633             ***/
1634            ThrowXMLwithMemMgr1(TranscodingException, XMLExcepts::Reader_NelLsepinDecl, fSystemId, fMemoryManager);
1635        }
1636    }
1637
1638    if (unlikely(curCh == chLF))
1639    {
1640        fCurCol = 1;
1641        fCurLine++;
1642    }
1643    else
1644    {
1645        fCurCol++;
1646    }
1647}
1648
1649// -----------------------------------------------------------------------
1650// DEPRECATED FUNCTIONS KEPT FOR DLL COMPATIBILITY
1651// -----------------------------------------------------------------------
1652
1653void XMLReader::checkForSwapped() { }
1654
1655XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.