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

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

Initial check-in of icXML 0.8 source files

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