dfacontentmodel.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,381 行 · 第 1/4 页

CPP
1,381
字号
                        nextState = fTransTable[curState][elemIndex];                        if (nextState != XMLContentModel::gInvalidTrans)                            break;                    }                }                else if ((type & 0x0f)== ContentSpecNode::Any)                {                    nextState = fTransTable[curState][elemIndex];                    if (nextState != XMLContentModel::gInvalidTrans)                            break;                }                else if ((type & 0x0f) == ContentSpecNode::Any_NS)                {                    if (inElem->getURI() == curElem->getURI())                    {                        nextState = fTransTable[curState][elemIndex];                        if (nextState != XMLContentModel::gInvalidTrans)                            break;                    }                }                else if ((type & 0x0f) == ContentSpecNode::Any_Other)                {                    if (inElem->getURI() != curElem->getURI()) {                        nextState = fTransTable[curState][elemIndex];                        if (nextState != XMLContentModel::gInvalidTrans)                            break;                    }                }            }        }//for elemIndex        // If "nextState" is -1, we found a match, but the transition is invalid        if (nextState == XMLContentModel::gInvalidTrans)            return childIndex;        // If we didn't find it, then obviously not valid        if (elemIndex == fElemMapSize)            return childIndex;        curState = nextState;        nextState = 0;    }//for childIndex    //    //  We transitioned all the way through the input list. However, that    //  does not mean that we ended in a final state. So check whether    //  our ending state is a final state.    //    if (!fFinalStateFlags[curState])        return childIndex;    //success    return -1;}int DFAContentModel::validateContentSpecial(QName** const          children                                            , const unsigned int      childCount                                            , const unsigned int                                            , GrammarResolver*  const pGrammarResolver                                            , XMLStringPool*    const pStringPool) const{    SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);    if (childCount == 0)        return fEmptyOk ? -1 : 0;    //    //  Lets loop through the children in the array and move our way    //  through the states. Note that we use the fElemMap array to map    //  an element index to a state index.    //    unsigned int curState = 0;    unsigned int nextState = 0;    unsigned int childIndex = 0;    for (; childIndex < childCount; childIndex++)    {        // Get the current element index out        QName* curElem = children[childIndex];        // If this is text in a Schema mixed content model, skip it.        if ( fIsMixed &&            ( curElem->getURI() == XMLElementDecl::fgPCDataElemId))            continue;        // Look up this child in our element map        unsigned int elemIndex = 0;        for (; elemIndex < fElemMapSize; elemIndex++)        {            QName* inElem  = fElemMap[elemIndex];            ContentSpecNode::NodeTypes type = fElemMapType[elemIndex];            if (type == ContentSpecNode::Leaf)            {                if (comparator.isEquivalentTo(curElem, inElem) )                {                    nextState = fTransTable[curState][elemIndex];                    if (nextState != XMLContentModel::gInvalidTrans)                        break;                }            }            else if ((type & 0x0f)== ContentSpecNode::Any)            {                nextState = fTransTable[curState][elemIndex];                if (nextState != XMLContentModel::gInvalidTrans)                        break;            }            else if ((type & 0x0f) == ContentSpecNode::Any_NS)            {                if (inElem->getURI() == curElem->getURI())                {                    nextState = fTransTable[curState][elemIndex];                    if (nextState != XMLContentModel::gInvalidTrans)                        break;                }            }            else if ((type & 0x0f) == ContentSpecNode::Any_Other)            {                if (inElem->getURI() != curElem->getURI())                {                    nextState = fTransTable[curState][elemIndex];                    if (nextState != XMLContentModel::gInvalidTrans)                        break;                }            }        }//for elemIndex        // If "nextState" is -1, we found a match, but the transition is invalid        if (nextState == XMLContentModel::gInvalidTrans)            return childIndex;        // If we didn't find it, then obviously not valid        if (elemIndex == fElemMapSize)            return childIndex;        curState = nextState;        nextState = 0;    }//for childIndex    //    //  We transitioned all the way through the input list. However, that    //  does not mean that we ended in a final state. So check whether    //  our ending state is a final state.    //    if (!fFinalStateFlags[curState])        return childIndex;    //success    return -1;}// ---------------------------------------------------------------------------//  DFAContentModel: Private helper methods// ---------------------------------------------------------------------------void DFAContentModel::buildDFA(ContentSpecNode* const curNode){    unsigned int index;    //    //  The first step we need to take is to rewrite the content model using    //  our CMNode objects, and in the process get rid of any repetition short    //  cuts, converting them into '*' style repetitions or getting rid of    //  repetitions altogether.    //    //  The conversions done are:    //    //  x+ -> (x|x*)    //  x? -> (x|epsilon)    //    //  This is a relatively complex scenario. What is happening is that we    //  create a top level binary node of which the special EOC value is set    //  as the right side node. The the left side is set to the rewritten    //  syntax tree. The source is the original content model info from the    //  decl pool. The rewrite is done by buildSyntaxTree() which recurses the    //  decl pool's content of the element and builds a new tree in the    //  process.    //    //  Note that, during this operation, we set each non-epsilon leaf node's    //  DFA state position and count the number of such leafs, which is left    //  in the fLeafCount member.    //    CMLeaf* nodeEOC = new (fMemoryManager) CMLeaf    (        new (fMemoryManager) QName        (            XMLUni::fgZeroLenString            , XMLUni::fgZeroLenString            , XMLContentModel::gEOCFakeId            , fMemoryManager        )        , ~0        , true        , fMemoryManager    );    CMNode* nodeOrgContent = buildSyntaxTree(curNode);    fHeadNode = new (fMemoryManager) CMBinaryOp    (        ContentSpecNode::Sequence        , nodeOrgContent        , nodeEOC        , fMemoryManager    );    //    //  And handle specially the EOC node, which also must be numbered and    //  counted as a non-epsilon leaf node. It could not be handled in the    //  above tree build because it was created before all that started. We    //  save the EOC position since its used during the DFA building loop.    //    fEOCPos = fLeafCount;    nodeEOC->setPosition(fLeafCount++);    //    //  Ok, so now we have to iterate the new tree and do a little more work    //  now that we know the leaf count. One thing we need to do is to    //  calculate the first and last position sets of each node. This is    //  cached away in each of the nodes.    //    //  Along the way we also set the leaf count in each node as the maximum    //  state count. They must know this in order to create their first/last    //  position sets.    //    //  We also need to build an array of references to the non-epsilon    //  leaf nodes. Since we iterate here the same way as we did during the    //  initial tree build (which built their position numbers, we will put    //  them in the array according to their position values.    //    fLeafList = (CMLeaf**) fMemoryManager->allocate(fLeafCount*sizeof(CMLeaf*)); //new CMLeaf*[fLeafCount];    fLeafListType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate    (        fLeafCount * sizeof(ContentSpecNode::NodeTypes)    ); //new ContentSpecNode::NodeTypes[fLeafCount];    postTreeBuildInit(fHeadNode, 0);    //    //  And, moving onward... We now need to build the follow position sets    //  for all the nodes. So we allocate an array of pointers to state sets,    //  one for each leaf node (i.e. each significant DFA position.)    //    fFollowList = (CMStateSet**) fMemoryManager->allocate    (        fLeafCount * sizeof(CMStateSet*)    ); //new CMStateSet*[fLeafCount];    for (index = 0; index < fLeafCount; index++)        fFollowList[index] = new (fMemoryManager) CMStateSet(fLeafCount, fMemoryManager);    calcFollowList(fHeadNode);    //    //  Check to see whether this content model can handle an empty content,    //  which is something we need to optimize by looking now before we    //  throw away the info that would tell us that.    //    //  If the left node of the head (the top level of the original content)    //  is nullable, then its true.    //    fEmptyOk = nodeOrgContent->isNullable();    //    //  And finally the big push... Now we build the DFA using all the states    //  and the tree we've built up. First we set up the various data    //  structures we are going to use while we do this.    //    //  First of all we need an array of unique element ids in our content    //  model. For each transition table entry, we need a set of contiguous    //  indices to represent the transitions for a particular input element.    //  So we need to a zero based range of indexes that map to element types.    //  This element map provides that mapping.    //    fElemMap = (QName**) fMemoryManager->allocate    (        fLeafCount * sizeof(QName*)    ); //new QName*[fLeafCount];    fElemMapType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate    (        fLeafCount * sizeof(ContentSpecNode::NodeTypes)    ); //new ContentSpecNode::NodeTypes[fLeafCount];    fElemMapSize = 0;    for (unsigned int outIndex = 0; outIndex < fLeafCount; outIndex++)    {        fElemMap[outIndex] = new (fMemoryManager) QName(fMemoryManager);        if ( (fLeafListType[outIndex] & 0x0f) != ContentSpecNode::Leaf )            if (!fLeafNameTypeVector)                fLeafNameTypeVector = new (fMemoryManager) ContentLeafNameTypeVector(fMemoryManager);        // Get the current leaf's element index        const QName* element = fLeafList[outIndex]->getElement();        const XMLCh* elementRawName = 0;        if (fDTD && element)            elementRawName = element->getRawName();        // See if the current leaf node's element index is in the list        unsigned int inIndex = 0;        for (; inIndex < fElemMapSize; inIndex++)        {            const QName* inElem = fElemMap[inIndex];            if (fDTD) {                if (XMLString::equals(inElem->getRawName(), elementRawName)) {                    break;                }            }            else {                if ((fElemMapType[inIndex] == fLeafListType[outIndex]) &&                    (inElem->getURI() == element->getURI()) &&                    (XMLString::equals(inElem->getLocalPart(), element->getLocalPart()))) {                    break;                }            }        }        // If it was not in the list, then add it and bump the map size        if (inIndex == fElemMapSize)        {            fElemMap[fElemMapSize]->setValues(*element);            fElemMapType[fElemMapSize] = fLeafListType[outIndex];            ++fElemMapSize;        }    }    // set up the fLeafNameTypeVector object if there is one.    if (fLeafNameTypeVector) {        fLeafNameTypeVector->setValues(fElemMap, fElemMapType, fElemMapSize);    }    /***     * Optimization(Jan, 2001); We sort fLeafList according to     * elemIndex which is *uniquely* associated to each leaf.     * We are *assuming* that each element appears in at least one leaf.     **/    // don't forget to delete it    int *fLeafSorter = (int*) fMemoryManager->allocate    (        (fLeafCount + fElemMapSize) * sizeof(int)    ); //new int[fLeafCount + fElemMapSize];    unsigned int fSortCount = 0;    for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++)    {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?