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 + -
显示快捷键?