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

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

Changes to icxercesc files

File size: 14.6 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, fElements(32, true, manager)
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, fElements(32, true, manager)
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    fEntityTable = new (fMemoryManager) ValueHashTableOf<XMLCh>(5, fMemoryManager);
302    //  Add the default entity entries for the character refs that must always be present.
303    fEntityTable->put((void*) XMLUni::fgAmp, chAmpersand);
304    fEntityTable->put((void*) XMLUni::fgLT, chOpenAngle);
305    fEntityTable->put((void*) XMLUni::fgGT, chCloseAngle);
306    fEntityTable->put((void*) XMLUni::fgQuot, chDoubleQuote);
307    fEntityTable->put((void*) XMLUni::fgApos, chSingleQuote);
308}
309
310void WFXMLScanner::setLocator(Locator *)
311{
312    /* do nothing */
313}
314
315void WFXMLScanner::cleanUp()
316{
317    delete fEntityTable;
318}
319
320//  This method will reset the scanner data structures, and related plugged
321//  in stuff, for a new scan session. We get the input source for the primary
322//  XML entity, create the reader for it, and push it on the stack so that
323//  upon successful return from here we are ready to go.
324void WFXMLScanner::scanReset(const InputSource& src)
325{
326        //  For all installed handlers, send reset events. This gives them
327        //  a chance to flush any cached data.
328        if (fDocHandler)
329                fDocHandler->resetDocument();
330        if (fEntityHandler)
331                fEntityHandler->resetEntities();
332        if (fErrorReporter)
333                fErrorReporter->resetErrors();
334
335        // Reset some status flags
336        fInException = false;
337        fStandalone = false;
338        fErrorCount = 0;
339        fHasNoDTD = true;
340
341        //  Handle the creation of the XML reader object for this input source.
342        //  This will provide us with transcoding and basic lexing services.
343        XMLReader* newReader = fReaderMgr.createReader
344        (
345                src
346                , true
347                , XMLReader::RefFrom_NonLiteral
348                , XMLReader::Type_General
349                , XMLReader::Source_External
350                , fCalculateSrcOfs
351                , fLowWaterMark
352        );
353
354        if (!newReader)
355        {
356                if (src.getIssueFatalErrorIfNotFound())
357                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
358                else
359                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
360        }
361
362        // Push this read onto the reader manager
363        fReaderMgr.pushReader(newReader, 0);
364
365        // and reset security-related things if necessary:
366        if(fSecurityManager != 0)
367        {
368                fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
369                fEntityExpansionCount = 0;
370        }
371}
372
373// ---------------------------------------------------------------------------
374//  WFXMLScanner: Grammar preparsing
375// ---------------------------------------------------------------------------
376Grammar* WFXMLScanner::loadGrammar( const InputSource&
377                                                                  , const short
378                                                                  , const bool)
379{
380        // REVISIT: emit a warning or throw an exception
381        return 0;
382}
383
384InputSource* WFXMLScanner::resolveSystemId(const XMLCh* const /*sysId*/
385                                                                                  ,const XMLCh* const /*pubId*/)
386{
387        return 0;
388}
389
390
391// ---------------------------------------------------------------------------
392//  WFXMLScanner: ICXML Deprecated Functions
393// ---------------------------------------------------------------------------
394
395void WFXMLScanner::sendCharData(XMLBuffer &)
396{
397        DEPRECATED_FEATURE_IN_ICXML;
398}
399
400bool WFXMLScanner::scanContent()
401{
402        DEPRECATED_FEATURE_IN_ICXML;
403}
404
405void WFXMLScanner::scanEndTag(bool&)
406{
407        DEPRECATED_FEATURE_IN_ICXML;
408}
409
410bool WFXMLScanner::scanStartTag(bool&)
411{
412        DEPRECATED_FEATURE_IN_ICXML;
413}
414
415bool WFXMLScanner::scanStartTagNS(bool&)
416{
417        DEPRECATED_FEATURE_IN_ICXML;
418}
419
420bool WFXMLScanner::scanAttValue(const XMLCh* const, XMLBuffer&)
421{
422        DEPRECATED_FEATURE_IN_ICXML;
423}
424
425void WFXMLScanner::scanCDSection()
426{
427        DEPRECATED_FEATURE_IN_ICXML;
428}
429
430void WFXMLScanner::scanCharData(XMLBuffer &)
431{
432        DEPRECATED_FEATURE_IN_ICXML;
433}
434
435//  This method will scan a general/character entity ref. It will either
436//  expand a char ref and return it directly, or push a reader for a general
437//  entity.
438//
439//  The return value indicates whether the char parameters hold the value
440//  or whether the value was pushed as a reader, or that it failed.
441//
442//  The escaped flag tells the caller whether the returned parameter resulted
443//  from a character reference, which escapes the character in some cases. It
444//  only makes any difference if the return value indicates the value was
445//  returned directly.
446XMLScanner::EntityExpRes
447WFXMLScanner::scanEntityRef(const bool
448                                                        ,     XMLCh&  firstCh
449                                                        ,     XMLCh&  secondCh
450                                                        ,     bool&   escaped)
451{
452#if 1
453        DEPRECATED_FEATURE_IN_ICXML;
454#else
455        // Assume no escape
456        secondCh = 0;
457        escaped = false;
458
459        // We have to insure that its all in one entity
460        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
461
462        //  If the next char is a pound, then its a character reference and we
463        //  need to expand it always.
464        if (fReaderMgr.skippedChar(chPound))
465        {
466                //  Its a character reference, so scan it and get back the numeric
467                //  value it represents.
468                if (!scanCharRef(firstCh, secondCh))
469                        return EntityExp_Failed;
470
471                escaped = true;
472
473                if (curReader != fReaderMgr.getCurrentReaderNum())
474                        emitError(XMLErrs::PartialMarkupInEntity);
475
476                return EntityExp_Returned;
477        }
478
479        // Expand it since its a normal entity ref
480        XMLBufBid bbName(&fBufMgr);
481        if (!fReaderMgr.getName(bbName.getBuffer()))
482        {
483                emitError(XMLErrs::ExpectedEntityRefName);
484                return EntityExp_Failed;
485        }
486
487        //  Next char must be a semi-colon. But if its not, just emit
488        //  an error and try to continue.
489        if (!fReaderMgr.skippedChar(chSemiColon))
490                emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
491
492        // Make sure we ended up on the same entity reader as the & char
493        if (curReader != fReaderMgr.getCurrentReaderNum())
494                emitError(XMLErrs::PartialMarkupInEntity);
495
496        // Look up the name in the general entity pool
497        // If it does not exist, then obviously an error
498        if (!fEntityTable->containsKey(bbName.getRawBuffer()))
499        {
500                // XML 1.0 Section 4.1
501                // Well-formedness Constraint for entity not found:
502                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
503                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
504                //      or a parameter entity
505                if (fStandalone || fHasNoDTD)
506                        emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
507
508                return EntityExp_Failed;
509        }
510
511        // here's where we need to check if there's a SecurityManager,
512        // how many entity references we've had
513        if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
514        {
515                XMLCh expLimStr[32];
516                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
517                emitError
518                (
519                        XMLErrs::EntityExpansionLimitExceeded
520                        , expLimStr
521                );
522                // there seems nothing better to be done than to reset the entity expansion counter
523                fEntityExpansionCount = 0;
524        }
525
526        firstCh = fEntityTable->get(bbName.getRawBuffer());
527        escaped = true;
528        return EntityExp_Returned;
529#endif
530}
531
532void WFXMLScanner::scanDocTypeDecl()
533{
534#ifdef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
535        DEPRECATED_FEATURE_IN_ICXML;
536#else
537        // Just skips over it
538        // REVISIT: Should we issue a warning
539        static const XMLCh doctypeIE[] =
540        {
541                chOpenSquare, chCloseAngle, chNull
542        };
543        XMLCh nextCh = fReaderMgr.skipUntilIn(doctypeIE);
544
545        if (nextCh == chOpenSquare)
546                fReaderMgr.skipPastChar(chCloseSquare);
547
548        fReaderMgr.skipPastChar(chCloseAngle);
549#endif
550}
551
552XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.