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

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

Fixes for icXML 0.9

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