ReaderMgr.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:33k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: ReaderMgr.cpp,v 1.15 2003/05/18 14:02:04 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/BinMemInputStream.hpp>
  63. #include <xercesc/util/Janitor.hpp>
  64. #include <xercesc/util/PlatformUtils.hpp>
  65. #include <xercesc/util/RuntimeException.hpp>
  66. #include <xercesc/util/UnexpectedEOFException.hpp>
  67. #include <xercesc/util/XMLURL.hpp>
  68. #include <xercesc/util/XMLUniDefs.hpp>
  69. #include <xercesc/util/XMLUni.hpp>
  70. #include <xercesc/sax/InputSource.hpp>
  71. #include <xercesc/framework/LocalFileInputSource.hpp>
  72. #include <xercesc/framework/URLInputSource.hpp>
  73. #include <xercesc/framework/XMLBuffer.hpp>
  74. #include <xercesc/framework/XMLDocumentHandler.hpp>
  75. #include <xercesc/framework/XMLEntityDecl.hpp>
  76. #include <xercesc/framework/XMLEntityHandler.hpp>
  77. #include <xercesc/internal/EndOfEntityException.hpp>
  78. #include <xercesc/internal/ReaderMgr.hpp>
  79. XERCES_CPP_NAMESPACE_BEGIN
  80. // ---------------------------------------------------------------------------
  81. //  ReaderMgr: Constructors and Destructor
  82. // ---------------------------------------------------------------------------
  83. ReaderMgr::ReaderMgr(MemoryManager* const manager) :
  84.     fCurEntity(0)
  85.     , fCurReader(0)
  86.     , fEntityHandler(0)
  87.     , fEntityStack(0)
  88.     , fNextReaderNum(1)
  89.     , fReaderStack(0)
  90.     , fThrowEOE(false)
  91.     , fXMLVersion(XMLReader::XMLV1_0)
  92.     , fStandardUriConformant(false)
  93.     , fMemoryManager(manager)
  94. {
  95. }
  96. ReaderMgr::~ReaderMgr()
  97. {
  98.     //
  99.     //  Clean up the reader and entity stacks. Note that we don't own the
  100.     //  entities, so we don't delete the current entity (and the entity stack
  101.     //  does not own its elements either, so deleting it will not delete the
  102.     //  entities it still references!)
  103.     //
  104.     delete fCurReader;
  105.     delete fReaderStack;
  106.     delete fEntityStack;
  107. }
  108. // ---------------------------------------------------------------------------
  109. //  ReaderMgr: Getter methods
  110. // ---------------------------------------------------------------------------
  111. bool ReaderMgr::isEmpty() const
  112. {
  113.     return fReaderStack->empty();
  114. }
  115. // ---------------------------------------------------------------------------
  116. //  ReaderMgr: Scanning APIs
  117. // ---------------------------------------------------------------------------
  118. XMLCh ReaderMgr::getNextChar()
  119. {
  120.     XMLCh chRet;
  121.     if (fCurReader->getNextChar(chRet))
  122.         return chRet;
  123.     //
  124.     //  Didn't get anything back so this reader is hosed. So lets move to
  125.     //  the next reader on the stack. If this fails, it will be because
  126.     //  its the end of the original file, and we just return zero.
  127.     //
  128.     //  If its the end of an entity and fThrowEOE is set, it will throw out
  129.     //  of here. Otherwise, it will take us down to the next reader and
  130.     //  we'll have more chars.
  131.     //
  132.     if (!popReader())
  133.         return XMLCh(0);
  134.     // Else try again and return the new character
  135.     fCurReader->getNextChar(chRet);
  136.     return chRet;
  137. }
  138. void ReaderMgr::getSpaces(XMLBuffer& toFill)
  139. {
  140.     // Reset the buffer before we start
  141.     toFill.reset();
  142.     while (true)
  143.     {
  144.         //
  145.         //  Get all the spaces from the current reader. If it returns true,
  146.         //  it hit a non-space and we are done. Else we have to pop a reader
  147.         //  and keep going.
  148.         //
  149.         if (fCurReader->getSpaces(toFill))
  150.             break;
  151.         // We wore that one out, so lets pop a reader and try again
  152.         if (!popReader())
  153.             break;
  154.     }
  155. }
  156. void ReaderMgr::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck)
  157. {
  158.     // Reset the target buffer before we start
  159.     toFill.reset();
  160.     //
  161.     //  Ok, enter a loop where we ask the current reader to get chars until
  162.     //  it meets the criteria. It returns false if it came back due to eating
  163.     //  up all of its data. Else it returned because something matched, and
  164.     //  we are done.
  165.     //
  166.     while (true)
  167.     {
  168.         if (fCurReader->getUpToCharOrWS(toFill, toCheck))
  169.             break;
  170.         // We ate that one up, lets try to pop another. If not, break out
  171.         if (!popReader())
  172.             break;
  173.     }
  174. }
  175. XMLCh ReaderMgr::peekNextChar()
  176. {
  177.     XMLCh chRet;
  178.     if (fCurReader->peekNextChar(chRet))
  179.         return chRet;
  180.     //
  181.     //  Didn't get anything back so this reader is hosed. So lets move to
  182.     //  the next reader on the stack. If this fails, it will be because
  183.     //  its the end of the original file, and we just return zero.
  184.     //
  185.     if (!popReader())
  186.         return XMLCh(0);
  187.     // Else peek again and return the character
  188.     fCurReader->peekNextChar(chRet);
  189.     return chRet;
  190. }
  191. bool ReaderMgr::skippedChar(const XMLCh toCheck)
  192. {
  193.     while (true)
  194.     {
  195.         // If we get it, then just return true now
  196.         if (fCurReader->skippedChar(toCheck))
  197.             return true;
  198.         //
  199.         //  Check to see if we hit end of input on this reader. If so, then
  200.         //  lets pop and try again. Else, we failed. If we cannot pop another
  201.         //  then we failed.
  202.         //
  203.         if (!fCurReader->getNoMoreFlag())
  204.             break;
  205.         if (!popReader())
  206.             break;
  207.     }
  208.     return false;
  209. }
  210. bool ReaderMgr::skippedSpace()
  211. {
  212.     while (true)
  213.     {
  214.         // If we get it, then just return true now
  215.         if (fCurReader->skippedSpace())
  216.             return true;
  217.         //
  218.         //  Check to see if we hit end of input on this reader. If so, then
  219.         //  lets pop and try again. Else, we failed. If we cannot pop another
  220.         //  then we failed.
  221.         //
  222.         if (!fCurReader->getNoMoreFlag())
  223.             break;
  224.         if (!popReader())
  225.             break;
  226.     }
  227.     return false;
  228. }
  229. bool ReaderMgr::skipIfQuote(XMLCh& chGotten)
  230. {
  231.     while (true)
  232.     {
  233.         // If we get it, then just return true now
  234.         if (fCurReader->skipIfQuote(chGotten))
  235.             return true;
  236.         //
  237.         //  Check to see if we hit end of input on this reader. If so, then
  238.         //  lets pop and try again. Else, we failed. If we cannot pop another
  239.         //  then we failed.
  240.         //
  241.         if (!fCurReader->getNoMoreFlag())
  242.             break;
  243.         if (!popReader())
  244.             break;
  245.     }
  246.     return false;
  247. }
  248. bool ReaderMgr::skipPastSpaces()
  249. {
  250.     bool skippedSomething = false;
  251.     bool tmpFlag;
  252.     while (true)
  253.     {
  254.         //
  255.         //  Skip all the spaces in the current reader. If it returned because
  256.         //  it hit a non-space, break out. Else we have to pop another entity
  257.         //  and keep going.
  258.         //
  259.         if (fCurReader->skipSpaces(tmpFlag))
  260.             break;
  261.         if (tmpFlag)
  262.             skippedSomething = true;
  263.         // Try to pop another enitity. If we can't then we are done
  264.         if (!popReader())
  265.             break;
  266.     }
  267.     return (tmpFlag || skippedSomething);
  268. }
  269. void ReaderMgr::skipQuotedString(const XMLCh quoteCh)
  270. {
  271.     XMLCh nextCh;
  272.     while (true)
  273.     {
  274.         nextCh = getNextChar();
  275.         // If we get an end of file char, then return
  276.         if (!nextCh)
  277.             break;
  278.         // If we get the quote char, then break out
  279.         if (nextCh == quoteCh)
  280.             break;
  281.     }
  282. }
  283. XMLCh ReaderMgr::skipUntilIn(const XMLCh* const listToSkip)
  284. {
  285.     XMLCh nextCh;
  286.     while (true)
  287.     {
  288.         nextCh = peekNextChar();
  289.         if (!nextCh)
  290.             break;
  291.         if (XMLString::indexOf(listToSkip, nextCh) != -1)
  292.             break;
  293.         // Its one of ours so eat it
  294.         getNextChar();
  295.     }
  296.     return nextCh;
  297. }
  298. XMLCh ReaderMgr::skipUntilInOrWS(const XMLCh* const listToSkip)
  299. {
  300.     XMLCh nextCh;
  301.     while (true)
  302.     {
  303.         nextCh = peekNextChar();
  304.         if (!nextCh)
  305.             break;
  306.         if (fCurReader->isWhitespace(nextCh))
  307.             break;
  308.         if (XMLString::indexOf(listToSkip, nextCh) != -1)
  309.             break;
  310.         // Its one of ours, so eat it
  311.         getNextChar();
  312.     }
  313.     return nextCh;
  314. }
  315. // ---------------------------------------------------------------------------
  316. //  ReaderMgr: Control methods
  317. // ---------------------------------------------------------------------------
  318. //
  319. //  If the reader stack is empty, then there is only the original main XML
  320. //  entity left. If its empty, then we have no more input.
  321. //
  322. bool ReaderMgr::atEOF() const
  323. {
  324.     return fReaderStack->empty() && fCurReader->getNoMoreFlag();
  325. }
  326. //
  327. //  This method is called in the case of errors to clean up the stack when
  328. //  entities have been incorrectly left on the stack due to syntax errors.
  329. //  It just cleans back the stack, and sends no entity events.
  330. //
  331. void ReaderMgr::cleanStackBackTo(const unsigned int readerNum)
  332. {
  333.     //
  334.     //  Just start popping readers until we find the one with the indicated
  335.     //  reader number.
  336.     //
  337.     while (true)
  338.     {
  339.         if (fCurReader->getReaderNum() == readerNum)
  340.             break;
  341.         if (fReaderStack->empty())
  342.             ThrowXML(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound);
  343.         delete fCurReader;
  344.         fCurReader = fReaderStack->pop();
  345.         fCurEntity = fEntityStack->pop();
  346.     }
  347. }
  348. XMLReader* ReaderMgr::createReader( const   InputSource&        src
  349.                                     , const bool                xmlDecl
  350.                                     , const XMLReader::RefFrom  refFrom
  351.                                     , const XMLReader::Types    type
  352.                                     , const XMLReader::Sources  source
  353.                                     , const bool                calcSrcOfs)
  354. {
  355.     //
  356.     //  Ask the input source to create us an input stream. The particular
  357.     //  type of input source will know what kind to create.
  358.     //
  359.     BinInputStream* newStream = src.makeStream();
  360.     if (!newStream)
  361.         return 0;
  362.     //
  363.     //  Create a new reader and return it. If the source has an encoding that
  364.     //  it wants to force, then we call the constructor that does that.
  365.     //  Otherwise, we just call the one that provides the provisional encoding
  366.     //  to be possibly updated later by the encoding="" setting.
  367.     //
  368.     XMLReader* retVal = 0;
  369.     // XMLReader ctor invokes refreshRawBuffer() which calls
  370.     // newStream->readBytes().
  371.     // This readBytes() may throw exception, which neither
  372.     // refresRawBuffer(), nor XMLReader ctor catches.
  373.     // We need to handle this exception to avoid leak on newStream.
  374.     try {
  375.         if (src.getEncoding())
  376.         {
  377.             retVal = new (fMemoryManager) XMLReader
  378.                 (
  379.                 src.getPublicId()
  380.                 , src.getSystemId()
  381.                 , newStream
  382.                 , src.getEncoding()
  383.                 , refFrom
  384.                 , type
  385.                 , source
  386.                 , false
  387.                 , calcSrcOfs
  388.                 , fXMLVersion
  389.                 , fMemoryManager
  390.                 );
  391.         }
  392.         else
  393.         {
  394.             retVal = new (fMemoryManager) XMLReader
  395.                 (
  396.                 src.getPublicId()
  397.                 , src.getSystemId()
  398.                 , newStream
  399.                 , refFrom
  400.                 , type
  401.                 , source
  402.                 , false
  403.                 , calcSrcOfs
  404.                 , fXMLVersion
  405.                 , fMemoryManager
  406.                 );
  407.         }
  408.     }
  409.     catch (...) //NetAccessorException&
  410.     {
  411.         delete newStream;
  412.         throw;
  413.     }
  414.     // If it failed for any reason, then return zero.
  415.     if (!retVal) {
  416.         delete newStream;
  417.         return 0;
  418.     }
  419.     // Set the next available reader number on this reader
  420.     retVal->setReaderNum(fNextReaderNum++);
  421.     return retVal;
  422. }
  423. XMLReader* ReaderMgr::createReader( const   XMLCh* const        sysId
  424.                                     , const XMLCh* const        pubId
  425.                                     , const bool                xmlDecl
  426.                                     , const XMLReader::RefFrom  refFrom
  427.                                     , const XMLReader::Types    type
  428.                                     , const XMLReader::Sources  source
  429.                                     ,       InputSource*&       srcToFill
  430.                                     , const bool                calcSrcOfs)
  431. {
  432.     // Create a buffer for expanding the system id
  433.     XMLBuffer expSysId(1023, fMemoryManager);
  434.     //
  435.     //  Allow the entity handler to expand the system id if they choose
  436.     //  to do so.
  437.     //
  438.     if (fEntityHandler)
  439.     {
  440.         if (!fEntityHandler->expandSystemId(sysId, expSysId))
  441.             expSysId.set(sysId);
  442.     }
  443.      else
  444.     {
  445.         expSysId.set(sysId);
  446.     }
  447.     // Call the entity resolver interface to get an input source
  448.     srcToFill = 0;
  449.     if (fEntityHandler)
  450.     {
  451.         srcToFill = fEntityHandler->resolveEntity
  452.         (
  453.             pubId
  454.             , expSysId.getRawBuffer()
  455.         );
  456.     }
  457.     //
  458.     //  If they didn't create a source via the entity resolver, then we
  459.     //  have to create one on our own.
  460.     //
  461.     if (!srcToFill)
  462.     {
  463.         LastExtEntityInfo lastInfo;
  464.         getLastExtEntityInfo(lastInfo);
  465.         try
  466.         {
  467.             XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer());
  468.             if (urlTmp.isRelative())
  469.             {
  470.                 ThrowXML
  471.                 (
  472.                     MalformedURLException
  473.                     , XMLExcepts::URL_NoProtocolPresent
  474.                 );
  475.             }
  476.             else {
  477.                 if (fStandardUriConformant && urlTmp.hasInvalidChar())
  478.                     ThrowXML(MalformedURLException, XMLExcepts::URL_MalformedURL);
  479.                 srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
  480.             }
  481.         }
  482.         catch(const MalformedURLException& e)
  483.         {
  484.             // Its not a URL, so lets assume its a local file name if non-standard uri is allowed
  485.             if (!fStandardUriConformant)
  486.                 srcToFill = new (fMemoryManager) LocalFileInputSource
  487.                 (
  488.                     lastInfo.systemId
  489.                     , expSysId.getRawBuffer()
  490.                     , fMemoryManager
  491.                 );
  492.             else
  493.                 throw e;
  494.         }
  495.     }
  496.     // Put a janitor on the input source
  497.     Janitor<InputSource> janSrc(srcToFill);
  498.     //
  499.     //  Now call the other version with the input source that we have, and
  500.     //  return the resulting reader.
  501.     //
  502.     XMLReader* retVal = createReader
  503.     (
  504.         *srcToFill
  505.         , xmlDecl
  506.         , refFrom
  507.         , type
  508.         , source
  509.         , calcSrcOfs
  510.     );
  511.     // Either way, we can release the input source now
  512.     janSrc.orphan();
  513.     // If it failed for any reason, then return zero.
  514.     if (!retVal)
  515.         return 0;
  516.     // Give this reader the next available reader number and return it
  517.     retVal->setReaderNum(fNextReaderNum++);
  518.     return retVal;
  519. }
  520. XMLReader* ReaderMgr::createReader( const   XMLCh* const        baseURI
  521.                                     , const XMLCh* const        sysId
  522.                                     , const XMLCh* const        pubId
  523.                                     , const bool                xmlDecl
  524.                                     , const XMLReader::RefFrom  refFrom
  525.                                     , const XMLReader::Types    type
  526.                                     , const XMLReader::Sources  source
  527.                                     ,       InputSource*&       srcToFill
  528.                                     , const bool                calcSrcOfs)
  529. {
  530.     // Create a buffer for expanding the system id
  531.     XMLBuffer expSysId(1023, fMemoryManager);
  532.     //
  533.     //  Allow the entity handler to expand the system id if they choose
  534.     //  to do so.
  535.     //
  536.     if (fEntityHandler)
  537.     {
  538.         if (!fEntityHandler->expandSystemId(sysId, expSysId))
  539.             expSysId.set(sysId);
  540.     }
  541.      else
  542.     {
  543.         expSysId.set(sysId);
  544.     }
  545.     // Call the entity resolver interface to get an input source
  546.     srcToFill = 0;
  547.     if (fEntityHandler)
  548.     {
  549.         srcToFill = fEntityHandler->resolveEntity
  550.         (
  551.             pubId
  552.             , expSysId.getRawBuffer()
  553.         );
  554.     }
  555.     //
  556.     //  If they didn't create a source via the entity resolver, then we
  557.     //  have to create one on our own.
  558.     //
  559.     if (!srcToFill)
  560.     {
  561.         LastExtEntityInfo lastInfo;
  562.         getLastExtEntityInfo(lastInfo);
  563.         try
  564.         {
  565.             XMLURL urlTmp((!baseURI || !*baseURI) ? lastInfo.systemId : baseURI, expSysId.getRawBuffer());
  566.             if (urlTmp.isRelative())
  567.             {
  568.                 ThrowXML
  569.                 (
  570.                     MalformedURLException
  571.                     , XMLExcepts::URL_NoProtocolPresent
  572.                 );
  573.             }
  574.             else {
  575.                 if (fStandardUriConformant && urlTmp.hasInvalidChar())
  576.                     ThrowXML(MalformedURLException, XMLExcepts::URL_MalformedURL);
  577.                 srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
  578.             }
  579.         }
  580.         catch(const MalformedURLException& e)
  581.         {
  582.             // Its not a URL, so lets assume its a local file name if non-standard uri is allowed
  583.             if (!fStandardUriConformant)
  584.                 srcToFill = new (fMemoryManager) LocalFileInputSource
  585.                 (
  586.                     lastInfo.systemId
  587.                     , expSysId.getRawBuffer()
  588.                     , fMemoryManager
  589.                 );
  590.             else
  591.                 throw e;
  592.         }
  593.     }
  594.     // Put a janitor on the input source
  595.     Janitor<InputSource> janSrc(srcToFill);
  596.     //
  597.     //  Now call the other version with the input source that we have, and
  598.     //  return the resulting reader.
  599.     //
  600.     XMLReader* retVal = createReader
  601.     (
  602.         *srcToFill
  603.         , xmlDecl
  604.         , refFrom
  605.         , type
  606.         , source
  607.         , calcSrcOfs
  608.     );
  609.     // Either way, we can release the input source now
  610.     janSrc.orphan();
  611.     // If it failed for any reason, then return zero.
  612.     if (!retVal)
  613.         return 0;
  614.     // Give this reader the next available reader number and return it
  615.     retVal->setReaderNum(fNextReaderNum++);
  616.     return retVal;
  617. }
  618. XMLReader*
  619. ReaderMgr::createIntEntReader(  const   XMLCh* const        sysId
  620.                                 , const XMLReader::RefFrom  refFrom
  621.                                 , const XMLReader::Types    type
  622.                                 , const XMLCh* const        dataBuf
  623.                                 , const unsigned int        dataLen
  624.                                 , const bool                copyBuf
  625.                                 , const bool                calcSrcOfs)
  626. {
  627.     //
  628.     //  This one is easy, we just create an input stream for the data and
  629.     //  provide a few extra goodies.
  630.     //
  631.     //  NOTE: We use a special encoding string that will be recognized
  632.     //  as a 'do nothing' transcoder for the already internalized XMLCh
  633.     //  data that makes up an internal entity.
  634.     //
  635.     BinMemInputStream* newStream = new (fMemoryManager) BinMemInputStream
  636.                                    (
  637.                                      (const XMLByte*)dataBuf
  638.                                      , dataLen * sizeof(XMLCh)
  639.                                      , copyBuf ? BinMemInputStream::BufOpt_Copy
  640.                                                : BinMemInputStream::BufOpt_Reference
  641.                                      , fMemoryManager
  642.                                    );
  643.     if (!newStream)
  644.         return 0;
  645.     XMLReader* retVal = new (fMemoryManager) XMLReader
  646.     (
  647.         sysId
  648.         , 0
  649.         , newStream
  650.         , XMLRecognizer::XERCES_XMLCH
  651.         , refFrom
  652.         , type
  653.         , XMLReader::Source_Internal
  654.         , false
  655.         , calcSrcOfs
  656.         , fXMLVersion
  657.         , fMemoryManager
  658.     );
  659.     // If it failed for any reason, then return zero.
  660.     if (!retVal) {
  661.         delete newStream;
  662.         return 0;
  663.     }
  664.     // Set the reader number to the next available number
  665.     retVal->setReaderNum(fNextReaderNum++);
  666.     return retVal;
  667. }
  668. const XMLCh* ReaderMgr::getCurrentEncodingStr() const
  669. {
  670.     const XMLEntityDecl*    theEntity;
  671.     const XMLReader*        theReader = getLastExtEntity(theEntity);
  672.     return theReader->getEncodingStr();
  673. }
  674. const XMLEntityDecl* ReaderMgr::getCurrentEntity() const
  675. {
  676.     return fCurEntity;
  677. }
  678. XMLEntityDecl* ReaderMgr::getCurrentEntity()
  679. {
  680.     return fCurEntity;
  681. }
  682. const XMLReader* ReaderMgr::getCurrentReader() const
  683. {
  684.     return fCurReader;
  685. }
  686. XMLReader* ReaderMgr::getCurrentReader()
  687. {
  688.     return fCurReader;
  689. }
  690. unsigned int ReaderMgr::getReaderDepth() const
  691. {
  692.     // If the stack doesn't exist, its obviously zero
  693.     if (!fEntityStack)
  694.         return 0;
  695.     //
  696.     //  The return is the stack size, plus one if there is a current
  697.     //  reader. So if there is no current reader and none on the stack,
  698.     //  its zero, else its some non-zero value.
  699.     //
  700.     unsigned int retVal = fEntityStack->size();
  701.     if (fCurReader)
  702.         retVal++;
  703.     return retVal;
  704. }
  705. void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const
  706. {
  707.     //
  708.     //  If the reader stack never got created or we've not managed to open any
  709.     //  main entity yet, then we can't give this information.
  710.     //
  711.     if (!fReaderStack || !fCurReader)
  712.     {
  713.         lastInfo.systemId = XMLUni::fgZeroLenString;
  714.         lastInfo.publicId = XMLUni::fgZeroLenString;
  715.         lastInfo.lineNumber = 0;
  716.         lastInfo.colNumber = 0;
  717.         return;
  718.     }
  719.     // We have at least one entity so get the data
  720.     const XMLEntityDecl*    theEntity;
  721.     const XMLReader*        theReader = getLastExtEntity(theEntity);
  722.     // Fill in the info structure with the reader we found
  723.     lastInfo.systemId = theReader->getSystemId();
  724.     lastInfo.publicId = theReader->getPublicId();
  725.     lastInfo.lineNumber = theReader->getLineNumber();
  726.     lastInfo.colNumber = theReader->getColumnNumber();
  727. }
  728. bool ReaderMgr::isScanningPERefOutOfLiteral() const
  729. {
  730.     // If the current reader is not for an entity, then definitely not
  731.     if (!fCurEntity)
  732.         return false;
  733.     //
  734.     //  If this is a PE entity, and its not being expanded in a literal
  735.     //  then its true.
  736.     //
  737.     if ((fCurReader->getType() == XMLReader::Type_PE)
  738.     &&  (fCurReader->getRefFrom() == XMLReader::RefFrom_NonLiteral))
  739.     {
  740.         return true;
  741.     }
  742.     return false;
  743. }
  744. bool ReaderMgr::pushReader(         XMLReader* const        reader
  745.                             ,       XMLEntityDecl* const    entity)
  746. {
  747.     //
  748.     //  First, if an entity was passed, we have to confirm that this entity
  749.     //  is not already on the entity stack. If so, then this is a recursive
  750.     //  entity expansion, so we issue an error and refuse to put the reader
  751.     //  on the stack.
  752.     //
  753.     //  If there is no entity passed, then its not an entity being pushed, so
  754.     //  nothing to do. If there is no entity stack yet, then of coures it
  755.     //  cannot already be there.
  756.     //
  757.     if (entity && fEntityStack)
  758.     {
  759.         const unsigned int count = fEntityStack->size();
  760.         const XMLCh* const theName = entity->getName();
  761.         for (unsigned int index = 0; index < count; index++)
  762.         {
  763.             const XMLEntityDecl* curDecl = fEntityStack->elementAt(index);
  764.             if (curDecl)
  765.             {
  766.                 if (XMLString::equals(theName, curDecl->getName()))
  767.                 {
  768.                     // Oops, already there so delete reader and return
  769.                     delete reader;
  770.                     return false;
  771.                 }
  772.             }
  773.         }
  774.     }
  775.     //
  776.     //  Fault in the reader stack. Give it an initial capacity of 16, and
  777.     //  tell it it does own its elements.
  778.     //
  779.     if (!fReaderStack)
  780.         fReaderStack = new (fMemoryManager) RefStackOf<XMLReader>(16, true, fMemoryManager);
  781.     // And the entity stack, which does not own its elements
  782.     if (!fEntityStack)
  783.         fEntityStack = new (fMemoryManager) RefStackOf<XMLEntityDecl>(16, false, fMemoryManager);
  784.     //
  785.     //  Push the current reader and entity onto their respective stacks.
  786.     //  Note that the the current entity can be null if the current reader
  787.     //  is not for an entity.
  788.     //
  789.     if (fCurReader)
  790.     {
  791.         fReaderStack->push(fCurReader);
  792.         fEntityStack->push(fCurEntity);
  793.     }
  794.     //
  795.     //  Make the passed reader and entity the current top of stack. The
  796.     //  passed entity can (and often is) null.
  797.     //
  798.     fCurReader = reader;
  799.     fCurEntity = entity;
  800.     return true;
  801. }
  802. void ReaderMgr::reset()
  803. {
  804.     // Reset all of the flags
  805.     fThrowEOE = false;
  806.     // Delete the current reader and flush the reader stack
  807.     delete fCurReader;
  808.     fCurReader = 0;
  809.     if (fReaderStack)
  810.         fReaderStack->removeAllElements();
  811.     //
  812.     //  And do the same for the entity stack, but don't delete the current
  813.     //  entity (if any) since we don't own them.
  814.     //
  815.     fCurEntity = 0;
  816.     if (fEntityStack)
  817.         fEntityStack->removeAllElements();
  818. }
  819. // ---------------------------------------------------------------------------
  820. //  ReaderMgr: Implement the SAX Locator interface
  821. // ---------------------------------------------------------------------------
  822. const XMLCh* ReaderMgr::getPublicId() const
  823. {
  824.     if (!fReaderStack && !fCurReader)
  825.         return XMLUni::fgZeroLenString;
  826.     const XMLEntityDecl* theEntity;
  827.     return getLastExtEntity(theEntity)->getPublicId();
  828. }
  829. const XMLCh* ReaderMgr::getSystemId() const
  830. {
  831.     if (!fReaderStack && !fCurReader)
  832.         return XMLUni::fgZeroLenString;
  833.     const XMLEntityDecl* theEntity;
  834.     return getLastExtEntity(theEntity)->getSystemId();
  835. }
  836. XMLSSize_t ReaderMgr::getColumnNumber() const
  837. {
  838.     if (!fReaderStack && !fCurReader)
  839.         return 0;
  840.     const XMLEntityDecl* theEntity;
  841.     return getLastExtEntity(theEntity)->getColumnNumber();
  842. }
  843. XMLSSize_t ReaderMgr::getLineNumber() const
  844. {
  845.     if (!fReaderStack && !fCurReader)
  846.         return 0;
  847.     const XMLEntityDecl* theEntity;
  848.     return getLastExtEntity(theEntity)->getLineNumber();
  849. }
  850. // ---------------------------------------------------------------------------
  851. //  ReaderMgr: Private helper methods
  852. // ---------------------------------------------------------------------------
  853. const XMLReader*
  854. ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
  855. {
  856.     //
  857.     //  Scan down the reader stack until we find a reader for an entity that
  858.     //  is external. First check that there is anything in the stack at all,
  859.     //  in which case the current reader is the main file and that's the one
  860.     //  that we want.
  861.     //
  862.     const XMLReader* theReader = fCurReader;
  863.     //
  864.     //  If there is a current entity and it is not an external entity, then
  865.     //  search the stack; else, keep the reader that we've got since its
  866.     //  either an external entity reader or the main file reader.
  867.     //
  868.     const XMLEntityDecl* curEntity = fCurEntity;
  869.     if (curEntity && !curEntity->isExternal())
  870.     {
  871.         unsigned int index = fReaderStack->size();
  872.         if (index)
  873.         {
  874.             while (true)
  875.             {
  876.                 // Move down to the previous element and get a pointer to it
  877.                 index--;
  878.                 curEntity = fEntityStack->elementAt(index);
  879.                 //
  880.                 //  If its null or its an external entity, then this reader
  881.                 //  is what we want, so break out with that one.
  882.                 //
  883.                 if (!curEntity)
  884.                 {
  885.                     theReader = fReaderStack->elementAt(index);
  886.                     break;
  887.                 }
  888.                  else if (curEntity->isExternal())
  889.                 {
  890.                     theReader = fReaderStack->elementAt(index);
  891.                     break;
  892.                 }
  893.                 // We hit the end, so leave the main file reader as the one
  894.                 if (!index)
  895.                     break;
  896.             }
  897.         }
  898.     }
  899.     itsEntity = curEntity;
  900.     return theReader;
  901. }
  902. bool ReaderMgr::popReader()
  903. {
  904.     //
  905.     //  We didn't get any more, so try to pop off a reader. If the reader
  906.     //  stack is empty, then we are at the end, so return false.
  907.     //
  908.     if (fReaderStack->empty())
  909.         return false;
  910.     //
  911.     //  Remember the current entity, before we pop off a new one. We might
  912.     //  need this to throw the end of entity exception at the end.
  913.     //
  914.     XMLEntityDecl* prevEntity = fCurEntity;
  915.     const bool prevReaderThrowAtEnd = fCurReader->getThrowAtEnd();
  916.     const unsigned int readerNum = fCurReader->getReaderNum();
  917.     //
  918.     //  Delete the current reader and pop a new reader and entity off
  919.     //  the stacks.
  920.     //
  921.     delete fCurReader;
  922.     fCurReader = fReaderStack->pop();
  923.     fCurEntity = fEntityStack->pop();
  924.     //
  925.     //  If there was a previous entity, and either the fThrowEOE flag is set
  926.     //  or reader was marked as such, then throw an end of entity.
  927.     //
  928.     if (prevEntity && fThrowEOE || prevReaderThrowAtEnd)
  929.         throw EndOfEntityException(prevEntity, readerNum);
  930.     while (true)
  931.     {
  932.         //
  933.         //  They don't want us to throw, so lets just return with a new
  934.         //  reader. Here we have to do a loop because we might have multiple
  935.         //  readers on these stack that are empty (i.e. the last char in them
  936.         //  was the ';' at the end of the entity ref that caused the next
  937.         //  entity to be pushed.
  938.         //
  939.         //  So we loop until we find a non-empty reader, or hit the main
  940.         //  file entity. If we find one with some chars available, then break
  941.         //  out and take that one.
  942.         //
  943.         if (fCurReader->charsLeftInBuffer())
  944.             break;
  945.         fCurReader->refreshCharBuffer();
  946.         if (fCurReader->charsLeftInBuffer())
  947.             break;
  948.         //
  949.         //  The current one is hosed. So, if the reader stack is empty we
  950.         //  are dead meat and can give up now.
  951.         //
  952.         if (fReaderStack->empty())
  953.             return false;
  954.         // Else pop again and try it one more time
  955.         delete fCurReader;
  956.         fCurReader = fReaderStack->pop();
  957.         fCurEntity = fEntityStack->pop();
  958.     }
  959.     return true;
  960. }
  961. XERCES_CPP_NAMESPACE_END