PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/internal/ReaderMgr.cpp

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