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

词法分析

开发平台:

Visual C++

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