source: icXML/icXML-devel/src/icxercesc/internal/WFXMLScanner.cpp @ 3150

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

Updates for various icxercesc modified files.

File size: 14.1 KB
Line 
1/*
2 * Unless required by applicable law or agreed to in writing, software
3 * distributed under the License is distributed on an "AS IS" BASIS,
4 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 * See the License for the specific language governing permissions and
6 * limitations under the License.
7 */
8
9/*
10  * $Id: WFXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $
11 */
12
13// ---------------------------------------------------------------------------
14//  Includes
15// ---------------------------------------------------------------------------
16#include <icxercesc/internal/WFXMLScanner.hpp>
17#include <xercesc/util/Janitor.hpp>
18#include <xercesc/util/RuntimeException.hpp>
19#include <xercesc/util/UnexpectedEOFException.hpp>
20#include <xercesc/sax/InputSource.hpp>
21#include <icxercesc/framework/XMLDocumentHandler.hpp>
22#include <xercesc/framework/XMLEntityHandler.hpp>
23#include <xercesc/framework/XMLPScanToken.hpp>
24#include <xercesc/framework/XMLValidityCodes.hpp>
25#include <xercesc/util/OutOfMemoryException.hpp>
26#include <iostream>
27
28#define USE_PARABIX_READER
29
30XERCES_CPP_NAMESPACE_BEGIN
31
32// ---------------------------------------------------------------------------
33//  WFXMLScanner: Constructors and Destructor
34// ---------------------------------------------------------------------------
35
36
37typedef JanitorMemFunCall<WFXMLScanner> CleanupType;
38typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
39
40
41WFXMLScanner::WFXMLScanner
42(
43    XMLValidator* const         valToAdopt
44    , GrammarResolver* const    grammarResolver
45    , MemoryManager* const      manager
46)
47: XMLScanner(valToAdopt, grammarResolver, manager)
48, fElementList(32, manager, true)
49{
50        CleanupType cleanup(this, &WFXMLScanner::cleanUp);
51
52        try
53        {
54                commonInit();
55        }
56        catch(const OutOfMemoryException&)
57        {
58                // Don't cleanup when out of memory, since executing the
59                // code can cause problems.
60                cleanup.release();
61
62                throw;
63        }
64
65        cleanup.release();
66}
67
68WFXMLScanner::WFXMLScanner
69(
70    XMLDocumentHandler* const docHandler
71    , DocTypeHandler* const     docTypeHandler
72    , XMLEntityHandler* const   entityHandler
73    , XMLErrorReporter* const   errHandler
74    , XMLValidator* const       valToAdopt
75    , GrammarResolver* const    grammarResolver
76    , MemoryManager* const      manager
77)
78: XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager)
79, fElementList(32, manager, true)
80{
81        CleanupType cleanup(this, &WFXMLScanner::cleanUp);
82
83        try
84        {
85                commonInit();
86        }
87        catch(const OutOfMemoryException&)
88        {
89                // Don't cleanup when out of memory, since executing the
90                // code can cause problems.
91                cleanup.release();
92
93                throw;
94        }
95
96        cleanup.release();
97}
98
99WFXMLScanner::~WFXMLScanner()
100{
101        cleanUp();
102}
103
104// ---------------------------------------------------------------------------
105//  XMLScanner: Getter methods
106// ---------------------------------------------------------------------------
107NameIdPool<DTDEntityDecl>* WFXMLScanner::getEntityDeclPool()
108{
109        return 0;
110}
111
112const NameIdPool<DTDEntityDecl>* WFXMLScanner::getEntityDeclPool() const
113{
114        return 0;
115}
116
117// ---------------------------------------------------------------------------
118//  WFXMLScanner: Main entry point to scan a document
119// ---------------------------------------------------------------------------
120void WFXMLScanner::scanDocument(const InputSource& src)
121{
122        //  Bump up the sequence id for this parser instance. This will invalidate
123        //  any previous progressive scan tokens.
124        fSequenceId++;
125
126        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
127
128        try
129        {
130                //  Reset the scanner and its plugged in stuff for a new run. This
131                //  resets all the data structures, creates the initial reader and
132                //  pushes it on the stack, and sets up the base document path.
133                scanReset(src);
134
135                // If we have a document handler, then call the start document
136                if (fDocHandler)
137                        fDocHandler->startDocument();
138
139                //  If we got to the end of input, then its not a valid XML file.
140                //  Else, go on to scan the content.
141                if (fReaderMgr.atEOF())
142                {
143                        emitError(XMLErrs::EmptyMainEntity);
144                }
145                else
146                {
147                        // Scan content, and tell it its not an external entity
148                        if (fReaderMgr.getCurrentReader()->scanDocument<WFXMLScanner>(this))
149                        {
150
151                        }
152                }
153
154                // If we have a document handler, then call the end document
155                if (fDocHandler)
156                        fDocHandler->endDocument();
157
158        }
159        //  NOTE:
160        //
161        //  In all of the error processing below, the emitError() call MUST come
162        //  before the flush of the reader mgr, or it will fail because it tries
163        //  to find out the position in the XML source of the error.
164        catch(const XMLErrs::Codes)
165        {
166                // This is a 'first failure' exception, so fall through
167        }
168        catch(const XMLValid::Codes)
169        {
170                // This is a 'first fatal error' type exit, so fall through
171        }
172        catch(const XMLException& excToCatch)
173        {
174                //  Emit the error and catch any user exception thrown from here. Make
175                //  sure in all cases we flush the reader manager.
176                fInException = true;
177                try
178                {
179                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
180                                emitError
181                                (
182                                        XMLErrs::XMLException_Warning
183                                        , excToCatch.getCode()
184                                        , excToCatch.getMessage()
185                                );
186                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
187                                emitError
188                                (
189                                        XMLErrs::XMLException_Fatal
190                                        , excToCatch.getCode()
191                                        , excToCatch.getMessage()
192                                );
193                        else
194                                emitError
195                                (
196                                        XMLErrs::XMLException_Error
197                                        , excToCatch.getCode()
198                                        , excToCatch.getMessage()
199                                );
200                }
201                catch(const OutOfMemoryException&)
202                {
203                        // This is a special case for out-of-memory
204                        // conditions, because resetting the ReaderMgr
205                        // can be problematic.
206                        resetReaderMgr.release();
207                        throw;
208                }
209        }
210        catch(const OutOfMemoryException&)
211        {
212                // This is a special case for out-of-memory
213                // conditions, because resetting the ReaderMgr
214                // can be problematic.
215                resetReaderMgr.release();
216                throw;
217        }
218}
219
220void WFXMLScanner::scanFirst()
221{
222    fReaderMgr.getCurrentReader()->scanFirst<WFXMLScanner>(this);
223}
224
225bool WFXMLScanner::scanNext(XMLPScanToken& token)
226{
227        // Make sure this token is still legal
228        if (!isLegalToken(token))
229                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
230
231        try
232        {
233        if (likely(fReaderMgr.getCurrentReader()->scanNext<WFXMLScanner>()))
234                {
235            return true;
236                }
237
238        if (fDocHandler)
239            fDocHandler->endDocument();
240        }
241        catch(const XMLErrs::Codes)
242        {
243
244        }
245        catch(const XMLValid::Codes)
246        {
247
248        }
249        catch(const XMLException & excToCatch)
250        {
251                //  Emit the error and catch any user exception thrown from here. Make
252                //  sure in all cases we flush the reader manager.
253                fInException = true;
254                try
255                {
256                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
257                                emitError
258                                (
259                                        XMLErrs::XMLException_Warning
260                                        , excToCatch.getCode()
261                                        , excToCatch.getMessage()
262                                );
263                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
264                                emitError
265                                (
266                                        XMLErrs::XMLException_Fatal
267                                        , excToCatch.getCode()
268                                        , excToCatch.getMessage()
269                                );
270                        else
271                                emitError
272                                (
273                                        XMLErrs::XMLException_Error
274                                        , excToCatch.getCode()
275                                        , excToCatch.getMessage()
276                                );
277                }
278                catch(const OutOfMemoryException&)
279                {
280                        throw;
281                }
282        }
283        catch(const OutOfMemoryException&)
284        {
285                throw;
286        }
287
288        fReaderMgr.reset();
289
290        return false;
291}
292
293// ---------------------------------------------------------------------------
294//  WFXMLScanner: Private helper methods.
295// ---------------------------------------------------------------------------
296
297//  This method handles the common initialization, to avoid having to do
298//  it redundantly in multiple constructors.
299void WFXMLScanner::commonInit()
300{
301
302}
303
304void WFXMLScanner::cleanUp()
305{
306
307}
308
309//  This method will reset the scanner data structures, and related plugged
310//  in stuff, for a new scan session. We get the input source for the primary
311//  XML entity, create the reader for it, and push it on the stack so that
312//  upon successful return from here we are ready to go.
313void WFXMLScanner::scanReset(const InputSource& src)
314{
315        //  For all installed handlers, send reset events. This gives them
316        //  a chance to flush any cached data.
317        if (fDocHandler)
318                fDocHandler->resetDocument();
319        if (fEntityHandler)
320                fEntityHandler->resetEntities();
321        if (fErrorReporter)
322                fErrorReporter->resetErrors();
323
324        // Reset some status flags
325        fInException = false;
326        fStandalone = false;
327        fErrorCount = 0;
328        fHasNoDTD = true;
329
330        //  Handle the creation of the XML reader object for this input source.
331        //  This will provide us with transcoding and basic lexing services.
332        XMLReader* newReader = fReaderMgr.createReader
333        (
334                src
335                , true
336                , XMLReader::RefFrom_NonLiteral
337                , XMLReader::Type_General
338                , XMLReader::Source_External
339                , fCalculateSrcOfs
340                , fLowWaterMark
341        );
342
343        if (!newReader)
344        {
345                if (src.getIssueFatalErrorIfNotFound())
346                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
347                else
348                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
349        }
350
351        // Push this read onto the reader manager
352        fReaderMgr.pushReader(newReader, 0);
353
354        // and reset security-related things if necessary:
355        if(fSecurityManager != 0)
356        {
357                fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
358                fEntityExpansionCount = 0;
359        }
360}
361
362// ---------------------------------------------------------------------------
363//  WFXMLScanner: Grammar preparsing
364// ---------------------------------------------------------------------------
365Grammar* WFXMLScanner::loadGrammar( const InputSource&
366                                                                  , const short
367                                                                  , const bool)
368{
369        // REVISIT: emit a warning or throw an exception
370        return 0;
371}
372
373InputSource* WFXMLScanner::resolveSystemId(const XMLCh* const /*sysId*/
374                                                                                  ,const XMLCh* const /*pubId*/)
375{
376        return 0;
377}
378
379
380// ---------------------------------------------------------------------------
381//  WFXMLScanner: ICXML Deprecated Functions
382// ---------------------------------------------------------------------------
383
384void WFXMLScanner::sendCharData(XMLBuffer &)
385{
386        DEPRECATED_FEATURE_IN_ICXML;
387}
388
389bool WFXMLScanner::scanContent()
390{
391        DEPRECATED_FEATURE_IN_ICXML;
392}
393
394void WFXMLScanner::scanEndTag(bool&)
395{
396        DEPRECATED_FEATURE_IN_ICXML;
397}
398
399bool WFXMLScanner::scanStartTag(bool&)
400{
401        DEPRECATED_FEATURE_IN_ICXML;
402}
403
404bool WFXMLScanner::scanStartTagNS(bool&)
405{
406        DEPRECATED_FEATURE_IN_ICXML;
407}
408
409bool WFXMLScanner::scanAttValue(const XMLCh* const, XMLBuffer&)
410{
411        DEPRECATED_FEATURE_IN_ICXML;
412}
413
414void WFXMLScanner::scanCDSection()
415{
416        DEPRECATED_FEATURE_IN_ICXML;
417}
418
419void WFXMLScanner::scanCharData(XMLBuffer &)
420{
421        DEPRECATED_FEATURE_IN_ICXML;
422}
423
424//  This method will scan a general/character entity ref. It will either
425//  expand a char ref and return it directly, or push a reader for a general
426//  entity.
427//
428//  The return value indicates whether the char parameters hold the value
429//  or whether the value was pushed as a reader, or that it failed.
430//
431//  The escaped flag tells the caller whether the returned parameter resulted
432//  from a character reference, which escapes the character in some cases. It
433//  only makes any difference if the return value indicates the value was
434//  returned directly.
435XMLScanner::EntityExpRes
436WFXMLScanner::scanEntityRef(const bool
437                                                        ,     XMLCh&  firstCh
438                                                        ,     XMLCh&  secondCh
439                                                        ,     bool&   escaped)
440{
441#if 1
442        DEPRECATED_FEATURE_IN_ICXML;
443#else
444        // Assume no escape
445        secondCh = 0;
446        escaped = false;
447
448        // We have to insure that its all in one entity
449        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
450
451        //  If the next char is a pound, then its a character reference and we
452        //  need to expand it always.
453        if (fReaderMgr.skippedChar(chPound))
454        {
455                //  Its a character reference, so scan it and get back the numeric
456                //  value it represents.
457                if (!scanCharRef(firstCh, secondCh))
458                        return EntityExp_Failed;
459
460                escaped = true;
461
462                if (curReader != fReaderMgr.getCurrentReaderNum())
463                        emitError(XMLErrs::PartialMarkupInEntity);
464
465                return EntityExp_Returned;
466        }
467
468        // Expand it since its a normal entity ref
469        XMLBufBid bbName(&fBufMgr);
470        if (!fReaderMgr.getName(bbName.getBuffer()))
471        {
472                emitError(XMLErrs::ExpectedEntityRefName);
473                return EntityExp_Failed;
474        }
475
476        //  Next char must be a semi-colon. But if its not, just emit
477        //  an error and try to continue.
478        if (!fReaderMgr.skippedChar(chSemiColon))
479                emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
480
481        // Make sure we ended up on the same entity reader as the & char
482        if (curReader != fReaderMgr.getCurrentReaderNum())
483                emitError(XMLErrs::PartialMarkupInEntity);
484
485        // Look up the name in the general entity pool
486        // If it does not exist, then obviously an error
487        if (!fEntityTable->containsKey(bbName.getRawBuffer()))
488        {
489                // XML 1.0 Section 4.1
490                // Well-formedness Constraint for entity not found:
491                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
492                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
493                //      or a parameter entity
494                if (fStandalone || fHasNoDTD)
495                        emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
496
497                return EntityExp_Failed;
498        }
499
500        // here's where we need to check if there's a SecurityManager,
501        // how many entity references we've had
502        if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
503        {
504                XMLCh expLimStr[32];
505                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
506                emitError
507                (
508                        XMLErrs::EntityExpansionLimitExceeded
509                        , expLimStr
510                );
511                // there seems nothing better to be done than to reset the entity expansion counter
512                fEntityExpansionCount = 0;
513        }
514
515        firstCh = fEntityTable->get(bbName.getRawBuffer());
516        escaped = true;
517        return EntityExp_Returned;
518#endif
519}
520
521void WFXMLScanner::scanDocTypeDecl()
522{
523#ifdef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
524        DEPRECATED_FEATURE_IN_ICXML;
525#else
526        // Just skips over it
527        // REVISIT: Should we issue a warning
528        static const XMLCh doctypeIE[] =
529        {
530                chOpenSquare, chCloseAngle, chNull
531        };
532        XMLCh nextCh = fReaderMgr.skipUntilIn(doctypeIE);
533
534        if (nextCh == chOpenSquare)
535                fReaderMgr.skipPastChar(chCloseSquare);
536
537        fReaderMgr.skipPastChar(chCloseAngle);
538#endif
539}
540
541XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.