PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/validators/common/DFAContentModel.cpp

http://atf2flightsim.googlecode.com/
C++ | 1408 lines | 729 code | 132 blank | 547 comment | 215 complexity | 2dd295dba52b63b46e11eb9e903c0839 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999-2001 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. * $Log: DFAContentModel.cpp,v $
  58. * Revision 1.1.1.1 2009/03/14 06:43:09 whitegr
  59. * epics channel archiver
  60. *
  61. * Revision 1.9 2003/11/20 18:12:20 knoaman
  62. * Use a bitwise operation to check the node type.
  63. *
  64. * Revision 1.8 2003/11/07 17:08:11 knoaman
  65. * For PSVI support, distinguish wildcard elements with namespace lists.
  66. *
  67. * Revision 1.7 2003/05/18 14:02:06 knoaman
  68. * Memory manager implementation: pass per instance manager.
  69. *
  70. * Revision 1.6 2003/05/16 21:43:20 knoaman
  71. * Memory manager implementation: Modify constructors to pass in the memory manager.
  72. *
  73. * Revision 1.5 2003/05/15 18:48:27 knoaman
  74. * Partial implementation of the configurable memory manager.
  75. *
  76. * Revision 1.4 2002/11/04 14:54:58 tng
  77. * C++ Namespace Support.
  78. *
  79. * Revision 1.3 2002/09/24 19:48:39 tng
  80. * Performance: use XMLString::equals instead of XMLString::compareString
  81. *
  82. * Revision 1.2 2002/02/25 21:18:53 tng
  83. * Schema Fix: Ensure no invalid uri index for UPA checking.
  84. *
  85. * Revision 1.1.1.1 2002/02/01 22:22:38 peiyongz
  86. * sane_include
  87. *
  88. * Revision 1.29 2001/12/10 21:42:55 peiyongz
  89. * Memory Leak: fLeafNameTypeVector
  90. *
  91. * Revision 1.28 2001/12/06 17:52:17 tng
  92. * Performance Enhancement. The QName that was passed to the CMLeaf
  93. * constructor was always being copied, even though the CMLeaf objects
  94. * only existed during construction of a DFA. In most cases the original
  95. * QName that was passed into the CMLeaf constructor continued to exist long
  96. * after the CMLeaf was destroyed; in some cases the QName was constructed
  97. * specifically to be passed to the CMLeaf constructor. Added a second CMLeaf constructor that indicated the QName passed in was to be adopted; otherwise the CMLeaf constructor just sets a reference to the QName passed in.
  98. * By Henry Zongaro.
  99. *
  100. * Revision 1.27 2001/11/21 14:30:13 knoaman
  101. * Fix for UPA checking.
  102. *
  103. * Revision 1.26 2001/11/07 21:10:46 tng
  104. * Performance: move getRawName() to outer loop so that it is called only once per outer loop.
  105. *
  106. * Revision 1.25 2001/10/04 15:08:55 knoaman
  107. * Add support for circular import.
  108. *
  109. * Revision 1.24 2001/09/14 14:50:22 tng
  110. * Schema: Fix some wildcard bugs, and some retrieving qualified/unqualified element decl problems.
  111. *
  112. * Revision 1.23 2001/08/24 12:48:48 tng
  113. * Schema: AllContentModel
  114. *
  115. * Revision 1.22 2001/08/22 16:58:55 tng
  116. * typo: should issue the name of second element.
  117. *
  118. * Revision 1.21 2001/08/21 16:50:23 tng
  119. * Schema: Unique Particle Attribution Constraint Checking.
  120. *
  121. * Revision 1.20 2001/08/21 16:06:11 tng
  122. * Schema: Unique Particle Attribution Constraint Checking.
  123. *
  124. * Revision 1.19 2001/08/17 16:12:51 peiyongz
  125. * Fix to memory leak in buildDFA(), patch from Nick Chiang (nchiang@ss8.com)
  126. *
  127. * Revision 1.18 2001/08/16 21:52:40 peiyongz
  128. * stateTable created to optimize the identification of new state created.
  129. *
  130. * Revision 1.17 2001/07/31 17:45:25 peiyongz
  131. * Fix: memory leak in postTreeBuildInit()
  132. *
  133. * Revision 1.16 2001/07/24 20:00:33 peiyongz
  134. * Memory Leak fix: Bugzilla #2707 reported by Francois Rioux
  135. *
  136. * + | DESCRIPTION |
  137. * + There are some memory leaks in the buildDFA method :
  138. * + the first QName allocated object
  139. * + the nodeOrgContent
  140. * + fHeadNode
  141. *
  142. * Revision 1.15 2001/07/09 15:22:36 knoaman
  143. * complete <any> declaration.
  144. *
  145. * Revision 1.14 2001/06/13 20:50:56 peiyongz
  146. * fIsMixed: to handle mixed Content Model
  147. *
  148. * Revision 1.13 2001/06/12 19:07:14 peiyongz
  149. * Memory leak: fixed by Erik Rydgren
  150. *
  151. * Revision 1.12 2001/06/12 17:30:49 knoaman
  152. * Fix Typo
  153. *
  154. * Revision 1.11 2001/06/07 21:08:20 tng
  155. * Fix unsigned/signed warning from Linux. By Pei Yong Zhang.
  156. *
  157. * Revision 1.10 2001/05/28 20:52:44 tng
  158. * Schema: move static data gInvalidTrans, gEOCFakeId, gEpsilonFakeId to XMLContentModel for others to access
  159. *
  160. * Revision 1.9 2001/05/11 13:27:18 tng
  161. * Copyright update.
  162. *
  163. * Revision 1.8 2001/05/03 21:02:29 tng
  164. * Schema: Add SubstitutionGroupComparator and update exception messages. By Pei Yong Zhang.
  165. *
  166. * Revision 1.7 2001/04/19 18:17:30 tng
  167. * Schema: SchemaValidator update, and use QName in Content Model
  168. *
  169. * Revision 1.6 2001/03/21 21:56:27 tng
  170. * Schema: Add Schema Grammar, Schema Validator, and split the DTDValidator into DTDValidator, DTDScanner, and DTDGrammar.
  171. *
  172. * Revision 1.5 2001/03/21 19:29:51 tng
  173. * Schema: Content Model Updates, by Pei Yong Zhang.
  174. *
  175. * Revision 1.4 2001/02/27 18:32:31 tng
  176. * Schema: Use XMLElementDecl instead of DTDElementDecl in Content Model.
  177. *
  178. * Revision 1.3 2001/02/27 14:48:51 tng
  179. * Schema: Add CMAny and ContentLeafNameTypeVector, by Pei Yong Zhang
  180. *
  181. * Revision 1.2 2001/02/16 14:58:57 tng
  182. * Schema: Update Makefile, configure files, project files, and include path in
  183. * certain cpp files because of the move of the common Content Model files. By Pei Yong Zhang.
  184. *
  185. * Revision 1.1 2001/02/16 14:17:29 tng
  186. * Schema: Move the common Content Model files that are shared by DTD
  187. * and schema from 'DTD' folder to 'common' folder. By Pei Yong Zhang.
  188. *
  189. * Revision 1.5 2000/03/28 19:43:25 roddey
  190. * Fixes for signed/unsigned warnings. New work for two way transcoding
  191. * stuff.
  192. *
  193. * Revision 1.4 2000/03/08 23:52:34 roddey
  194. * Got rid of the use of -1 to represent an invalid transition state,
  195. * and just created a const value that is unsigned. This should make
  196. * some compilers happier.
  197. *
  198. * Revision 1.3 2000/03/02 19:55:38 roddey
  199. * This checkin includes many changes done while waiting for the
  200. * 1.1.0 code to be finished. I can't list them all here, but a list is
  201. * available elsewhere.
  202. *
  203. * Revision 1.2 2000/02/09 21:42:37 abagchi
  204. * Copyright swatswat
  205. *
  206. * Revision 1.1.1.1 1999/11/09 01:03:17 twl
  207. * Initial checkin
  208. *
  209. * Revision 1.2 1999/11/08 20:45:38 rahul
  210. * Swat for adding in Product name and CVS comment log variable.
  211. *
  212. */
  213. // ---------------------------------------------------------------------------
  214. // Includes
  215. // ---------------------------------------------------------------------------
  216. #include <xercesc/util/RuntimeException.hpp>
  217. #include <xercesc/framework/XMLBuffer.hpp>
  218. #include <xercesc/framework/XMLElementDecl.hpp>
  219. #include <xercesc/framework/XMLValidator.hpp>
  220. #include <xercesc/validators/common/CMAny.hpp>
  221. #include <xercesc/validators/common/CMBinaryOp.hpp>
  222. #include <xercesc/validators/common/CMLeaf.hpp>
  223. #include <xercesc/validators/common/CMUnaryOp.hpp>
  224. #include <xercesc/validators/common/DFAContentModel.hpp>
  225. #include <xercesc/validators/common/ContentSpecNode.hpp>
  226. #include <xercesc/validators/common/Grammar.hpp>
  227. #include <xercesc/validators/schema/SchemaSymbols.hpp>
  228. #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
  229. #include <xercesc/validators/schema/XercesElementWildcard.hpp>
  230. #include <xercesc/util/RefHashTableOf.hpp>
  231. #include <xercesc/util/HashCMStateSet.hpp>
  232. #include <xercesc/util/XMLInteger.hpp>
  233. XERCES_CPP_NAMESPACE_BEGIN
  234. // ---------------------------------------------------------------------------
  235. // DFAContentModel: Constructors and Destructor
  236. // ---------------------------------------------------------------------------
  237. DFAContentModel::DFAContentModel( const bool dtd
  238. , ContentSpecNode* const elemContentSpec
  239. , MemoryManager* const manager) :
  240. fElemMap(0)
  241. , fElemMapType(0)
  242. , fElemMapSize(0)
  243. , fEmptyOk(false)
  244. , fEOCPos(0)
  245. , fFinalStateFlags(0)
  246. , fFollowList(0)
  247. , fHeadNode(0)
  248. , fLeafCount(0)
  249. , fLeafList(0)
  250. , fTransTable(0)
  251. , fTransTableSize(0)
  252. , fDTD(dtd)
  253. , fIsMixed(false)
  254. , fLeafNameTypeVector(0)
  255. , fMemoryManager(manager)
  256. {
  257. // And build the DFA data structures
  258. buildDFA(elemContentSpec);
  259. }
  260. DFAContentModel::DFAContentModel( const bool dtd
  261. , ContentSpecNode* const elemContentSpec
  262. , const bool isMixed
  263. , MemoryManager* const manager):
  264. fElemMap(0)
  265. , fElemMapType(0)
  266. , fElemMapSize(0)
  267. , fEmptyOk(false)
  268. , fEOCPos(0)
  269. , fFinalStateFlags(0)
  270. , fFollowList(0)
  271. , fHeadNode(0)
  272. , fLeafCount(0)
  273. , fLeafList(0)
  274. , fTransTable(0)
  275. , fTransTableSize(0)
  276. , fDTD(dtd)
  277. , fIsMixed(isMixed)
  278. , fLeafNameTypeVector(0)
  279. , fMemoryManager(manager)
  280. {
  281. // And build the DFA data structures
  282. buildDFA(elemContentSpec);
  283. }
  284. DFAContentModel::~DFAContentModel()
  285. {
  286. //
  287. // Clean up all the stuff that is not just temporary representation
  288. // data that was cleaned up after building the DFA.
  289. //
  290. fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags;
  291. unsigned index;
  292. for (index = 0; index < fTransTableSize; index++)
  293. fMemoryManager->deallocate(fTransTable[index]); //delete [] fTransTable[index];
  294. fMemoryManager->deallocate(fTransTable); //delete [] fTransTable;
  295. for (index = 0; index < fLeafCount; index++)
  296. delete fElemMap[index];
  297. fMemoryManager->deallocate(fElemMap); //delete [] fElemMap;
  298. fMemoryManager->deallocate(fElemMapType); //delete [] fElemMapType;
  299. fMemoryManager->deallocate(fLeafListType); //delete [] fLeafListType;
  300. delete fLeafNameTypeVector;
  301. }
  302. // ---------------------------------------------------------------------------
  303. // DFAContentModel: Implementation of the ContentModel virtual interface
  304. // ---------------------------------------------------------------------------
  305. int
  306. DFAContentModel::validateContent( QName** const children
  307. , const unsigned int childCount
  308. , const unsigned int emptyNamespaceId) const
  309. {
  310. //
  311. // If there are no children, then either we fail on the 0th element
  312. // or we return success. It depends upon whether this content model
  313. // accepts empty content, which we determined earlier.
  314. //
  315. if (!childCount)
  316. {
  317. // success -1
  318. return fEmptyOk ? -1 : 0;
  319. }
  320. //
  321. // Lets loop through the children in the array and move our way
  322. // through the states. Note that we use the fElemMap array to map
  323. // an element index to a state index.
  324. //
  325. unsigned int curState = 0;
  326. unsigned int nextState = 0;
  327. unsigned int childIndex = 0;
  328. for (; childIndex < childCount; childIndex++)
  329. {
  330. // Get the current element index out
  331. const QName* curElem = children[childIndex];
  332. const XMLCh* curElemRawName = 0;
  333. if (fDTD)
  334. curElemRawName = curElem->getRawName();
  335. // If this is text in a Schema mixed content model, skip it.
  336. if ( fIsMixed &&
  337. ( curElem->getURI() == XMLElementDecl::fgPCDataElemId))
  338. continue;
  339. // Look up this child in our element map
  340. unsigned int elemIndex = 0;
  341. for (; elemIndex < fElemMapSize; elemIndex++)
  342. {
  343. const QName* inElem = fElemMap[elemIndex];
  344. if (fDTD) {
  345. if (XMLString::equals(inElem->getRawName(), curElemRawName)) {
  346. nextState = fTransTable[curState][elemIndex];
  347. if (nextState != XMLContentModel::gInvalidTrans)
  348. break;
  349. }
  350. }
  351. else {
  352. ContentSpecNode::NodeTypes type = fElemMapType[elemIndex];
  353. if (type == ContentSpecNode::Leaf)
  354. {
  355. if ((inElem->getURI() == curElem->getURI()) &&
  356. (XMLString::equals(inElem->getLocalPart(), curElem->getLocalPart()))) {
  357. nextState = fTransTable[curState][elemIndex];
  358. if (nextState != XMLContentModel::gInvalidTrans)
  359. break;
  360. }
  361. }
  362. else if ((type & 0x0f)== ContentSpecNode::Any)
  363. {
  364. nextState = fTransTable[curState][elemIndex];
  365. if (nextState != XMLContentModel::gInvalidTrans)
  366. break;
  367. }
  368. else if ((type & 0x0f) == ContentSpecNode::Any_NS)
  369. {
  370. if (inElem->getURI() == curElem->getURI())
  371. {
  372. nextState = fTransTable[curState][elemIndex];
  373. if (nextState != XMLContentModel::gInvalidTrans)
  374. break;
  375. }
  376. }
  377. else if ((type & 0x0f) == ContentSpecNode::Any_Other)
  378. {
  379. if (inElem->getURI() != curElem->getURI()) {
  380. nextState = fTransTable[curState][elemIndex];
  381. if (nextState != XMLContentModel::gInvalidTrans)
  382. break;
  383. }
  384. }
  385. }
  386. }//for elemIndex
  387. // If "nextState" is -1, we found a match, but the transition is invalid
  388. if (nextState == XMLContentModel::gInvalidTrans)
  389. return childIndex;
  390. // If we didn't find it, then obviously not valid
  391. if (elemIndex == fElemMapSize)
  392. return childIndex;
  393. curState = nextState;
  394. nextState = 0;
  395. }//for childIndex
  396. //
  397. // We transitioned all the way through the input list. However, that
  398. // does not mean that we ended in a final state. So check whether
  399. // our ending state is a final state.
  400. //
  401. if (!fFinalStateFlags[curState])
  402. return childIndex;
  403. //success
  404. return -1;
  405. }
  406. int DFAContentModel::validateContentSpecial(QName** const children
  407. , const unsigned int childCount
  408. , const unsigned int emptyNamespaceId
  409. , GrammarResolver* const pGrammarResolver
  410. , XMLStringPool* const pStringPool) const
  411. {
  412. SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
  413. if (childCount == 0)
  414. return fEmptyOk ? -1 : 0;
  415. //
  416. // Lets loop through the children in the array and move our way
  417. // through the states. Note that we use the fElemMap array to map
  418. // an element index to a state index.
  419. //
  420. unsigned int curState = 0;
  421. unsigned int nextState = 0;
  422. unsigned int childIndex = 0;
  423. for (; childIndex < childCount; childIndex++)
  424. {
  425. // Get the current element index out
  426. QName* curElem = children[childIndex];
  427. // If this is text in a Schema mixed content model, skip it.
  428. if ( fIsMixed &&
  429. ( curElem->getURI() == XMLElementDecl::fgPCDataElemId))
  430. continue;
  431. // Look up this child in our element map
  432. unsigned int elemIndex = 0;
  433. for (; elemIndex < fElemMapSize; elemIndex++)
  434. {
  435. QName* inElem = fElemMap[elemIndex];
  436. ContentSpecNode::NodeTypes type = fElemMapType[elemIndex];
  437. if (type == ContentSpecNode::Leaf)
  438. {
  439. if (comparator.isEquivalentTo(curElem, inElem) )
  440. {
  441. nextState = fTransTable[curState][elemIndex];
  442. if (nextState != XMLContentModel::gInvalidTrans)
  443. break;
  444. }
  445. }
  446. else if ((type & 0x0f)== ContentSpecNode::Any)
  447. {
  448. nextState = fTransTable[curState][elemIndex];
  449. if (nextState != XMLContentModel::gInvalidTrans)
  450. break;
  451. }
  452. else if ((type & 0x0f) == ContentSpecNode::Any_NS)
  453. {
  454. if (inElem->getURI() == curElem->getURI())
  455. {
  456. nextState = fTransTable[curState][elemIndex];
  457. if (nextState != XMLContentModel::gInvalidTrans)
  458. break;
  459. }
  460. }
  461. else if ((type & 0x0f) == ContentSpecNode::Any_Other)
  462. {
  463. if (inElem->getURI() != curElem->getURI())
  464. {
  465. nextState = fTransTable[curState][elemIndex];
  466. if (nextState != XMLContentModel::gInvalidTrans)
  467. break;
  468. }
  469. }
  470. }//for elemIndex
  471. // If "nextState" is -1, we found a match, but the transition is invalid
  472. if (nextState == XMLContentModel::gInvalidTrans)
  473. return childIndex;
  474. // If we didn't find it, then obviously not valid
  475. if (elemIndex == fElemMapSize)
  476. return childIndex;
  477. curState = nextState;
  478. nextState = 0;
  479. }//for childIndex
  480. //
  481. // We transitioned all the way through the input list. However, that
  482. // does not mean that we ended in a final state. So check whether
  483. // our ending state is a final state.
  484. //
  485. if (!fFinalStateFlags[curState])
  486. return childIndex;
  487. //success
  488. return -1;
  489. }
  490. // ---------------------------------------------------------------------------
  491. // DFAContentModel: Private helper methods
  492. // ---------------------------------------------------------------------------
  493. void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
  494. {
  495. unsigned int index;
  496. //
  497. // The first step we need to take is to rewrite the content model using
  498. // our CMNode objects, and in the process get rid of any repetition short
  499. // cuts, converting them into '*' style repetitions or getting rid of
  500. // repetitions altogether.
  501. //
  502. // The conversions done are:
  503. //
  504. // x+ -> (x|x*)
  505. // x? -> (x|epsilon)
  506. //
  507. // This is a relatively complex scenario. What is happening is that we
  508. // create a top level binary node of which the special EOC value is set
  509. // as the right side node. The the left side is set to the rewritten
  510. // syntax tree. The source is the original content model info from the
  511. // decl pool. The rewrite is done by buildSyntaxTree() which recurses the
  512. // decl pool's content of the element and builds a new tree in the
  513. // process.
  514. //
  515. // Note that, during this operation, we set each non-epsilon leaf node's
  516. // DFA state position and count the number of such leafs, which is left
  517. // in the fLeafCount member.
  518. //
  519. CMLeaf* nodeEOC = new (fMemoryManager) CMLeaf
  520. (
  521. new (fMemoryManager) QName
  522. (
  523. XMLUni::fgZeroLenString
  524. , XMLUni::fgZeroLenString
  525. , XMLContentModel::gEOCFakeId
  526. , fMemoryManager
  527. )
  528. , ~0
  529. , true
  530. , fMemoryManager
  531. );
  532. CMNode* nodeOrgContent = buildSyntaxTree(curNode);
  533. fHeadNode = new (fMemoryManager) CMBinaryOp
  534. (
  535. ContentSpecNode::Sequence
  536. , nodeOrgContent
  537. , nodeEOC
  538. , fMemoryManager
  539. );
  540. //
  541. // And handle specially the EOC node, which also must be numbered and
  542. // counted as a non-epsilon leaf node. It could not be handled in the
  543. // above tree build because it was created before all that started. We
  544. // save the EOC position since its used during the DFA building loop.
  545. //
  546. fEOCPos = fLeafCount;
  547. nodeEOC->setPosition(fLeafCount++);
  548. //
  549. // Ok, so now we have to iterate the new tree and do a little more work
  550. // now that we know the leaf count. One thing we need to do is to
  551. // calculate the first and last position sets of each node. This is
  552. // cached away in each of the nodes.
  553. //
  554. // Along the way we also set the leaf count in each node as the maximum
  555. // state count. They must know this in order to create their first/last
  556. // position sets.
  557. //
  558. // We also need to build an array of references to the non-epsilon
  559. // leaf nodes. Since we iterate here the same way as we did during the
  560. // initial tree build (which built their position numbers, we will put
  561. // them in the array according to their position values.
  562. //
  563. fLeafList = (CMLeaf**) fMemoryManager->allocate(fLeafCount*sizeof(CMLeaf*)); //new CMLeaf*[fLeafCount];
  564. fLeafListType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
  565. (
  566. fLeafCount * sizeof(ContentSpecNode::NodeTypes)
  567. ); //new ContentSpecNode::NodeTypes[fLeafCount];
  568. postTreeBuildInit(fHeadNode, 0);
  569. //
  570. // And, moving onward... We now need to build the follow position sets
  571. // for all the nodes. So we allocate an array of pointers to state sets,
  572. // one for each leaf node (i.e. each significant DFA position.)
  573. //
  574. fFollowList = (CMStateSet**) fMemoryManager->allocate
  575. (
  576. fLeafCount * sizeof(CMStateSet*)
  577. ); //new CMStateSet*[fLeafCount];
  578. for (index = 0; index < fLeafCount; index++)
  579. fFollowList[index] = new (fMemoryManager) CMStateSet(fLeafCount, fMemoryManager);
  580. calcFollowList(fHeadNode);
  581. //
  582. // Check to see whether this content model can handle an empty content,
  583. // which is something we need to optimize by looking now before we
  584. // throw away the info that would tell us that.
  585. //
  586. // If the left node of the head (the top level of the original content)
  587. // is nullable, then its true.
  588. //
  589. fEmptyOk = nodeOrgContent->isNullable();
  590. //
  591. // And finally the big push... Now we build the DFA using all the states
  592. // and the tree we've built up. First we set up the various data
  593. // structures we are going to use while we do this.
  594. //
  595. // First of all we need an array of unique element ids in our content
  596. // model. For each transition table entry, we need a set of contiguous
  597. // indices to represent the transitions for a particular input element.
  598. // So we need to a zero based range of indexes that map to element types.
  599. // This element map provides that mapping.
  600. //
  601. fElemMap = (QName**) fMemoryManager->allocate
  602. (
  603. fLeafCount * sizeof(QName*)
  604. ); //new QName*[fLeafCount];
  605. fElemMapType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
  606. (
  607. fLeafCount * sizeof(ContentSpecNode::NodeTypes)
  608. ); //new ContentSpecNode::NodeTypes[fLeafCount];
  609. fElemMapSize = 0;
  610. for (unsigned int outIndex = 0; outIndex < fLeafCount; outIndex++)
  611. {
  612. fElemMap[outIndex] = new (fMemoryManager) QName(fMemoryManager);
  613. if ( (fLeafListType[outIndex] & 0x0f) != ContentSpecNode::Leaf )
  614. if (!fLeafNameTypeVector)
  615. fLeafNameTypeVector = new (fMemoryManager) ContentLeafNameTypeVector(fMemoryManager);
  616. // Get the current leaf's element index
  617. const QName* element = fLeafList[outIndex]->getElement();
  618. const XMLCh* elementRawName = 0;
  619. if (fDTD && element)
  620. elementRawName = element->getRawName();
  621. // See if the current leaf node's element index is in the list
  622. unsigned int inIndex = 0;
  623. for (; inIndex < fElemMapSize; inIndex++)
  624. {
  625. const QName* inElem = fElemMap[inIndex];
  626. if (fDTD) {
  627. if (XMLString::equals(inElem->getRawName(), elementRawName)) {
  628. break;
  629. }
  630. }
  631. else {
  632. if ((fElemMapType[inIndex] == fLeafListType[outIndex]) &&
  633. (inElem->getURI() == element->getURI()) &&
  634. (XMLString::equals(inElem->getLocalPart(), element->getLocalPart()))) {
  635. break;
  636. }
  637. }
  638. }
  639. // If it was not in the list, then add it and bump the map size
  640. if (inIndex == fElemMapSize)
  641. {
  642. fElemMap[fElemMapSize]->setValues(*element);
  643. fElemMapType[fElemMapSize] = fLeafListType[outIndex];
  644. ++fElemMapSize;
  645. }
  646. }
  647. // set up the fLeafNameTypeVector object if there is one.
  648. if (fLeafNameTypeVector) {
  649. fLeafNameTypeVector->setValues(fElemMap, fElemMapType, fElemMapSize);
  650. }
  651. /***
  652. * Optimization(Jan, 2001); We sort fLeafList according to
  653. * elemIndex which is *uniquely* associated to each leaf.
  654. * We are *assuming* that each element appears in at least one leaf.
  655. **/
  656. // don't forget to delete it
  657. int *fLeafSorter = (int*) fMemoryManager->allocate
  658. (
  659. (fLeafCount + fElemMapSize) * sizeof(int)
  660. ); //new int[fLeafCount + fElemMapSize];
  661. unsigned int fSortCount = 0;
  662. for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++)
  663. {
  664. const QName* element = fElemMap[elemIndex];
  665. const XMLCh* elementRawName = 0;
  666. if (fDTD && element)
  667. elementRawName = element->getRawName();
  668. for (unsigned int leafIndex = 0; leafIndex < fLeafCount; leafIndex++)
  669. {
  670. const QName* leaf = fLeafList[leafIndex]->getElement();
  671. const int leafType = fLeafListType[leafIndex];
  672. if (fDTD) {
  673. if (XMLString::equals(leaf->getRawName(), elementRawName)) {
  674. fLeafSorter[fSortCount++] = leafIndex;
  675. }
  676. }
  677. else {
  678. if ((fElemMapType[elemIndex] == fLeafListType[leafIndex]) &&
  679. (leaf->getURI() == element->getURI()) &&
  680. (XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) {
  681. fLeafSorter[fSortCount++] = leafIndex;
  682. }
  683. }
  684. }
  685. fLeafSorter[fSortCount++] = -1;
  686. }
  687. //
  688. // Next lets create some arrays, some that that hold transient info
  689. // during the DFA build and some that are permament. These are kind of
  690. // sticky since we cannot know how big they will get, but we don't want
  691. // to use any collection type classes because of performance.
  692. //
  693. // Basically they will probably be about fLeafCount*2 on average, but can
  694. // be as large as 2^(fLeafCount*2), worst case. So we start with
  695. // fLeafCount*4 as a middle ground. This will be very unlikely to ever
  696. // have to expand though, it if does, the overhead will be somewhat ugly.
  697. //
  698. unsigned int curArraySize = fLeafCount * 4;
  699. const CMStateSet** statesToDo = (const CMStateSet**)
  700. fMemoryManager->allocate
  701. (
  702. curArraySize * sizeof(const CMStateSet*)
  703. ); //new const CMStateSet*[curArraySize];
  704. fFinalStateFlags = (bool*) fMemoryManager->allocate
  705. (
  706. curArraySize * sizeof(bool)
  707. ); //new bool[curArraySize];
  708. fTransTable = (unsigned int**) fMemoryManager->allocate
  709. (
  710. curArraySize * sizeof(unsigned int*)
  711. ); //new unsigned int*[curArraySize];
  712. //
  713. // Ok we start with the initial set as the first pos set of the head node
  714. // (which is the seq node that holds the content model and the EOC node.)
  715. //
  716. const CMStateSet* setT = new (fMemoryManager) CMStateSet(fHeadNode->getFirstPos());
  717. //
  718. // Init our two state flags. Basically the unmarked state counter is
  719. // always chasing the current state counter. When it catches up, that
  720. // means we made a pass through that did not add any new states to the
  721. // lists, at which time we are done. We could have used a expanding array
  722. // of flags which we used to mark off states as we complete them, but
  723. // this is easier though less readable maybe.
  724. //
  725. unsigned int unmarkedState = 0;
  726. unsigned int curState = 0;
  727. //
  728. // Init the first transition table entry, and put the initial state
  729. // into the states to do list, then bump the current state.
  730. //
  731. fTransTable[curState] = makeDefStateList();
  732. statesToDo[curState] = setT;
  733. curState++;
  734. //
  735. // the stateTable is an auxiliary means to fast
  736. // identification of new state created (instead
  737. // of squential loop statesToDo to find out),
  738. // while the role that statesToDo plays remain unchanged.
  739. //
  740. // TODO: in the future, we may change the 29 to something
  741. // derived from curArraySize.
  742. RefHashTableOf<XMLInteger> *stateTable =
  743. new (fMemoryManager) RefHashTableOf<XMLInteger>
  744. (
  745. curArraySize
  746. , true
  747. , new (fMemoryManager) HashCMStateSet()
  748. , fMemoryManager
  749. );
  750. //stateTable->put((CMStateSet*)setT, new (fMemoryManager) XMLInteger(0));
  751. //
  752. // Ok, almost done with the algorithm from hell... We now enter the
  753. // loop where we go until the states done counter catches up with
  754. // the states to do counter.
  755. //
  756. CMStateSet* newSet = 0;
  757. while (unmarkedState < curState)
  758. {
  759. //
  760. // Get the next unmarked state out of the list of states to do.
  761. // And get the associated transition table entry.
  762. //
  763. setT = statesToDo[unmarkedState];
  764. unsigned int* transEntry = fTransTable[unmarkedState];
  765. // Mark this one final if it contains the EOC state
  766. fFinalStateFlags[unmarkedState] = setT->getBit(fEOCPos);
  767. // Bump up the unmarked state count, marking this state done
  768. unmarkedState++;
  769. // Optimization(Jan, 2001)
  770. unsigned int sorterIndex = 0;
  771. // Optimization(Jan, 2001)
  772. // Loop through each possible input symbol in the element map
  773. for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++)
  774. {
  775. //
  776. // Build up a set of states which is the union of all of the
  777. // follow sets of DFA positions that are in the current state. If
  778. // we gave away the new set last time through then create a new
  779. // one. Otherwise, zero out the existing one.
  780. //
  781. if (!newSet)
  782. newSet = new (fMemoryManager) CMStateSet
  783. (
  784. fLeafCount
  785. , fMemoryManager
  786. );
  787. else
  788. newSet->zeroBits();
  789. #ifdef OBSOLETED
  790. // unoptimized code
  791. for (unsigned int leafIndex = 0; leafIndex < fLeafCount; leafIndex++)
  792. {
  793. // If this leaf index (DFA position) is in the current set...
  794. if (setT->getBit(leafIndex))
  795. {
  796. //
  797. // If this leaf is the current input symbol, then we want
  798. // to add its follow list to the set of states to transition
  799. // to from the current state.
  800. //
  801. const QName* leaf = fLeafList[leafIndex]->getElement();
  802. const QName* element = fElemMap[elemIndex];
  803. if (fDTD) {
  804. if (XMLString::equals(leaf->getRawName(), element->getRawName())) {
  805. *newSet |= *fFollowList[leafIndex];
  806. }
  807. }
  808. else {
  809. if ((leaf->getURI() == element->getURI()) &&
  810. (XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) {
  811. *newSet |= *fFollowList[leafIndex];
  812. }
  813. }
  814. }
  815. } // for leafIndex
  816. #endif
  817. // Optimization(Jan, 2001)
  818. int leafIndex = fLeafSorter[sorterIndex++];
  819. while (leafIndex != -1)
  820. {
  821. // If this leaf index (DFA position) is in the current set...
  822. if (setT->getBit(leafIndex))
  823. {
  824. //
  825. // If this leaf is the current input symbol, then we
  826. // want to add its follow list to the set of states to
  827. // transition to from the current state.
  828. //
  829. *newSet |= *fFollowList[leafIndex];
  830. }
  831. leafIndex = fLeafSorter[sorterIndex++];
  832. } // while (leafIndex != -1)
  833. //
  834. // If this new set is not empty, then see if its in the list
  835. // of states to do. If not, then add it.
  836. //
  837. if (!newSet->isEmpty())
  838. {
  839. //
  840. // Search the 'states to do' list to see if this new
  841. // state set is already in there.
  842. //
  843. /***
  844. unsigned int stateIndex = 0;
  845. for (; stateIndex < curState; stateIndex++)
  846. {
  847. if (*statesToDo[stateIndex] == *newSet)
  848. break;
  849. }
  850. ***/
  851. XMLInteger *stateObj = (XMLInteger*) (stateTable->get(newSet));
  852. unsigned int stateIndex = (stateObj == 0 ? curState : stateObj->intValue());
  853. // If we did not find it, then add it
  854. if (stateIndex == curState)
  855. {
  856. //
  857. // Put this new state into the states to do and init
  858. // a new entry at the same index in the transition
  859. // table.
  860. //
  861. statesToDo[curState] = newSet;
  862. fTransTable[curState] = makeDefStateList();
  863. stateTable->put
  864. (
  865. newSet
  866. , new (fMemoryManager) XMLInteger(curState)
  867. );
  868. // We now have a new state to do so bump the count
  869. curState++;
  870. //
  871. // Null out the new set to indicate we adopted it. This
  872. // will cause the creation of a new set on the next time
  873. // around the loop.
  874. //
  875. newSet = 0;
  876. }
  877. //
  878. // Now set this state in the transition table's entry for this
  879. // element (using its index), with the DFA state we will move
  880. // to from the current state when we see this input element.
  881. //
  882. transEntry[elemIndex] = stateIndex;
  883. // Expand the arrays if we're full
  884. if (curState == curArraySize)
  885. {
  886. //
  887. // Yikes, we overflowed the initial array size, so we've
  888. // got to expand all of these arrays. So adjust up the
  889. // size by 50% and allocate new arrays.
  890. //
  891. const unsigned int newSize = (unsigned int)(curArraySize * 1.5);
  892. const CMStateSet** newToDo = (const CMStateSet**)
  893. fMemoryManager->allocate
  894. (
  895. newSize * sizeof(const CMStateSet*)
  896. ); //new const CMStateSet*[newSize];
  897. bool* newFinalFlags = (bool*) fMemoryManager->allocate
  898. (
  899. newSize * sizeof(bool)
  900. ); //new bool[newSize];
  901. unsigned int** newTransTable = (unsigned int**)
  902. fMemoryManager->allocate
  903. (
  904. newSize * sizeof(unsigned int*)
  905. ); //new unsigned int*[newSize];
  906. // Copy over all of the existing content
  907. for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++)
  908. {
  909. newToDo[expIndex] = statesToDo[expIndex];
  910. newFinalFlags[expIndex] = fFinalStateFlags[expIndex];
  911. newTransTable[expIndex] = fTransTable[expIndex];
  912. }
  913. // Clean up the old stuff
  914. fMemoryManager->deallocate(statesToDo); //delete [] statesToDo;
  915. fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags;
  916. fMemoryManager->deallocate(fTransTable); //delete [] fTransTable;
  917. // Store the new array size and pointers
  918. curArraySize = newSize;
  919. statesToDo = newToDo;
  920. fFinalStateFlags = newFinalFlags;
  921. fTransTable = newTransTable;
  922. } //if (curState == curArraySize)
  923. } //if (!newSet->isEmpty())
  924. } // for elemIndex
  925. } //while
  926. // Store the current state count in the trans table size
  927. fTransTableSize = curState;
  928. // If the last temp set was not stored, then clean it up
  929. if (newSet)
  930. delete newSet;
  931. //
  932. // Now we can clean up all of the temporary data that was needed during
  933. // DFA build.
  934. //
  935. //
  936. // Note on memory leak: Bugzilla#2707:
  937. // ===================================
  938. // The CMBinary, pointed to by fHeadNode, shall be released by
  939. // deleted by itself.
  940. //
  941. // Change has been made to postTreeBuildInit() such that fLeafList[]
  942. // would maintain its **OWN** copy of CMLeaf to avoid double deletion
  943. // of CMLeaf.
  944. //
  945. delete fHeadNode;
  946. for (index = 0; index < fLeafCount; index++)
  947. delete fFollowList[index];
  948. fMemoryManager->deallocate(fFollowList); //delete [] fFollowList;
  949. //
  950. // removeAll() will delete all data, XMLInteger,
  951. // while the keys are to be deleted by the
  952. // deletion of statesToDo.
  953. //
  954. delete stateTable;
  955. for (index = 0; index < curState; index++)
  956. delete (CMStateSet*)statesToDo[index];
  957. fMemoryManager->deallocate(statesToDo); //delete [] statesToDo;
  958. for (index = 0; index < fLeafCount; index++)
  959. delete fLeafList[index];
  960. fMemoryManager->deallocate(fLeafList); //delete [] fLeafList;
  961. fMemoryManager->deallocate(fLeafSorter); //delete [] fLeafSorter;
  962. }
  963. CMNode* DFAContentModel::buildSyntaxTree(ContentSpecNode* const curNode)
  964. {
  965. // Initialize a return node pointer
  966. CMNode* retNode = 0;
  967. // Get the spec type of the passed node
  968. const ContentSpecNode::NodeTypes curType = curNode->getType();
  969. if ((curType & 0x0f) == ContentSpecNode::Any
  970. || (curType & 0x0f) == ContentSpecNode::Any_Other
  971. || (curType & 0x0f) == ContentSpecNode::Any_NS)
  972. {
  973. retNode = new (fMemoryManager) CMAny
  974. (
  975. curType
  976. , curNode->getElement()->getURI()
  977. , fLeafCount++
  978. , fMemoryManager
  979. );
  980. }
  981. else if (curType == ContentSpecNode::Leaf)
  982. {
  983. //
  984. // Create a new leaf node, and pass it the current leaf count, which
  985. // is its DFA state position. Bump the leaf count after storing it.
  986. // This makes the positions zero based since we store first and then
  987. // increment.
  988. //
  989. retNode = new (fMemoryManager) CMLeaf
  990. (
  991. curNode->getElement()
  992. , fLeafCount++
  993. , fMemoryManager
  994. );
  995. }
  996. else
  997. {
  998. //
  999. // Its not a leaf, so we have to recurse its left and maybe right
  1000. // nodes. Save both values before we recurse and trash the node.
  1001. //
  1002. ContentSpecNode* leftNode = curNode->getFirst();
  1003. ContentSpecNode* rightNode = curNode->getSecond();
  1004. if (((curType & 0x0f) == ContentSpecNode::Choice)
  1005. || ((curType & 0x0f) == ContentSpecNode::Sequence))
  1006. {
  1007. //
  1008. // Recurse on both children, and return a binary op node with the
  1009. // two created sub nodes as its children. The node type is the
  1010. // same type as the source.
  1011. //
  1012. CMNode* newLeft = buildSyntaxTree(leftNode);
  1013. CMNode* newRight = buildSyntaxTree(rightNode);
  1014. retNode = new (fMemoryManager) CMBinaryOp
  1015. (
  1016. curType
  1017. , newLeft
  1018. , newRight
  1019. , fMemoryManager
  1020. );
  1021. }
  1022. else if (curType == ContentSpecNode::ZeroOrMore
  1023. || curType == ContentSpecNode::ZeroOrOne
  1024. || curType == ContentSpecNode::OneOrMore)
  1025. {
  1026. // This one is fine as is, just change to our form
  1027. retNode = new (fMemoryManager) CMUnaryOp
  1028. (
  1029. curType
  1030. , buildSyntaxTree(leftNode)
  1031. , fMemoryManager
  1032. );
  1033. }
  1034. else
  1035. {
  1036. ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  1037. }
  1038. }
  1039. return retNode;
  1040. }
  1041. void DFAContentModel::calcFollowList(CMNode* const curNode)
  1042. {
  1043. // Get the spec type of the passed node
  1044. const ContentSpecNode::NodeTypes curType = curNode->getType();
  1045. if ((curType & 0x0f) == ContentSpecNode::Choice)
  1046. {
  1047. // Just recurse
  1048. calcFollowList(((CMBinaryOp*)curNode)->getLeft());
  1049. calcFollowList(((CMBinaryOp*)curNode)->getRight());
  1050. }
  1051. else if ((curType & 0x0f) == ContentSpecNode::Sequence)
  1052. {
  1053. // Recurse before we process this node
  1054. calcFollowList(((CMBinaryOp*)curNode)->getLeft());
  1055. calcFollowList(((CMBinaryOp*)curNode)->getRight());
  1056. //
  1057. // Now handle our level. We use our left child's last pos set and our
  1058. // right child's first pos set, so get them now for convenience.
  1059. //
  1060. const CMStateSet& last = ((CMBinaryOp*)curNode)->getLeft()->getLastPos();
  1061. const CMStateSet& first = ((CMBinaryOp*)curNode)->getRight()->getFirstPos();
  1062. //
  1063. // Now, for every position which is in our left child's last set
  1064. // add all of the states in our right child's first set to the
  1065. // follow set for that position.
  1066. //
  1067. for (unsigned int index = 0; index < fLeafCount; index++)
  1068. {
  1069. if (last.getBit(index))
  1070. *fFollowList[index] |= first;
  1071. }
  1072. }
  1073. else if (curType == ContentSpecNode::ZeroOrMore ||
  1074. curType == ContentSpecNode::OneOrMore )
  1075. {
  1076. // Recurse first
  1077. calcFollowList(((CMUnaryOp*)curNode)->getChild());
  1078. //
  1079. // Now handle our level. We use our own first and last position
  1080. // sets, so get them up front.
  1081. //
  1082. const CMStateSet& first = curNode->getFirstPos();
  1083. const CMStateSet& last = curNode->getLastPos();
  1084. //
  1085. // For every position which is in our last position set, add all
  1086. // of our first position states to the follow set for that
  1087. // position.
  1088. //
  1089. for (unsigned int index = 0; index < fLeafCount; index++)
  1090. {
  1091. if (last.getBit(index))
  1092. *fFollowList[index] |= first;
  1093. }
  1094. }
  1095. else if (curType == ContentSpecNode::ZeroOrOne)
  1096. {
  1097. // Recurse only
  1098. calcFollowList(((CMUnaryOp*)curNode)->getChild());
  1099. }
  1100. }
  1101. //
  1102. // gInvalidTrans is used to represent bad transitions in the transition table
  1103. // entry for each state. So each entry is initialized to that value. This
  1104. // method creates a new entry and initializes it.
  1105. //
  1106. unsigned int* DFAContentModel::makeDefStateList() const
  1107. {
  1108. unsigned int* retArray = (unsigned int*) fMemoryManager->allocate
  1109. (
  1110. fElemMapSize * sizeof(unsigned int)
  1111. ); //new unsigned int[fElemMapSize];
  1112. for (unsigned int index = 0; index < fElemMapSize; index++)
  1113. retArray[index] = XMLContentModel::gInvalidTrans;
  1114. return retArray;
  1115. }
  1116. int DFAContentModel::postTreeBuildInit( CMNode* const nodeCur
  1117. , const unsigned int curIndex)
  1118. {
  1119. // Set the maximum states on this node
  1120. nodeCur->setMaxStates(fLeafCount);
  1121. // Get the spec type of the passed node
  1122. const ContentSpecNode::NodeTypes curType = nodeCur->getType();
  1123. // Get a copy of the index we can modify
  1124. unsigned int newIndex = curIndex;
  1125. // Recurse as required
  1126. if ( ((curType & 0x0f) == ContentSpecNode::Any) ||
  1127. ((curType & 0x0f) == ContentSpecNode::Any_NS) ||
  1128. ((curType & 0x0f) == ContentSpecNode::Any_Other) )
  1129. {
  1130. fLeafList[newIndex] = new (fMemoryManager) CMLeaf
  1131. (
  1132. new (fMemoryManager) QName
  1133. (
  1134. XMLUni::fgZeroLenString
  1135. , XMLUni::fgZeroLenString
  1136. , ((CMAny*) nodeCur)->getURI()
  1137. , fMemoryManager
  1138. )
  1139. , ((CMAny*)nodeCur)->getPosition()
  1140. , true
  1141. , fMemoryManager
  1142. );
  1143. fLeafListType[newIndex] = curType;
  1144. ++newIndex;
  1145. }
  1146. else if (((curType & 0x0f) == ContentSpecNode::Choice)
  1147. || ((curType & 0x0f) == ContentSpecNode::Sequence))
  1148. {
  1149. newIndex = postTreeBuildInit(((CMBinaryOp*)nodeCur)->getLeft(), newIndex);
  1150. newIndex = postTreeBuildInit(((CMBinaryOp*)nodeCur)->getRight(), newIndex);
  1151. }
  1152. else if (curType == ContentSpecNode::ZeroOrMore ||
  1153. curType == ContentSpecNode::ZeroOrOne ||
  1154. curType == ContentSpecNode::OneOrMore)
  1155. {
  1156. newIndex = postTreeBuildInit(((CMUnaryOp*)nodeCur)->getChild(), newIndex);
  1157. }
  1158. else if (curType == ContentSpecNode::Leaf)
  1159. {
  1160. //
  1161. // Put this node in the leaf list at the current index if its
  1162. // a non-epsilon leaf.
  1163. //
  1164. if (((CMLeaf*)nodeCur)->getElement()->getURI() != XMLContentModel::gEpsilonFakeId)
  1165. {
  1166. //
  1167. // fLeafList make its own copy of the CMLeaf, so that
  1168. // delete[] fLeafList and delete the owner of the nodeCur
  1169. // will NOT delete the nodeCur --twice--,
  1170. // thuse to make delete the owner of the nodeCur possible.
  1171. //
  1172. fLeafList[newIndex] = new (fMemoryManager) CMLeaf
  1173. (
  1174. ((CMLeaf*)nodeCur)->getElement()
  1175. , ((CMLeaf*)nodeCur)->getPosition()
  1176. , fMemoryManager
  1177. );
  1178. fLeafListType[newIndex] = ContentSpecNode::Leaf;
  1179. ++newIndex;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  1185. }
  1186. return newIndex;
  1187. }
  1188. ContentLeafNameTypeVector* DFAContentModel::getContentLeafNameTypeVector() const
  1189. {
  1190. //later change it to return the data member
  1191. return fLeafNameTypeVector;
  1192. };
  1193. void DFAContentModel::checkUniqueParticleAttribution (SchemaGrammar* const pGrammar,
  1194. GrammarResolver* const pGrammarResolver,
  1195. XMLStringPool* const pStringPool,
  1196. XMLValidator* const pValidator,
  1197. unsigned int* const pContentSpecOrgURI)
  1198. {
  1199. SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
  1200. unsigned int i, j, k;
  1201. // Rename the URI back
  1202. for (i = 0; i < fElemMapSize; i++) {
  1203. unsigned int orgURIIndex = fElemMap[i]->getURI();
  1204. if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
  1205. (orgURIIndex != XMLContentModel::gEpsilonFakeId) &&
  1206. (orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
  1207. (orgURIIndex != XMLElementDecl::fgPCDataElemId)) {
  1208. fElemMap[i]->setURI(pContentSpecOrgURI[orgURIIndex]);
  1209. }
  1210. }
  1211. // Unique Particle Attribution
  1212. // store the confl…

Large files files are truncated, but you can click here to view the full file