Added Xerces-C++ 3.1.2

This commit is contained in:
sippeangelo
2015-12-01 10:23:50 +01:00
parent 65d3f3bc31
commit 1b478d3159
815 changed files with 262638 additions and 0 deletions
@@ -0,0 +1,378 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: AllContentModel.cpp 676911 2008-07-15 13:27:32Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/framework/XMLElementDecl.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/common/AllContentModel.hpp>
#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
#include <xercesc/validators/schema/XercesElementWildcard.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// AllContentModel: Constructors and Destructor
// ---------------------------------------------------------------------------
AllContentModel::AllContentModel( ContentSpecNode* const parentContentSpec
, const bool isMixed
, MemoryManager* const manager) :
fMemoryManager(manager)
, fCount(0)
, fChildren(0)
, fChildOptional(0)
, fNumRequired(0)
, fIsMixed(isMixed)
, fHasOptionalContent(false)
{
//
// Create a vector of unsigned ints that will be filled in with the
// ids of the child nodes. It will be expanded as needed but we give
// it an initial capacity of 64 which should be more than enough for
// 99% of the scenarios.
//
ValueVectorOf<QName*> children(64, fMemoryManager);
ValueVectorOf<bool> childOptional(64, fMemoryManager);
//
// Get the parent element's content spec. This is the head of the tree
// of nodes that describes the content model. We will iterate this
// tree.
//
ContentSpecNode* curNode = parentContentSpec;
if (!curNode)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoParentCSN, fMemoryManager);
// And now call the private recursive method that iterates the tree
if (curNode->getType() == ContentSpecNode::All
&& curNode->getMinOccurs() == 0) {
fHasOptionalContent = true;
}
buildChildList(curNode, children, childOptional);
//
// And now we know how many elements we need in our member list. So
// fill them in.
//
fCount = children.size();
fChildren = (QName**) fMemoryManager->allocate(fCount * sizeof(QName*)); //new QName*[fCount];
fChildOptional = (bool*) fMemoryManager->allocate(fCount * sizeof(bool)); //new bool[fCount];
for (unsigned int index = 0; index < fCount; index++) {
fChildren[index] = new (fMemoryManager) QName(*(children.elementAt(index)));
fChildOptional[index] = childOptional.elementAt(index);
}
}
AllContentModel::~AllContentModel()
{
for (XMLSize_t index = 0; index < fCount; index++)
delete fChildren[index];
fMemoryManager->deallocate(fChildren); //delete [] fChildren;
fMemoryManager->deallocate(fChildOptional); //delete [] fChildOptional;
}
// ---------------------------------------------------------------------------
// AllContentModel: Implementation of the ContentModel virtual interface
// ---------------------------------------------------------------------------
//
//Under the XML Schema mixed model,
//the order and number of child elements appearing in an instance
//must agree with
//the order and number of child elements specified in the model.
//
bool
AllContentModel::validateContent( QName** const children
, XMLSize_t childCount
, unsigned int
, XMLSize_t* indexFailingChild
, MemoryManager* const manager) const
{
// If <all> had minOccurs of zero and there are
// no children to validate, trivially validate
if (childCount == 0 && (fHasOptionalContent || !fNumRequired))
return true;
// keep track of the required element seen
XMLSize_t numRequiredSeen = 0;
if(childCount > 0)
{
// Check for duplicate element
bool* elementSeen = (bool*) manager->allocate(fCount*sizeof(bool)); //new bool[fCount];
const ArrayJanitor<bool> jan(elementSeen, manager);
// initialize the array
for (XMLSize_t i = 0; i < fCount; i++)
elementSeen[i] = false;
for (XMLSize_t outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
const QName* curChild = children[outIndex];
// If it's PCDATA, then we just accept that
if (fIsMixed && curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
// And try to find it in our list
XMLSize_t inIndex = 0;
for (; inIndex < fCount; inIndex++)
{
const QName* inChild = fChildren[inIndex];
if ((inChild->getURI() == curChild->getURI()) &&
(XMLString::equals(inChild->getLocalPart(), curChild->getLocalPart()))) {
// found it
// If this element was seen already, indicate an error was
// found at the duplicate index.
if (elementSeen[inIndex]) {
*indexFailingChild=outIndex;
return false;
}
else
elementSeen[inIndex] = true;
if (!fChildOptional[inIndex])
numRequiredSeen++;
break;
}
}
// We did not find this one, so the validation failed
if (inIndex == fCount) {
*indexFailingChild=outIndex;
return false;
}
}
}
// Were all the required elements of the <all> encountered?
if (numRequiredSeen != fNumRequired) {
*indexFailingChild=childCount;
return false;
}
// Everything seems to be ok, so return success
return true;
}
bool AllContentModel::validateContentSpecial(QName** const children
, XMLSize_t childCount
, unsigned int
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const manager) const
{
// If <all> had minOccurs of zero and there are
// no children to validate, trivially validate
if (childCount == 0 && (fHasOptionalContent || !fNumRequired))
return true;
// keep track of the required element seen
XMLSize_t numRequiredSeen = 0;
if(childCount > 0)
{
SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
// Check for duplicate element
bool* elementSeen = (bool*) manager->allocate(fCount*sizeof(bool)); //new bool[fCount];
const ArrayJanitor<bool> jan(elementSeen, manager);
// initialize the array
for (XMLSize_t i = 0; i < fCount; i++)
elementSeen[i] = false;
for (XMLSize_t outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
QName* const curChild = children[outIndex];
// If it's PCDATA, then we just accept that
if (fIsMixed && curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
// And try to find it in our list
XMLSize_t inIndex = 0;
for (; inIndex < fCount; inIndex++)
{
QName* const inChild = fChildren[inIndex];
if ( comparator.isEquivalentTo(curChild, inChild)) {
// match
// If this element was seen already, indicate an error was
// found at the duplicate index.
if (elementSeen[inIndex]) {
*indexFailingChild=outIndex;
return false;
}
else
elementSeen[inIndex] = true;
if (!fChildOptional[inIndex])
numRequiredSeen++;
break;
}
}
// We did not find this one, so the validation failed
if (inIndex == fCount) {
*indexFailingChild=outIndex;
return false;
}
}
}
// Were all the required elements of the <all> encountered?
if (numRequiredSeen != fNumRequired) {
*indexFailingChild=childCount;
return false;
}
// Everything seems to be ok, so return success
return true;
}
void AllContentModel::checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName /*= 0*/
)
{
SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
XMLSize_t i, j;
// rename back
for (i = 0; i < fCount; i++) {
unsigned int orgURIIndex = fChildren[i]->getURI();
fChildren[i]->setURI(pContentSpecOrgURI[orgURIIndex]);
}
// check whether there is conflict between any two leaves
for (i = 0; i < fCount; i++) {
for (j = i+1; j < fCount; j++) {
// If this is text in a Schema mixed content model, skip it.
if ( fIsMixed &&
(( fChildren[i]->getURI() == XMLElementDecl::fgPCDataElemId) ||
( fChildren[j]->getURI() == XMLElementDecl::fgPCDataElemId)))
continue;
if (XercesElementWildcard::conflict(pGrammar,
ContentSpecNode::Leaf,
fChildren[i],
ContentSpecNode::Leaf,
fChildren[j],
&comparator)) {
pValidator->emitError(XMLValid::UniqueParticleAttributionFail,
pComplexTypeName,
fChildren[i]->getRawName(),
fChildren[j]->getRawName());
}
}
}
}
// ---------------------------------------------------------------------------
// AllContentModel: Private helper methods
// ---------------------------------------------------------------------------
void
AllContentModel::buildChildList(ContentSpecNode* const curNode
, ValueVectorOf<QName*>& toFill
, ValueVectorOf<bool>& toOptional)
{
// Get the type of spec node our current node is
const ContentSpecNode::NodeTypes curType = curNode->getType();
if (curType == ContentSpecNode::All)
{
// Get both the child node pointers
ContentSpecNode* leftNode = curNode->getFirst();
ContentSpecNode* rightNode = curNode->getSecond();
// Recurse on the left and right nodes
buildChildList(leftNode, toFill, toOptional);
if(rightNode)
buildChildList(rightNode, toFill, toOptional);
}
else if (curType == ContentSpecNode::Leaf)
{
// At leaf, add the element to list of elements permitted in the all
toFill.addElement(curNode->getElement());
toOptional.addElement(false);
fNumRequired++;
}
else if (curType == ContentSpecNode::ZeroOrOne)
{
// At ZERO_OR_ONE node, subtree must be an element
// that was specified with minOccurs=0, maxOccurs=1
ContentSpecNode* leftNode = curNode->getFirst();
if (leftNode->getType() != ContentSpecNode::Leaf)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
toFill.addElement(leftNode->getElement());
toOptional.addElement(true);
}
// only allow ZeroOrMore when it's the father of a Loop
else if (curType == ContentSpecNode::ZeroOrMore &&
curNode->getFirst()!=0 &&
curNode->getFirst()->getType()==ContentSpecNode::Loop)
{
ContentSpecNode* leftNode = curNode->getFirst();
buildChildList(leftNode, toFill, toOptional);
}
else if (curType == ContentSpecNode::Loop)
{
// At leaf, add the element to list of elements permitted in the all
int i;
for(i=0;i<curNode->getMinOccurs();i++)
{
toFill.addElement(curNode->getElement());
toOptional.addElement(false);
fNumRequired++;
}
if(curNode->getMaxOccurs()!=-1)
for(i=0;i<(curNode->getMaxOccurs() - curNode->getMinOccurs());i++)
{
toFill.addElement(curNode->getElement());
toOptional.addElement(true);
}
}
else
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,177 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: AllContentModel.hpp 901107 2010-01-20 08:45:02Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_ALLCONTENTMODEL_HPP)
#define XERCESC_INCLUDE_GUARD_ALLCONTENTMODEL_HPP
#include <xercesc/framework/XMLContentModel.hpp>
#include <xercesc/util/ValueVectorOf.hpp>
#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class ContentSpecNode;
//
// AllContentModel is a derivative of the abstract content model base
// class that handles the special case of <all> feature in schema. If a model
// is <all>, all non-optional children must appear
//
// So, all we have to do is to keep an array of the possible children and
// validate by just looking up each child being validated by looking it up
// in the list, and make sure all non-optional children appear.
//
class AllContentModel : public XMLContentModel
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
AllContentModel
(
ContentSpecNode* const parentContentSpec
, const bool isMixed
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~AllContentModel();
// -----------------------------------------------------------------------
// Implementation of the ContentModel virtual interface
// -----------------------------------------------------------------------
virtual bool validateContent
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual bool validateContentSpecial
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual ContentLeafNameTypeVector* getContentLeafNameTypeVector() const ;
virtual unsigned int getNextState(unsigned int currentState,
XMLSize_t elementIndex) const;
virtual bool handleRepetitions( const QName* const curElem,
unsigned int curState,
unsigned int currentLoop,
unsigned int& nextState,
unsigned int& nextLoop,
XMLSize_t elementIndex,
SubstitutionGroupComparator * comparator) const;
virtual void checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName = 0
) ;
private :
// -----------------------------------------------------------------------
// Private helper methods
// -----------------------------------------------------------------------
void buildChildList
(
ContentSpecNode* const curNode
, ValueVectorOf<QName*>& toFill
, ValueVectorOf<bool>& toType
);
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
AllContentModel();
AllContentModel(const AllContentModel&);
AllContentModel& operator=(const AllContentModel&);
// -----------------------------------------------------------------------
// Private data members
//
// fCount
// The count of possible children in the fChildren member.
//
// fChildren
// The list of possible children that we have to accept. This array
// is allocated as large as needed in the constructor.
//
// fChildOptional
// The corresponding list of optional state of each child in fChildren
// True if the child is optional (i.e. minOccurs = 0).
//
// fNumRequired
// The number of required children in <all> (i.e. minOccurs = 1)
//
// fIsMixed
// AllContentModel with mixed PCDATA.
// -----------------------------------------------------------------------
MemoryManager* fMemoryManager;
XMLSize_t fCount;
QName** fChildren;
bool* fChildOptional;
unsigned int fNumRequired;
bool fIsMixed;
bool fHasOptionalContent;
};
inline ContentLeafNameTypeVector* AllContentModel::getContentLeafNameTypeVector() const
{
return 0;
}
inline unsigned int
AllContentModel::getNextState(unsigned int,
XMLSize_t) const {
return XMLContentModel::gInvalidTrans;
}
inline bool
AllContentModel::handleRepetitions( const QName* const /*curElem*/,
unsigned int /*curState*/,
unsigned int /*currentLoop*/,
unsigned int& /*nextState*/,
unsigned int& /*nextLoop*/,
XMLSize_t /*elementIndex*/,
SubstitutionGroupComparator * /*comparator*/) const
{
return true;
}
XERCES_CPP_NAMESPACE_END
#endif
+110
View File
@@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMAny.cpp 677396 2008-07-16 19:36:20Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/validators/common/CMStateSet.hpp>
#include <xercesc/validators/common/CMAny.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// CMUnaryOp: Constructors and Destructor
// ---------------------------------------------------------------------------
CMAny::CMAny( ContentSpecNode::NodeTypes type
, unsigned int URI
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager) :
CMNode(type, maxStates, manager)
, fURI(URI)
, fPosition(position)
{
if ((type & 0x0f) != ContentSpecNode::Any
&& (type & 0x0f) != ContentSpecNode::Any_Other
&& (type & 0x0f) != ContentSpecNode::Any_NS)
{
ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::CM_NotValidSpecTypeForNode,
"CMAny", manager);
}
// Leaf nodes are never nullable unless its an epsilon node
fIsNullable=(fPosition == epsilonNode);
}
CMAny::~CMAny()
{
}
// ---------------------------------------------------------------------------
// Getter methods
// ---------------------------------------------------------------------------
unsigned int CMAny::getURI() const
{
return fURI;
}
unsigned int CMAny::getPosition() const
{
return fPosition;
}
// ---------------------------------------------------------------------------
// Setter methods
// ---------------------------------------------------------------------------
void CMAny::setPosition(const unsigned int newPosition)
{
fPosition = newPosition;
}
// ---------------------------------------------------------------------------
// Implementation of public CMNode virtual interface
// ---------------------------------------------------------------------------
void CMAny::orphanChild()
{
}
// ---------------------------------------------------------------------------
// Implementation of protected CMNode virtual interface
// ---------------------------------------------------------------------------
void CMAny::calcFirstPos(CMStateSet& toSet) const
{
// If we are an epsilon node, then the first pos is an empty set
if (isNullable())
toSet.zeroBits();
else
// Otherwise, its just the one bit of our position
toSet.setBit(fPosition);
}
void CMAny::calcLastPos(CMStateSet& toSet) const
{
// If we are an epsilon node, then the last pos is an empty set
if (isNullable())
toSet.zeroBits();
// Otherwise, its just the one bit of our position
else
toSet.setBit(fPosition);
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,99 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMAny.hpp 677396 2008-07-16 19:36:20Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMANY_HPP)
#define XERCESC_INCLUDE_GUARD_CMANY_HPP
#include <xercesc/validators/common/CMNode.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class CMStateSet;
class CMAny : public CMNode
{
public :
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
CMAny
(
ContentSpecNode::NodeTypes type
, unsigned int URI
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~CMAny();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
unsigned int getURI() const;
unsigned int getPosition() const;
// -----------------------------------------------------------------------
// Setter methods
// -----------------------------------------------------------------------
void setPosition(const unsigned int newPosition);
// -----------------------------------------------------------------------
// Implementation of the public CMNode virtual interface
// -----------------------------------------------------------------------
virtual void orphanChild();
protected :
// -----------------------------------------------------------------------
// Implementation of the protected CMNode virtual interface
// -----------------------------------------------------------------------
void calcFirstPos(CMStateSet& toSet) const;
void calcLastPos(CMStateSet& toSet) const;
private :
// -----------------------------------------------------------------------
// Private data members
//
// fURI;
// URI of the any content model. This value is set if the type is
// of the following:
// XMLContentSpec.CONTENTSPECNODE_ANY,
// XMLContentSpec.CONTENTSPECNODE_ANY_OTHER.
//
// fPosition
// Part of the algorithm to convert a regex directly to a DFA
// numbers each leaf sequentially. If its -1, that means its an
// epsilon node. Zero and greater are non-epsilon positions.
// -----------------------------------------------------------------------
unsigned int fURI;
unsigned int fPosition;
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMAny(const CMAny&);
CMAny& operator=(const CMAny&);
};
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,150 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMBinaryOp.cpp 677396 2008-07-16 19:36:20Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/common/CMBinaryOp.hpp>
#include <xercesc/validators/common/CMStateSet.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// CMBinaryOp: Constructors
// ---------------------------------------------------------------------------
CMBinaryOp::CMBinaryOp( ContentSpecNode::NodeTypes type
, CMNode* const leftToAdopt
, CMNode* const rightToAdopt
, unsigned int maxStates
, MemoryManager* const manager) :
CMNode(type, maxStates, manager)
, fLeftChild(leftToAdopt)
, fRightChild(rightToAdopt)
{
// Insure that its one of the types we require
if (((type & 0x0f) != ContentSpecNode::Choice)
&& ((type & 0x0f) != ContentSpecNode::Sequence))
{
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_BinOpHadUnaryType, manager);
}
//
// If its an alternation, then if either child is nullable then
// this node is nullable. If its a concatenation, then both of
// them have to be nullable.
//
if ((type & 0x0f) == ContentSpecNode::Choice)
fIsNullable=(fLeftChild->isNullable() || fRightChild->isNullable());
else
fIsNullable=(fLeftChild->isNullable() && fRightChild->isNullable());
}
CMBinaryOp::~CMBinaryOp()
{
delete fLeftChild;
delete fRightChild;
}
// ---------------------------------------------------------------------------
// CMBinaryOp: Getter methods
// ---------------------------------------------------------------------------
const CMNode* CMBinaryOp::getLeft() const
{
return fLeftChild;
}
CMNode* CMBinaryOp::getLeft()
{
return fLeftChild;
}
const CMNode* CMBinaryOp::getRight() const
{
return fRightChild;
}
CMNode* CMBinaryOp::getRight()
{
return fRightChild;
}
// ---------------------------------------------------------------------------
// CMBinaryOp: Implementation of the public CMNode virtual interface
// ---------------------------------------------------------------------------
void CMBinaryOp::orphanChild()
{
delete fLeftChild;
fLeftChild=0;
delete fRightChild;
fRightChild=0;
}
// ---------------------------------------------------------------------------
// CMBinaryOp: Implementation of the protected CMNode virtual interface
// ---------------------------------------------------------------------------
void CMBinaryOp::calcFirstPos(CMStateSet& toSet) const
{
if ((getType() & 0x0f) == ContentSpecNode::Choice)
{
// Its the the union of the first positions of our children.
toSet = fLeftChild->getFirstPos();
toSet |= fRightChild->getFirstPos();
}
else if ((getType() & 0x0f) == ContentSpecNode::Sequence)
{
//
// If our left child is nullable, then its the union of our
// children's first positions. Else is our left child's first
// positions.
//
toSet = fLeftChild->getFirstPos();
if (fLeftChild->isNullable())
toSet |= fRightChild->getFirstPos();
}
}
void CMBinaryOp::calcLastPos(CMStateSet& toSet) const
{
if ((getType() & 0x0f) == ContentSpecNode::Choice)
{
// Its the the union of the first positions of our children.
toSet = fLeftChild->getLastPos();
toSet |= fRightChild->getLastPos();
}
else if ((getType() & 0x0f) == ContentSpecNode::Sequence)
{
//
// If our right child is nullable, then its the union of our
// children's last positions. Else is our right child's last
// positions.
//
toSet = fRightChild->getLastPos();
if (fRightChild->isNullable())
toSet |= fLeftChild->getLastPos();
}
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMBinaryOp.hpp 677396 2008-07-16 19:36:20Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMBINARYOP_HPP)
#define XERCESC_INCLUDE_GUARD_CMBINARYOP_HPP
#include <xercesc/validators/common/CMNode.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class CMStateSet;
class CMBinaryOp : public CMNode
{
public :
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
CMBinaryOp
(
ContentSpecNode::NodeTypes type
, CMNode* const leftToAdopt
, CMNode* const rightToAdopt
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~CMBinaryOp();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const CMNode* getLeft() const;
CMNode* getLeft();
const CMNode* getRight() const;
CMNode* getRight();
// -----------------------------------------------------------------------
// Implementation of the public CMNode virtual interface
// -----------------------------------------------------------------------
virtual void orphanChild();
protected :
// -----------------------------------------------------------------------
// Implementation of the protected CMNode virtual interface
// -----------------------------------------------------------------------
void calcFirstPos(CMStateSet& toSet) const;
void calcLastPos(CMStateSet& toSet) const;
private :
// -----------------------------------------------------------------------
// Private data members
//
// fLeftChild
// fRightChild
// These are the references to the two nodes that are on either side
// of this binary operation. We own them both.
// -----------------------------------------------------------------------
CMNode* fLeftChild;
CMNode* fRightChild;
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMBinaryOp(const CMBinaryOp&);
CMBinaryOp& operator=(const CMBinaryOp&);
};
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,253 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMLeaf.hpp 677396 2008-07-16 19:36:20Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMLEAF_HPP)
#define XERCESC_INCLUDE_GUARD_CMLEAF_HPP
#include <xercesc/validators/common/CMNode.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class represents a leaf in the content spec node tree of an
// element's content model. It just has an element qname and a position value,
// the latter of which is used during the building of a DFA.
//
class CMLeaf : public CMNode
{
public :
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
CMLeaf
(
QName* const element
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
CMLeaf
(
QName* const element
, unsigned int position
, bool adopt
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~CMLeaf();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
QName* getElement();
const QName* getElement() const;
unsigned int getPosition() const;
virtual bool isRepeatableLeaf() const;
// -----------------------------------------------------------------------
// Setter methods
// -----------------------------------------------------------------------
void setPosition(const unsigned int newPosition);
// -----------------------------------------------------------------------
// Implementation of public CMNode virtual interface
// -----------------------------------------------------------------------
virtual void orphanChild();
protected :
// -----------------------------------------------------------------------
// Implementation of protected CMNode virtual interface
// -----------------------------------------------------------------------
void calcFirstPos(CMStateSet& toSet) const;
void calcLastPos(CMStateSet& toSet) const;
private :
// -----------------------------------------------------------------------
// Private data members
//
// fElement
// This is the element that this leaf represents.
//
// fPosition
// Part of the algorithm to convert a regex directly to a DFA
// numbers each leaf sequentially. If its -1, that means its an
// epsilon node. All others are non-epsilon positions.
//
// fAdopt
// This node is responsible for the storage of the fElement QName.
// -----------------------------------------------------------------------
QName* fElement;
unsigned int fPosition;
bool fAdopt;
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMLeaf(const CMLeaf&);
CMLeaf& operator=(const CMLeaf&);
};
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
inline CMLeaf::CMLeaf( QName* const element
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager) :
CMNode(ContentSpecNode::Leaf, maxStates, manager)
, fElement(0)
, fPosition(position)
, fAdopt(false)
{
if (!element)
{
fElement = new (fMemoryManager) QName
(
XMLUni::fgZeroLenString
, XMLUni::fgZeroLenString
, XMLElementDecl::fgInvalidElemId
, fMemoryManager
);
// We have to be responsible for this QName - override default fAdopt
fAdopt = true;
}
else
{
fElement = element;
}
// Leaf nodes are never nullable unless its an epsilon node
fIsNullable=(fPosition == epsilonNode);
}
inline CMLeaf::CMLeaf( QName* const element
, unsigned int position
, bool adopt
, unsigned int maxStates
, MemoryManager* const manager) :
CMNode(ContentSpecNode::Leaf, maxStates, manager)
, fElement(0)
, fPosition(position)
, fAdopt(adopt)
{
if (!element)
{
fElement = new (fMemoryManager) QName
(
XMLUni::fgZeroLenString
, XMLUni::fgZeroLenString
, XMLElementDecl::fgInvalidElemId
, fMemoryManager
);
// We have to be responsible for this QName - override adopt parameter
fAdopt = true;
}
else
{
fElement = element;
}
// Leaf nodes are never nullable unless its an epsilon node
fIsNullable=(fPosition == epsilonNode);
}
inline CMLeaf::~CMLeaf()
{
if (fAdopt)
delete fElement;
}
// ---------------------------------------------------------------------------
// Getter methods
// ---------------------------------------------------------------------------
inline QName* CMLeaf::getElement()
{
return fElement;
}
inline const QName* CMLeaf::getElement() const
{
return fElement;
}
inline unsigned int CMLeaf::getPosition() const
{
return fPosition;
}
inline bool CMLeaf::isRepeatableLeaf() const
{
return false;
}
// ---------------------------------------------------------------------------
// Setter methods
// ---------------------------------------------------------------------------
inline void CMLeaf::setPosition(const unsigned int newPosition)
{
fPosition = newPosition;
}
// ---------------------------------------------------------------------------
// Implementation of public CMNode virtual interface
// ---------------------------------------------------------------------------
inline void CMLeaf::orphanChild()
{
}
// ---------------------------------------------------------------------------
// Implementation of protected CMNode virtual interface
// ---------------------------------------------------------------------------
inline void CMLeaf::calcFirstPos(CMStateSet& toSet) const
{
// If we are an epsilon node, then the first pos is an empty set
if (isNullable())
{
toSet.zeroBits();
return;
}
// Otherwise, its just the one bit of our position
toSet.setBit(fPosition);
}
inline void CMLeaf::calcLastPos(CMStateSet& toSet) const
{
// If we are an epsilon node, then the last pos is an empty set
if (isNullable())
{
toSet.zeroBits();
return;
}
// Otherwise, its just the one bit of our position
toSet.setBit(fPosition);
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,193 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMNode.hpp 677430 2008-07-16 21:05:31Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMNODE_HPP)
#define XERCESC_INCLUDE_GUARD_CMNODE_HPP
#include <limits.h>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/common/CMStateSet.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class CMNode : public XMemory
{
public :
enum {
// Special value to indicate a nullable node
epsilonNode = UINT_MAX - 1
};
// -----------------------------------------------------------------------
// Constructors and Destructors
// -----------------------------------------------------------------------
CMNode
(
const ContentSpecNode::NodeTypes type
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
virtual ~CMNode();
// -----------------------------------------------------------------------
// Virtual methods to be provided derived node classes
// -----------------------------------------------------------------------
virtual void orphanChild() = 0;
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
ContentSpecNode::NodeTypes getType() const;
const CMStateSet& getFirstPos();
const CMStateSet& getLastPos();
bool isNullable() const;
protected :
// -----------------------------------------------------------------------
// Protected, abstract methods
// -----------------------------------------------------------------------
virtual void calcFirstPos(CMStateSet& toUpdate) const = 0;
virtual void calcLastPos(CMStateSet& toUpdate) const = 0;
// -----------------------------------------------------------------------
// Protected data members
//
// fMemoryManager
// Pluggable memory manager for dynamic allocation/deallocation.
// -----------------------------------------------------------------------
MemoryManager* fMemoryManager;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMNode();
CMNode(const CMNode&);
CMNode& operator=(const CMNode&);
// -----------------------------------------------------------------------
// Private data members
//
// fType
// The type of node. This indicates whether its a leaf or an
// operation.
//
// fFirstPos
// The set of NFA states that represent the entry states of this
// node in the DFA.
//
// fLastPos
// The set of NFA states that represent the final states of this
// node in the DFA.
//
// fMaxStates
// The maximum number of states that the NFA has, which means the
// max number of NFA states that have to be traced in the state
// sets during the building of the DFA. Its unfortunate that it
// has to be stored redundantly, but we need to fault in the
// state set members and they have to be sized to this size.
//
// fIsNullable
// Whether the node can be empty
// -----------------------------------------------------------------------
ContentSpecNode::NodeTypes fType;
CMStateSet* fFirstPos;
CMStateSet* fLastPos;
unsigned int fMaxStates;
protected:
bool fIsNullable;
};
// ---------------------------------------------------------------------------
// CMNode: Constructors and Destructors
// ---------------------------------------------------------------------------
inline CMNode::CMNode(const ContentSpecNode::NodeTypes type
, unsigned int maxStates
, MemoryManager* const manager) :
fMemoryManager(manager)
, fType(type)
, fFirstPos(0)
, fLastPos(0)
, fMaxStates(maxStates)
, fIsNullable(false)
{
}
inline CMNode::~CMNode()
{
// Clean up any position sets that got created
delete fFirstPos;
delete fLastPos;
}
// ---------------------------------------------------------------------------
// CMNode: Getter methods
// ---------------------------------------------------------------------------
inline ContentSpecNode::NodeTypes CMNode::getType() const
{
return fType;
}
inline const CMStateSet& CMNode::getFirstPos()
{
//
// Fault in the state set if needed. Since we can't use mutable members
// cast off the const'ness.
//
if (!fFirstPos)
{
fFirstPos = new (fMemoryManager) CMStateSet(fMaxStates, fMemoryManager);
calcFirstPos(*fFirstPos);
}
return *fFirstPos;
}
inline const CMStateSet& CMNode::getLastPos()
{
//
// Fault in the state set if needed. Since we can't use mutable members
// cast off the const'ness.
//
if (!fLastPos)
{
fLastPos = new (fMemoryManager) CMStateSet(fMaxStates, fMemoryManager);
calcLastPos(*fLastPos);
}
return *fLastPos;
}
inline bool CMNode::isNullable() const
{
return fIsNullable;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMRepeatingLeaf.hpp 677396 2008-07-16 19:36:20Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMREPEATINGLEAF_HPP)
#define XERCESC_INCLUDE_GUARD_CMREPEATINGLEAF_HPP
#include <xercesc/validators/common/CMLeaf.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// A compound content model leaf node which carries occurence information.
//
class CMRepeatingLeaf : public CMLeaf
{
public :
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
CMRepeatingLeaf
(
QName* const element
, int minOccurs
, int maxOccurs
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
CMRepeatingLeaf
(
QName* const element
, int minOccurs
, int maxOccurs
, unsigned int position
, bool adopt
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
int getMinOccurs() const;
int getMaxOccurs() const;
virtual bool isRepeatableLeaf() const;
private :
// -----------------------------------------------------------------------
// Private data members
//
// fMinOccurs
// fMaxOccurs
// The cardinality of the repeating leaf
//
// -----------------------------------------------------------------------
int fMinOccurs;
int fMaxOccurs;
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMRepeatingLeaf(const CMRepeatingLeaf&);
CMRepeatingLeaf& operator=(const CMRepeatingLeaf&);
};
// -----------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------
inline CMRepeatingLeaf::CMRepeatingLeaf( QName* const element
, int minOccurs
, int maxOccurs
, unsigned int position
, unsigned int maxStates
, MemoryManager* const manager) :
CMLeaf(element, position, maxStates, manager)
, fMinOccurs(minOccurs)
, fMaxOccurs(maxOccurs)
{
}
inline CMRepeatingLeaf::CMRepeatingLeaf( QName* const element
, int minOccurs
, int maxOccurs
, unsigned int position
, bool adopt
, unsigned int maxStates
, MemoryManager* const manager) :
CMLeaf(element, position, adopt, maxStates, manager)
, fMinOccurs(minOccurs)
, fMaxOccurs(maxOccurs)
{
}
// ---------------------------------------------------------------------------
// Getter methods
// ---------------------------------------------------------------------------
inline int CMRepeatingLeaf::getMinOccurs() const
{
return fMinOccurs;
}
inline int CMRepeatingLeaf::getMaxOccurs() const
{
return fMaxOccurs;
}
inline bool CMRepeatingLeaf::isRepeatableLeaf() const
{
return true;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,627 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMStateSet.hpp 901107 2010-01-20 08:45:02Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMSTATESET_HPP)
#define XERCESC_INCLUDE_GUARD_CMSTATESET_HPP
// DESCRIPTION:
//
// This class is a specialized bitset class for the content model code of
// the validator. It assumes that its never called with two objects of
// different bit counts, and that bit sets smaller than a threshold are far
// and away the most common. So it can be a lot more optimized than a general
// purpose utility bitset class
//
#include <xercesc/util/ArrayIndexOutOfBoundsException.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>
#if XERCES_HAVE_EMMINTRIN_H
# include <emmintrin.h>
#endif
XERCES_CPP_NAMESPACE_BEGIN
class CMStateSetEnumerator;
// This value must be 4 in order to use the SSE2 instruction set
#define CMSTATE_CACHED_INT32_SIZE 4
// This value must be a multiple of 128 in order to use the SSE2 instruction set
#define CMSTATE_BITFIELD_CHUNK 1024
#define CMSTATE_BITFIELD_INT32_SIZE (1024 / 32)
struct CMDynamicBuffer
{
// fArraySize
// This indicates the number of elements of the fBitArray vector
//
// fBitArray
// A vector of arrays of XMLInt32; each array is allocated on demand
// if a bit needs to be set in that range
//
// fMemoryManager
// The memory manager used to allocate and deallocate memory
//
XMLSize_t fArraySize;
XMLInt32** fBitArray;
MemoryManager* fMemoryManager;
};
class CMStateSet : public XMemory
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
CMStateSet( const XMLSize_t bitCount
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :
fBitCount(bitCount)
, fDynamicBuffer(0)
{
//
// See if we need to allocate the byte array or whether we can live
// within the cached bit high performance scheme.
//
if (fBitCount > (CMSTATE_CACHED_INT32_SIZE * 32))
{
fDynamicBuffer = (CMDynamicBuffer*)manager->allocate(sizeof(CMDynamicBuffer));
fDynamicBuffer->fMemoryManager = manager;
// allocate an array of vectors, each one containing CMSTATE_BITFIELD_CHUNK bits
fDynamicBuffer->fArraySize = fBitCount / CMSTATE_BITFIELD_CHUNK;
if (fBitCount % CMSTATE_BITFIELD_CHUNK)
fDynamicBuffer->fArraySize++;
fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
fDynamicBuffer->fBitArray[index]=NULL;
}
else
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
fBits[index] = 0;
}
}
CMStateSet(const CMStateSet& toCopy) :
XMemory(toCopy)
, fBitCount(toCopy.fBitCount)
, fDynamicBuffer(0)
{
//
// See if we need to allocate the byte array or whether we can live
// within the cahced bit high performance scheme.
//
if (fBitCount > (CMSTATE_CACHED_INT32_SIZE * 32))
{
fDynamicBuffer = (CMDynamicBuffer*) toCopy.fDynamicBuffer->fMemoryManager->allocate(sizeof(CMDynamicBuffer));
fDynamicBuffer->fMemoryManager = toCopy.fDynamicBuffer->fMemoryManager;
fDynamicBuffer->fArraySize = fBitCount / CMSTATE_BITFIELD_CHUNK;
if (fBitCount % CMSTATE_BITFIELD_CHUNK)
fDynamicBuffer->fArraySize++;
fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
{
if(toCopy.fDynamicBuffer->fBitArray[index]!=NULL)
{
allocateChunk(index);
memcpy((void *) fDynamicBuffer->fBitArray[index],
(const void *) toCopy.fDynamicBuffer->fBitArray[index],
CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
}
else
fDynamicBuffer->fBitArray[index]=NULL;
}
}
else
{
memcpy((void *) fBits,
(const void *) toCopy.fBits,
CMSTATE_CACHED_INT32_SIZE * sizeof(XMLInt32));
}
}
~CMStateSet()
{
if(fDynamicBuffer)
{
for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
if(fDynamicBuffer->fBitArray[index]!=NULL)
deallocateChunk(index);
fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer->fBitArray);
fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer);
}
}
// -----------------------------------------------------------------------
// Set manipulation methods
// -----------------------------------------------------------------------
void operator|=(const CMStateSet& setToOr)
{
if(fDynamicBuffer==0)
{
#ifdef XERCES_HAVE_SSE2_INTRINSIC
if(XMLPlatformUtils::fgSSE2ok)
{
__m128i xmm1 = _mm_loadu_si128((__m128i*)fBits);
__m128i xmm2 = _mm_loadu_si128((__m128i*)setToOr.fBits);
__m128i xmm3 = _mm_or_si128(xmm1, xmm2); // OR 4 32-bit words
_mm_storeu_si128((__m128i*)fBits, xmm3);
}
else
#endif
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
if(setToOr.fBits[index])
{
if(fBits[index])
fBits[index] |= setToOr.fBits[index];
else
fBits[index] = setToOr.fBits[index];
}
}
}
else
{
for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
{
XMLInt32 *& other = setToOr.fDynamicBuffer->fBitArray[index];
if(other!=NULL)
{
// if we haven't allocated the subvector yet, allocate it and copy
if(fDynamicBuffer->fBitArray[index]==NULL)
{
allocateChunk(index);
memcpy((void *) fDynamicBuffer->fBitArray[index],
(const void *) other,
CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
}
else
{
// otherwise, merge them
XMLInt32*& mine = fDynamicBuffer->fBitArray[index];
#ifdef XERCES_HAVE_SSE2_INTRINSIC
if(XMLPlatformUtils::fgSSE2ok)
{
for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex+=4)
{
__m128i xmm1 = _mm_load_si128((__m128i*)&other[subIndex]);
__m128i xmm2 = _mm_load_si128((__m128i*)&mine[subIndex]);
__m128i xmm3 = _mm_or_si128(xmm1, xmm2); // OR 4 32-bit words
_mm_store_si128((__m128i*)&mine[subIndex], xmm3);
}
}
else
#endif
{
for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
if(setToOr.fDynamicBuffer->fBitArray[index][subIndex])
{
if(fDynamicBuffer->fBitArray[index][subIndex])
fDynamicBuffer->fBitArray[index][subIndex] |= setToOr.fDynamicBuffer->fBitArray[index][subIndex];
else
fDynamicBuffer->fBitArray[index][subIndex] = setToOr.fDynamicBuffer->fBitArray[index][subIndex];
}
}
}
}
}
}
}
bool operator==(const CMStateSet& setToCompare) const
{
if (fBitCount != setToCompare.fBitCount)
return false;
if(fDynamicBuffer==0)
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
{
if (fBits[index] != setToCompare.fBits[index])
return false;
}
}
else
{
for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
{
XMLInt32 *& other = setToCompare.fDynamicBuffer->fBitArray[index],
*& mine = fDynamicBuffer->fBitArray[index];
if(mine==NULL && other==NULL)
continue;
else if(mine==NULL || other==NULL) // the other should have been empty too
return false;
else
{
for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
if(mine[subIndex]!=other[subIndex])
return false;
}
}
}
return true;
}
CMStateSet& operator=(const CMStateSet& srcSet)
{
if (this == &srcSet)
return *this;
// They have to be the same size
if (fBitCount != srcSet.fBitCount)
{
if(fDynamicBuffer)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Bitset_NotEqualSize, fDynamicBuffer->fMemoryManager);
else
ThrowXML(RuntimeException, XMLExcepts::Bitset_NotEqualSize);
}
if(fDynamicBuffer==0)
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
fBits[index] = srcSet.fBits[index];
}
else
{
for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
if(srcSet.fDynamicBuffer->fBitArray[index]==NULL)
{
// delete this subentry
if(fDynamicBuffer->fBitArray[index]!=NULL)
deallocateChunk(index);
}
else
{
// if we haven't allocated the subvector yet, allocate it and copy
if(fDynamicBuffer->fBitArray[index]==NULL)
allocateChunk(index);
memcpy((void *) fDynamicBuffer->fBitArray[index],
(const void *) srcSet.fDynamicBuffer->fBitArray[index],
CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
}
}
return *this;
}
XMLSize_t getBitCountInRange(XMLSize_t start, XMLSize_t end) const
{
XMLSize_t count = 0;
end /= 32;
if(fDynamicBuffer==0)
{
if(end > CMSTATE_CACHED_INT32_SIZE)
end = CMSTATE_CACHED_INT32_SIZE;
for (XMLSize_t index = start / 32; index < end; index++)
{
if (fBits[index] != 0)
for(int i=0;i<32;i++)
{
const XMLInt32 mask = 1UL << i;
if(fBits[index] & mask)
count++;
}
}
}
else
{
if(end > fDynamicBuffer->fArraySize)
end = fDynamicBuffer->fArraySize;
for (XMLSize_t index = start / 32; index < end; index++)
{
if(fDynamicBuffer->fBitArray[index]==NULL)
continue;
for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
{
if (fDynamicBuffer->fBitArray[index][subIndex] != 0)
for(int i=0;i<32;i++)
{
const XMLInt32 mask = 1UL << i;
if(fDynamicBuffer->fBitArray[index][subIndex] & mask)
count++;
}
}
}
}
return count;
}
bool getBit(const XMLSize_t bitToGet) const
{
if (bitToGet >= fBitCount)
{
if(fDynamicBuffer)
ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex, fDynamicBuffer->fMemoryManager);
else
ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex);
}
// And access the right bit and byte
if(fDynamicBuffer==0)
{
const XMLInt32 mask = 1UL << (bitToGet % 32);
const XMLSize_t byteOfs = bitToGet / 32;
return (fBits[byteOfs]!=0 && (fBits[byteOfs] & mask) != 0);
}
else
{
const XMLSize_t vectorOfs = bitToGet / CMSTATE_BITFIELD_CHUNK;
if(fDynamicBuffer->fBitArray[vectorOfs]==NULL)
return false;
const XMLInt32 mask = 1UL << (bitToGet % 32);
const XMLSize_t byteOfs = (bitToGet % CMSTATE_BITFIELD_CHUNK) / 32;
return (fDynamicBuffer->fBitArray[vectorOfs][byteOfs]!=0 && (fDynamicBuffer->fBitArray[vectorOfs][byteOfs] & mask) != 0);
}
}
bool isEmpty() const
{
if(fDynamicBuffer==0)
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
{
if (fBits[index] != 0)
return false;
}
}
else
{
for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
{
if(fDynamicBuffer->fBitArray[index]==NULL)
continue;
for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
{
if (fDynamicBuffer->fBitArray[index][subIndex] != 0)
return false;
}
}
}
return true;
}
void setBit(const XMLSize_t bitToSet)
{
if (bitToSet >= fBitCount)
{
if(fDynamicBuffer)
ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex, fDynamicBuffer->fMemoryManager);
else
ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex);
}
const XMLInt32 mask = 1UL << (bitToSet % 32);
// And access the right bit and byte
if(fDynamicBuffer==0)
{
const XMLSize_t byteOfs = bitToSet / 32;
fBits[byteOfs] &= ~mask;
fBits[byteOfs] |= mask;
}
else
{
const XMLSize_t vectorOfs = bitToSet / CMSTATE_BITFIELD_CHUNK;
if(fDynamicBuffer->fBitArray[vectorOfs]==NULL)
{
allocateChunk(vectorOfs);
for(XMLSize_t index=0;index < CMSTATE_BITFIELD_INT32_SIZE; index++)
fDynamicBuffer->fBitArray[vectorOfs][index]=0;
}
const XMLSize_t byteOfs = (bitToSet % CMSTATE_BITFIELD_CHUNK) / 32;
fDynamicBuffer->fBitArray[vectorOfs][byteOfs] &= ~mask;
fDynamicBuffer->fBitArray[vectorOfs][byteOfs] |= mask;
}
}
void zeroBits()
{
if(fDynamicBuffer==0)
{
for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
fBits[index] = 0;
}
else
{
for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
// delete this subentry
if(fDynamicBuffer->fBitArray[index]!=NULL)
deallocateChunk(index);
}
}
XMLSize_t hashCode() const
{
XMLSize_t hash = 0;
if(fDynamicBuffer==0)
{
for (XMLSize_t index = 0; index<CMSTATE_CACHED_INT32_SIZE; index++)
hash = fBits[index] + hash * 31;
}
else
{
for (XMLSize_t index = 0; index<fDynamicBuffer->fArraySize; index++)
{
if(fDynamicBuffer->fBitArray[index]==NULL)
// simulates the iteration on the missing bits
for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
hash *= 31;
else
for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
hash = fDynamicBuffer->fBitArray[index][subIndex] + hash * 31;
}
}
return hash;
}
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMStateSet();
// -----------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------
void allocateChunk(const XMLSize_t index)
{
#ifdef XERCES_HAVE_SSE2_INTRINSIC
if(XMLPlatformUtils::fgSSE2ok)
fDynamicBuffer->fBitArray[index]=(XMLInt32*)_mm_malloc(CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32), 16);
else
#endif
fDynamicBuffer->fBitArray[index]=(XMLInt32*)fDynamicBuffer->fMemoryManager->allocate(CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
}
void deallocateChunk(const XMLSize_t index)
{
#ifdef XERCES_HAVE_SSE2_INTRINSIC
if(XMLPlatformUtils::fgSSE2ok)
_mm_free(fDynamicBuffer->fBitArray[index]);
else
#endif
fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer->fBitArray[index]);
fDynamicBuffer->fBitArray[index]=NULL;
}
// -----------------------------------------------------------------------
// Private data members
//
// fBitCount
// The count of bits that the outside world wants to support,
// so its the max bit index plus one.
//
// fBits
// When the bit count is less than a threshold (very common), these hold the bits.
// Otherwise, the fDynamicBuffer member holds htem.
//
// fDynamicBuffer
// If the bit count is greater than the threshold, then we allocate this structure to
// store the bits, the length, and the memory manager to allocate/deallocate
// the memory
//
// -----------------------------------------------------------------------
XMLSize_t fBitCount;
XMLInt32 fBits[CMSTATE_CACHED_INT32_SIZE];
CMDynamicBuffer* fDynamicBuffer;
friend class CMStateSetEnumerator;
};
class CMStateSetEnumerator : public XMemory
{
public:
CMStateSetEnumerator(const CMStateSet* toEnum, XMLSize_t start = 0) :
fToEnum(toEnum),
fIndexCount((XMLSize_t)-1),
fLastValue(0)
{
// if a starting bit is specified, place fIndexCount at the beginning of the previous 32 bit area
// so the findNext moves to the one where 'start' is located
if(start > 32)
fIndexCount = (start/32 - 1) * 32;
findNext();
// if we found data, and fIndexCount is still pointing to the area where 'start' is located, erase the bits before 'start'
if(hasMoreElements() && fIndexCount < start)
{
for(XMLSize_t i=0;i< (start - fIndexCount);i++)
{
XMLInt32 mask=1UL << i;
if(fLastValue & mask)
fLastValue &= ~mask;
}
// in case the 32 bit area contained only bits before 'start', advance
if(fLastValue==0)
findNext();
}
}
bool hasMoreElements()
{
return fLastValue!=0;
}
unsigned int nextElement()
{
for(int i=0;i<32;i++)
{
XMLInt32 mask=1UL << i;
if(fLastValue & mask)
{
fLastValue &= ~mask;
unsigned int retVal=(unsigned int)fIndexCount+i;
if(fLastValue==0)
findNext();
return retVal;
}
}
return 0;
}
private:
void findNext()
{
if(fToEnum->fDynamicBuffer==0)
{
XMLSize_t nOffset=((fIndexCount==(XMLSize_t)-1)?0:(fIndexCount/32)+1);
for(XMLSize_t index=nOffset;index<CMSTATE_CACHED_INT32_SIZE;index++)
{
if(fToEnum->fBits[index]!=0)
{
fIndexCount=index*32;
fLastValue=fToEnum->fBits[index];
return;
}
}
}
else
{
XMLSize_t nOffset=((fIndexCount==(XMLSize_t)-1)?0:(fIndexCount/CMSTATE_BITFIELD_CHUNK));
XMLSize_t nSubOffset=((fIndexCount==(XMLSize_t)-1)?0:((fIndexCount % CMSTATE_BITFIELD_CHUNK) /32)+1);
for (XMLSize_t index = nOffset; index<fToEnum->fDynamicBuffer->fArraySize; index++)
{
if(fToEnum->fDynamicBuffer->fBitArray[index]!=NULL)
{
for(XMLSize_t subIndex=nSubOffset;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
if(fToEnum->fDynamicBuffer->fBitArray[index][subIndex]!=0)
{
fIndexCount=index*CMSTATE_BITFIELD_CHUNK + subIndex*32;
fLastValue=fToEnum->fDynamicBuffer->fBitArray[index][subIndex];
return;
}
}
nSubOffset = 0; // next chunks will be processed from the beginning
}
}
}
const CMStateSet* fToEnum;
XMLSize_t fIndexCount;
XMLInt32 fLastValue;
};
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,99 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMUnaryOp.cpp 677396 2008-07-16 19:36:20Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/validators/common/CMStateSet.hpp>
#include <xercesc/validators/common/CMUnaryOp.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// CMUnaryOp: Constructors and Destructor
// ---------------------------------------------------------------------------
CMUnaryOp::CMUnaryOp( ContentSpecNode::NodeTypes type
, CMNode* const nodeToAdopt
, unsigned int maxStates
, MemoryManager* const manager) :
CMNode(type, maxStates, manager)
, fChild(nodeToAdopt)
{
// Insure that its one of the types we require
if ((type != ContentSpecNode::ZeroOrOne)
&& (type != ContentSpecNode::ZeroOrMore)
&& (type != ContentSpecNode::OneOrMore))
{
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnaryOpHadBinType, manager);
}
if (type == ContentSpecNode::OneOrMore)
fIsNullable=fChild->isNullable();
else
fIsNullable=true;
}
CMUnaryOp::~CMUnaryOp()
{
delete fChild;
}
// ---------------------------------------------------------------------------
// CMUnaryOp: Getter methods
// ---------------------------------------------------------------------------
const CMNode* CMUnaryOp::getChild() const
{
return fChild;
}
CMNode* CMUnaryOp::getChild()
{
return fChild;
}
// ---------------------------------------------------------------------------
// CMUnaryOp: Implementation of the public CMNode virtual interface
// ---------------------------------------------------------------------------
void CMUnaryOp::orphanChild()
{
delete fChild;
fChild=0;
}
// ---------------------------------------------------------------------------
// CMUnaryOp: Implementation of the protected CMNode virtual interface
// ---------------------------------------------------------------------------
void CMUnaryOp::calcFirstPos(CMStateSet& toSet) const
{
// Its just based on our child node's first pos
toSet = fChild->getFirstPos();
}
void CMUnaryOp::calcLastPos(CMStateSet& toSet) const
{
// Its just based on our child node's last pos
toSet = fChild->getLastPos();
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: CMUnaryOp.hpp 677396 2008-07-16 19:36:20Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CMUNARYOP_HPP)
#define XERCESC_INCLUDE_GUARD_CMUNARYOP_HPP
#include <xercesc/validators/common/CMNode.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class CMStateSet;
class CMUnaryOp : public CMNode
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
CMUnaryOp
(
ContentSpecNode::NodeTypes type
, CMNode* const nodeToAdopt
, unsigned int maxStates
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~CMUnaryOp();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const CMNode* getChild() const;
CMNode* getChild();
// -----------------------------------------------------------------------
// Implementation of the public CMNode virtual interface
// -----------------------------------------------------------------------
virtual void orphanChild();
protected :
// -----------------------------------------------------------------------
// Implementation of the protected CMNode virtual interface
// -----------------------------------------------------------------------
void calcFirstPos(CMStateSet& toSet) const;
void calcLastPos(CMStateSet& toSet) const;
private :
// -----------------------------------------------------------------------
// Private data members
//
// fChild
// This is the reference to the one child that we have for this
// unary operation. We own it.
// -----------------------------------------------------------------------
CMNode* fChild;
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CMUnaryOp(const CMUnaryOp&);
CMUnaryOp& operator=(const CMUnaryOp&);
};
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,132 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: ContentLeafNameTypeVector.cpp 676911 2008-07-15 13:27:32Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// ContentLeafNameTypeVector: Constructors and Destructor
// ---------------------------------------------------------------------------
ContentLeafNameTypeVector::ContentLeafNameTypeVector
(
MemoryManager* const manager
)
: fMemoryManager(manager)
, fLeafNames(0)
, fLeafTypes(0)
, fLeafCount(0)
{
}
ContentLeafNameTypeVector::ContentLeafNameTypeVector
(
QName** const names
, ContentSpecNode::NodeTypes* const types
, const XMLSize_t count
, MemoryManager* const manager
)
: fMemoryManager(manager)
, fLeafNames(0)
, fLeafTypes(0)
, fLeafCount(0)
{
setValues(names, types, count);
}
/***
copy ctor
***/
ContentLeafNameTypeVector::ContentLeafNameTypeVector
(
const ContentLeafNameTypeVector& toCopy
)
: XMemory(toCopy)
, fMemoryManager(toCopy.fMemoryManager)
, fLeafNames(0)
, fLeafTypes(0)
, fLeafCount(0)
{
fLeafCount=toCopy.getLeafCount();
init(fLeafCount);
for (XMLSize_t i=0; i<this->fLeafCount; i++)
{
fLeafNames[i] = toCopy.getLeafNameAt(i);
fLeafTypes[i] = toCopy.getLeafTypeAt(i);
}
}
ContentLeafNameTypeVector::~ContentLeafNameTypeVector()
{
cleanUp();
}
// ---------------------------------------------------------------------------
// ContentSpecType: Setter methods
// ---------------------------------------------------------------------------
void ContentLeafNameTypeVector::setValues
(
QName** const names
, ContentSpecNode::NodeTypes* const types
, const XMLSize_t count
)
{
cleanUp();
init(count);
for (XMLSize_t i=0; i<count; i++)
{
fLeafNames[i] = names[i];
fLeafTypes[i] = types[i];
}
}
// ---------------------------------------------------------------------------
// ContentLeafNameTypeVector: Getter methods
// ---------------------------------------------------------------------------
QName* ContentLeafNameTypeVector::getLeafNameAt(const XMLSize_t pos) const
{
if (pos >= fLeafCount)
ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager);
return fLeafNames[pos];
}
ContentSpecNode::NodeTypes ContentLeafNameTypeVector::getLeafTypeAt
(const XMLSize_t pos) const
{
if (pos >= fLeafCount)
ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager);
return fLeafTypes[pos];
}
XMLSize_t ContentLeafNameTypeVector::getLeafCount() const
{
return fLeafCount;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,119 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: ContentLeafNameTypeVector.hpp 676911 2008-07-15 13:27:32Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CONTENTLEAFNAMETYPEVECTOR_HPP)
#define XERCESC_INCLUDE_GUARD_CONTENTLEAFNAMETYPEVECTOR_HPP
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/framework/MemoryManager.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class XMLPARSER_EXPORT ContentLeafNameTypeVector : public XMemory
{
public :
// -----------------------------------------------------------------------
// Class specific types
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
ContentLeafNameTypeVector
(
MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
ContentLeafNameTypeVector
(
QName** const qName
, ContentSpecNode::NodeTypes* const types
, const XMLSize_t count
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~ContentLeafNameTypeVector();
ContentLeafNameTypeVector(const ContentLeafNameTypeVector&);
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
QName* getLeafNameAt(const XMLSize_t pos) const;
ContentSpecNode::NodeTypes getLeafTypeAt(const XMLSize_t pos) const;
XMLSize_t getLeafCount() const;
// -----------------------------------------------------------------------
// Setter methods
// -----------------------------------------------------------------------
void setValues
(
QName** const qName
, ContentSpecNode::NodeTypes* const types
, const XMLSize_t count
);
// -----------------------------------------------------------------------
// Miscellaneous
// -----------------------------------------------------------------------
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
ContentLeafNameTypeVector& operator=(const ContentLeafNameTypeVector&);
// -----------------------------------------------------------------------
// helper methods
// -----------------------------------------------------------------------
void cleanUp();
void init(const XMLSize_t size);
// -----------------------------------------------------------------------
// Private Data Members
//
// -----------------------------------------------------------------------
MemoryManager* fMemoryManager;
QName** fLeafNames;
ContentSpecNode::NodeTypes *fLeafTypes;
XMLSize_t fLeafCount;
};
inline void ContentLeafNameTypeVector::cleanUp()
{
fMemoryManager->deallocate(fLeafNames); //delete [] fLeafNames;
fMemoryManager->deallocate(fLeafTypes); //delete [] fLeafTypes;
}
inline void ContentLeafNameTypeVector::init(const XMLSize_t size)
{
fLeafNames = (QName**) fMemoryManager->allocate(size * sizeof(QName*));//new QName*[size];
fLeafTypes = (ContentSpecNode::NodeTypes *) fMemoryManager->allocate
(
size * sizeof(ContentSpecNode::NodeTypes)
); //new ContentSpecNode::NodeTypes [size];
fLeafCount = size;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,323 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: ContentSpecNode.cpp 1662870 2015-02-28 00:56:55Z scantor $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// ContentSpecNode: Copy Constructor
//
// Note: this copy constructor has dependency on various get*() methods
// and shall be placed after those method's declaration.
// aka inline function compilation error on AIX 4.2, xlC 3 r ev.1
// ---------------------------------------------------------------------------
ContentSpecNode::ContentSpecNode(const ContentSpecNode& toCopy) :
XSerializable(toCopy)
, XMemory(toCopy)
, fMemoryManager(toCopy.fMemoryManager)
, fElement(0)
, fElementDecl(toCopy.fElementDecl)
, fFirst(0)
, fSecond(0)
, fType(toCopy.fType)
, fAdoptFirst(true)
, fAdoptSecond(true)
, fMinOccurs(toCopy.fMinOccurs)
, fMaxOccurs(toCopy.fMaxOccurs)
{
const QName* tempElement = toCopy.getElement();
if (tempElement)
fElement = new (fMemoryManager) QName(*tempElement);
const ContentSpecNode *tmp = toCopy.getFirst();
if (tmp)
fFirst = new (fMemoryManager) ContentSpecNode(*tmp);
tmp = toCopy.getSecond();
if (tmp)
fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
}
// ---------------------------------------------------------------------------
// Local methods
// ---------------------------------------------------------------------------
static void formatNode( const ContentSpecNode* const curNode
, const ContentSpecNode::NodeTypes parentType
, XMLBuffer& bufToFill)
{
if (!curNode)
return;
const ContentSpecNode* first = curNode->getFirst();
const ContentSpecNode* second = curNode->getSecond();
const ContentSpecNode::NodeTypes curType = curNode->getType();
// Get the type of the first node
const ContentSpecNode::NodeTypes firstType = first ?
first->getType() :
ContentSpecNode::Leaf;
// Calculate the parens flag for the rep nodes
bool doRepParens = false;
if (((firstType != ContentSpecNode::Leaf)
&& (parentType != ContentSpecNode::UnknownType))
|| ((firstType == ContentSpecNode::Leaf)
&& (parentType == ContentSpecNode::UnknownType)))
{
doRepParens = true;
}
// Now handle our type
switch(curType & 0x0f)
{
case ContentSpecNode::Leaf :
if (curNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
bufToFill.append(XMLElementDecl::fgPCDataElemName);
else
{
bufToFill.append(curNode->getElement()->getRawName());
// show the + and * modifiers also when we have a non-infinite number of repetitions
if(curNode->getMinOccurs()==0 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
bufToFill.append(chAsterisk);
else if(curNode->getMinOccurs()==0 && curNode->getMaxOccurs()==1)
bufToFill.append(chQuestion);
else if(curNode->getMinOccurs()==1 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
bufToFill.append(chPlus);
}
break;
case ContentSpecNode::ZeroOrOne :
if (doRepParens)
bufToFill.append(chOpenParen);
formatNode(first, curType, bufToFill);
if (doRepParens)
bufToFill.append(chCloseParen);
bufToFill.append(chQuestion);
break;
case ContentSpecNode::ZeroOrMore :
if (doRepParens)
bufToFill.append(chOpenParen);
formatNode(first, curType, bufToFill);
if (doRepParens)
bufToFill.append(chCloseParen);
bufToFill.append(chAsterisk);
break;
case ContentSpecNode::OneOrMore :
if (doRepParens)
bufToFill.append(chOpenParen);
formatNode(first, curType, bufToFill);
if (doRepParens)
bufToFill.append(chCloseParen);
bufToFill.append(chPlus);
break;
case ContentSpecNode::Choice :
if ((parentType & 0x0f) != (curType & 0x0f))
bufToFill.append(chOpenParen);
formatNode(first, curType, bufToFill);
if(second!=NULL)
{
bufToFill.append(chPipe);
formatNode(second, curType, bufToFill);
}
if ((parentType & 0x0f) != (curType & 0x0f))
bufToFill.append(chCloseParen);
break;
case ContentSpecNode::Sequence :
if ((parentType & 0x0f) != (curType & 0x0f))
bufToFill.append(chOpenParen);
formatNode(first, curType, bufToFill);
if(second!=NULL)
{
bufToFill.append(chComma);
formatNode(second, curType, bufToFill);
}
if ((parentType & 0x0f) != (curType & 0x0f))
bufToFill.append(chCloseParen);
break;
case ContentSpecNode::All :
if ((parentType & 0x0f) != (curType & 0x0f))
{
bufToFill.append(chLatin_A);
bufToFill.append(chLatin_l);
bufToFill.append(chLatin_l);
bufToFill.append(chOpenParen);
}
formatNode(first, curType, bufToFill);
bufToFill.append(chComma);
formatNode(second, curType, bufToFill);
if ((parentType & 0x0f) != (curType & 0x0f))
bufToFill.append(chCloseParen);
break;
}
}
// ---------------------------------------------------------------------------
// ContentSpecNode: Miscellaneous
// ---------------------------------------------------------------------------
void ContentSpecNode::formatSpec(XMLBuffer& bufToFill) const
{
// Clean out the buffer first
bufToFill.reset();
if (fType == ContentSpecNode::Leaf)
bufToFill.append(chOpenParen);
formatNode
(
this
, UnknownType
, bufToFill
);
if (fType == ContentSpecNode::Leaf)
bufToFill.append(chCloseParen);
}
int ContentSpecNode::getMinTotalRange() const {
int min = fMinOccurs;
if ((fType & 0x0f) == ContentSpecNode::Sequence
|| fType == ContentSpecNode::All
|| (fType & 0x0f) == ContentSpecNode::Choice) {
int minFirst = fFirst->getMinTotalRange();
if (fSecond) {
int minSecond = fSecond->getMinTotalRange();
if ((fType & 0x0f) == ContentSpecNode::Choice) {
min = min * ((minFirst < minSecond)? minFirst : minSecond);
}
else {
min = min * (minFirst + minSecond);
}
}
else
min = min * minFirst;
}
return min;
}
int ContentSpecNode::getMaxTotalRange() const {
int max = fMaxOccurs;
if (max == SchemaSymbols::XSD_UNBOUNDED) {
return SchemaSymbols::XSD_UNBOUNDED;
}
if ((fType & 0x0f) == ContentSpecNode::Sequence
|| fType == ContentSpecNode::All
|| (fType & 0x0f) == ContentSpecNode::Choice) {
int maxFirst = fFirst->getMaxTotalRange();
if (maxFirst == SchemaSymbols::XSD_UNBOUNDED) {
return SchemaSymbols::XSD_UNBOUNDED;
}
if (fSecond) {
int maxSecond = fSecond->getMaxTotalRange();
if (maxSecond == SchemaSymbols::XSD_UNBOUNDED) {
return SchemaSymbols::XSD_UNBOUNDED;
}
else {
if ((fType & 0x0f) == ContentSpecNode::Choice) {
max = max * ((maxFirst > maxSecond) ? maxFirst : maxSecond);
}
else {
max = max * (maxFirst + maxSecond);
}
}
}
else {
max = max * maxFirst;
}
}
return max;
}
/***
* Support for Serialization/De-serialization
***/
IMPL_XSERIALIZABLE_TOCREATE(ContentSpecNode)
void ContentSpecNode::serialize(XSerializeEngine& serEng)
{
/***
* Since fElement, fFirst, fSecond are NOT created by the default
* constructor, we need to create them dynamically.
***/
if (serEng.isStoring())
{
serEng<<fElement;
XMLElementDecl::storeElementDecl(serEng, fElementDecl);
serEng<<fFirst;
serEng<<fSecond;
serEng<<(int)fType;
serEng<<fAdoptFirst;
serEng<<fAdoptSecond;
serEng<<fMinOccurs;
serEng<<fMaxOccurs;
}
else
{
serEng>>fElement;
fElementDecl = XMLElementDecl::loadElementDecl(serEng);
serEng>>fFirst;
serEng>>fSecond;
int type;
serEng>>type;
fType = (NodeTypes)type;
serEng>>fAdoptFirst;
serEng>>fAdoptSecond;
serEng>>fMinOccurs;
serEng>>fMaxOccurs;
}
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,467 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: ContentSpecNode.hpp 932887 2010-04-11 13:04:59Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CONTENTSPECNODE_HPP)
#define XERCESC_INCLUDE_GUARD_CONTENTSPECNODE_HPP
#include <xercesc/framework/XMLElementDecl.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <xercesc/internal/XSerializable.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class XMLBuffer;
class Grammar;
class XMLUTIL_EXPORT ContentSpecNode : public XSerializable, public XMemory
{
public :
// -----------------------------------------------------------------------
// Class specific types
// -----------------------------------------------------------------------
enum NodeTypes
{
Leaf = 0
, ZeroOrOne
, ZeroOrMore
, OneOrMore
, Choice
, Sequence
, Any
, Any_Other
, Any_NS = 8
, All = 9
, Loop = 10
, Any_NS_Choice = 20 // 16 + 4 (Choice)
, ModelGroupSequence = 21 // 16 + 5 (Sequence)
, Any_Lax = 22 // 16 + 6 (Any)
, Any_Other_Lax = 23 // 16 + 7 (Any_Other)
, Any_NS_Lax = 24 // 16 + 8 (Any_NS)
, ModelGroupChoice = 36 // 32 + 4 (Choice)
, Any_Skip = 38 // 32 + 6 (Any)
, Any_Other_Skip = 39 // 32 + 7 (Any_Other)
, Any_NS_Skip = 40 // 32 + 8 (Any_NS)
, UnknownType = -1
};
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
ContentSpecNode(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
ContentSpecNode
(
QName* const toAdopt
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
ContentSpecNode
(
XMLElementDecl* const elemDecl
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
ContentSpecNode
(
QName* const toAdopt
, const bool copyQName
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
ContentSpecNode
(
const NodeTypes type
, ContentSpecNode* const firstToAdopt
, ContentSpecNode* const secondToAdopt
, const bool adoptFirst = true
, const bool adoptSecond = true
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
ContentSpecNode(const ContentSpecNode&);
~ContentSpecNode();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
QName* getElement();
const QName* getElement() const;
XMLElementDecl* getElementDecl();
const XMLElementDecl* getElementDecl() const;
ContentSpecNode* getFirst();
const ContentSpecNode* getFirst() const;
ContentSpecNode* getSecond();
const ContentSpecNode* getSecond() const;
NodeTypes getType() const;
ContentSpecNode* orphanFirst();
ContentSpecNode* orphanSecond();
int getMinOccurs() const;
int getMaxOccurs() const;
bool isFirstAdopted() const;
bool isSecondAdopted() const;
// -----------------------------------------------------------------------
// Setter methods
// -----------------------------------------------------------------------
void setElement(QName* const toAdopt);
void setFirst(ContentSpecNode* const toAdopt);
void setSecond(ContentSpecNode* const toAdopt);
void setType(const NodeTypes type);
void setMinOccurs(int min);
void setMaxOccurs(int max);
void setAdoptFirst(bool adoptFirst);
void setAdoptSecond(bool adoptSecond);
// -----------------------------------------------------------------------
// Miscellaneous
// -----------------------------------------------------------------------
void formatSpec (XMLBuffer& bufToFill) const;
bool hasAllContent();
int getMinTotalRange() const;
int getMaxTotalRange() const;
/***
* Support for Serialization/De-serialization
***/
DECL_XSERIALIZABLE(ContentSpecNode)
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
ContentSpecNode& operator=(const ContentSpecNode&);
// -----------------------------------------------------------------------
// Private Data Members
//
// fElement
// If the type is Leaf/Any*, then this is the qName of the element. If the URI
// is fgPCDataElemId, then its a PCData node. Else, it is zero.
//
// fFirst
// fSecond
// The optional first and second nodes. The fType field indicates
// which of these are valid. The validity constraints are:
//
// Leaf = Neither valid
// ZeroOrOne, ZeroOrMore = First
// Choice, Sequence, All = First and Second
// Any* = Neither valid
//
// fType
// The type of node. This controls how many of the child node fields
// are used.
//
// fAdoptFirst
// Indicate if this ContentSpecNode adopts the fFirst, and is responsible
// for deleting it.
//
// fAdoptSecond
// Indicate if this ContentSpecNode adopts the fSecond, and is responsible
// for deleting it.
//
// fMinOccurs
// Indicate the minimum times that this node can occur
//
// fMaxOccurs
// Indicate the maximum times that this node can occur
// -1 (Unbounded), default (1)
// -----------------------------------------------------------------------
MemoryManager* fMemoryManager;
QName* fElement;
XMLElementDecl* fElementDecl;
ContentSpecNode* fFirst;
ContentSpecNode* fSecond;
NodeTypes fType;
bool fAdoptFirst;
bool fAdoptSecond;
int fMinOccurs;
int fMaxOccurs;
};
// ---------------------------------------------------------------------------
// ContentSpecNode: Constructors and Destructor
// ---------------------------------------------------------------------------
inline ContentSpecNode::ContentSpecNode(MemoryManager* const manager) :
fMemoryManager(manager)
, fElement(0)
, fElementDecl(0)
, fFirst(0)
, fSecond(0)
, fType(ContentSpecNode::Leaf)
, fAdoptFirst(true)
, fAdoptSecond(true)
, fMinOccurs(1)
, fMaxOccurs(1)
{
}
inline
ContentSpecNode::ContentSpecNode(QName* const element,
MemoryManager* const manager) :
fMemoryManager(manager)
, fElement(0)
, fElementDecl(0)
, fFirst(0)
, fSecond(0)
, fType(ContentSpecNode::Leaf)
, fAdoptFirst(true)
, fAdoptSecond(true)
, fMinOccurs(1)
, fMaxOccurs(1)
{
if (element)
fElement = new (fMemoryManager) QName(*element);
}
inline
ContentSpecNode::ContentSpecNode(XMLElementDecl* const elemDecl,
MemoryManager* const manager) :
fMemoryManager(manager)
, fElement(0)
, fElementDecl(elemDecl)
, fFirst(0)
, fSecond(0)
, fType(ContentSpecNode::Leaf)
, fAdoptFirst(true)
, fAdoptSecond(true)
, fMinOccurs(1)
, fMaxOccurs(1)
{
if (elemDecl)
fElement = new (manager) QName(*(elemDecl->getElementName()));
}
inline
ContentSpecNode::ContentSpecNode( QName* const element
, const bool copyQName
, MemoryManager* const manager) :
fMemoryManager(manager)
, fElement(0)
, fElementDecl(0)
, fFirst(0)
, fSecond(0)
, fType(ContentSpecNode::Leaf)
, fAdoptFirst(true)
, fAdoptSecond(true)
, fMinOccurs(1)
, fMaxOccurs(1)
{
if (copyQName)
{
if (element)
fElement = new (fMemoryManager) QName(*element);
}
else
{
fElement = element;
}
}
inline
ContentSpecNode::ContentSpecNode(const NodeTypes type
, ContentSpecNode* const firstAdopt
, ContentSpecNode* const secondAdopt
, const bool adoptFirst
, const bool adoptSecond
, MemoryManager* const manager) :
fMemoryManager(manager)
, fElement(0)
, fElementDecl(0)
, fFirst(firstAdopt)
, fSecond(secondAdopt)
, fType(type)
, fAdoptFirst(adoptFirst)
, fAdoptSecond(adoptSecond)
, fMinOccurs(1)
, fMaxOccurs(1)
{
}
inline ContentSpecNode::~ContentSpecNode()
{
// Delete our children, which cause recursive cleanup
if (fAdoptFirst) {
delete fFirst;
}
if (fAdoptSecond) {
delete fSecond;
}
delete fElement;
}
// ---------------------------------------------------------------------------
// ContentSpecNode: Getter methods
// ---------------------------------------------------------------------------
inline QName* ContentSpecNode::getElement()
{
return fElement;
}
inline const QName* ContentSpecNode::getElement() const
{
return fElement;
}
inline XMLElementDecl* ContentSpecNode::getElementDecl()
{
return fElementDecl;
}
inline const XMLElementDecl* ContentSpecNode::getElementDecl() const
{
return fElementDecl;
}
inline ContentSpecNode* ContentSpecNode::getFirst()
{
return fFirst;
}
inline const ContentSpecNode* ContentSpecNode::getFirst() const
{
return fFirst;
}
inline ContentSpecNode* ContentSpecNode::getSecond()
{
return fSecond;
}
inline const ContentSpecNode* ContentSpecNode::getSecond() const
{
return fSecond;
}
inline ContentSpecNode::NodeTypes ContentSpecNode::getType() const
{
return fType;
}
inline ContentSpecNode* ContentSpecNode::orphanFirst()
{
ContentSpecNode* retNode = fFirst;
fFirst = 0;
return retNode;
}
inline ContentSpecNode* ContentSpecNode::orphanSecond()
{
ContentSpecNode* retNode = fSecond;
fSecond = 0;
return retNode;
}
inline int ContentSpecNode::getMinOccurs() const
{
return fMinOccurs;
}
inline int ContentSpecNode::getMaxOccurs() const
{
return fMaxOccurs;
}
inline bool ContentSpecNode::isFirstAdopted() const
{
return fAdoptFirst;
}
inline bool ContentSpecNode::isSecondAdopted() const
{
return fAdoptSecond;
}
// ---------------------------------------------------------------------------
// ContentSpecType: Setter methods
// ---------------------------------------------------------------------------
inline void ContentSpecNode::setElement(QName* const element)
{
delete fElement;
fElement = 0;
if (element)
fElement = new (fMemoryManager) QName(*element);
}
inline void ContentSpecNode::setFirst(ContentSpecNode* const toAdopt)
{
if (fAdoptFirst)
delete fFirst;
fFirst = toAdopt;
}
inline void ContentSpecNode::setSecond(ContentSpecNode* const toAdopt)
{
if (fAdoptSecond)
delete fSecond;
fSecond = toAdopt;
}
inline void ContentSpecNode::setType(const NodeTypes type)
{
fType = type;
}
inline void ContentSpecNode::setMinOccurs(int min)
{
fMinOccurs = min;
}
inline void ContentSpecNode::setMaxOccurs(int max)
{
fMaxOccurs = max;
}
inline void ContentSpecNode::setAdoptFirst(bool newState)
{
fAdoptFirst = newState;
}
inline void ContentSpecNode::setAdoptSecond(bool newState)
{
fAdoptSecond = newState;
}
// ---------------------------------------------------------------------------
// ContentSpecNode: Miscellaneous
// ---------------------------------------------------------------------------
inline bool ContentSpecNode::hasAllContent() {
if (fType == ContentSpecNode::ZeroOrOne) {
return (fFirst->getType() == ContentSpecNode::All);
}
return (fType == ContentSpecNode::All);
}
XERCES_CPP_NAMESPACE_END
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,274 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: DFAContentModel.hpp 677705 2008-07-17 20:15:32Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_DFACONTENTMODEL_HPP)
#define XERCESC_INCLUDE_GUARD_DFACONTENTMODEL_HPP
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/ArrayIndexOutOfBoundsException.hpp>
#include <xercesc/framework/XMLContentModel.hpp>
#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class ContentSpecNode;
class CMLeaf;
class CMRepeatingLeaf;
class CMNode;
class CMStateSet;
//
// DFAContentModel is the heavy weight derivative of ContentModel that does
// all of the non-trivial element content validation. This guy does the full
// bore regular expression to DFA conversion to create a DFA that it then
// uses in its validation algorithm.
//
// NOTE: Upstream work insures that this guy will never see a content model
// with PCDATA in it. Any model with PCDATA is 'mixed' and is handled
// via the MixedContentModel class, since mixed models are very
// constrained in form and easily handled via a special case. This
// also makes our life much easier here.
//
class DFAContentModel : public XMLContentModel
{
public:
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
DFAContentModel
(
const bool dtd
, ContentSpecNode* const elemContentSpec
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
DFAContentModel
(
const bool dtd
, ContentSpecNode* const elemContentSpec
, const bool isMixed
, MemoryManager* const manager
);
virtual ~DFAContentModel();
// -----------------------------------------------------------------------
// Implementation of the virtual content model interface
// -----------------------------------------------------------------------
virtual bool validateContent
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual bool validateContentSpecial
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual void checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName = 0
) ;
virtual ContentLeafNameTypeVector* getContentLeafNameTypeVector() const ;
virtual unsigned int getNextState(unsigned int currentState,
XMLSize_t elementIndex) const;
virtual bool handleRepetitions( const QName* const curElem,
unsigned int curState,
unsigned int currentLoop,
unsigned int& nextState,
unsigned int& nextLoop,
XMLSize_t elementIndex,
SubstitutionGroupComparator * comparator) const;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
DFAContentModel();
DFAContentModel(const DFAContentModel&);
DFAContentModel& operator=(const DFAContentModel&);
// -----------------------------------------------------------------------
// Private helper methods
// -----------------------------------------------------------------------
void buildDFA(ContentSpecNode* const curNode);
CMNode* buildSyntaxTree(ContentSpecNode* const curNode, unsigned int& curIndex);
unsigned int* makeDefStateList() const;
unsigned int countLeafNodes(ContentSpecNode* const curNode);
class Occurence : public XMemory
{
public:
Occurence(int minOcc, int maxOcc, int eltIndex);
int minOccurs;
int maxOccurs;
int elemIndex;
};
// -----------------------------------------------------------------------
// Private data members
//
// fElemMap
// fElemMapSize
// This is the map of unique input symbol elements to indices into
// each state's per-input symbol transition table entry. This is part
// of the built DFA information that must be kept around to do the
// actual validation.
//
// fElemMapType
// This is a map of whether the element map contains information
// related to ANY models.
//
// fEmptyOk
// This is an optimization. While building the transition table we
// can see whether this content model would approve of an empty
// content (which could happen if everything was optional.) So we
// set this flag and short circuit that check, which would otherwise
// be ugly and time consuming if we tried to determine it at each
// validation call.
//
// fEOCPos
// The NFA position of the special EOC (end of content) node. This
// is saved away since its used during the DFA build.
//
// fFinalStateFlags
// This is an array of booleans, one per state (there are
// fTransTableSize states in the DFA) that indicates whether that
// state is a final state.
//
// fFollowList
// The list of follow positions for each NFA position (i.e. for each
// non-epsilon leaf node.) This is only used during the building of
// the DFA, and is let go afterwards.
//
// fHeadNode
// This is the head node of our intermediate representation. It is
// only non-null during the building of the DFA (just so that it
// does not have to be passed all around.) Once the DFA is built,
// this is no longer required so its deleted.
//
// fLeafCount
// The count of leaf nodes. This is an important number that set some
// limits on the sizes of data structures in the DFA process.
//
// fLeafList
// An array of non-epsilon leaf nodes, which is used during the DFA
// build operation, then dropped. These are just references to nodes
// pointed to by fHeadNode, so we don't have to clean them up, just
// the actually leaf list array itself needs cleanup.
//
// fLeafListType
// Array mapping ANY types to the leaf list.
//
// fTransTable
// fTransTableSize
// This is the transition table that is the main by product of all
// of the effort here. It is an array of arrays of ints. The first
// dimension is the number of states we end up with in the DFA. The
// second dimensions is the number of unique elements in the content
// model (fElemMapSize). Each entry in the second dimension indicates
// the new state given that input for the first dimension's start
// state.
//
// The fElemMap array handles mapping from element indexes to
// positions in the second dimension of the transition table.
//
// fTransTableSize is the number of valid entries in the transition
// table, and in the other related tables such as fFinalStateFlags.
//
// fCountingStates
// This is the table holding the minOccurs/maxOccurs for elements
// that can be repeated a finite number of times.
//
// fDTD
// Boolean to allow DTDs to validate even with namespace support.
//
// fIsMixed
// DFA ContentModel with mixed PCDATA.
// -----------------------------------------------------------------------
QName** fElemMap;
ContentSpecNode::NodeTypes* fElemMapType;
unsigned int fElemMapSize;
bool fEmptyOk;
unsigned int fEOCPos;
bool* fFinalStateFlags;
CMStateSet** fFollowList;
CMNode* fHeadNode;
unsigned int fLeafCount;
CMLeaf** fLeafList;
ContentSpecNode::NodeTypes* fLeafListType;
unsigned int** fTransTable;
unsigned int fTransTableSize;
Occurence** fCountingStates;
bool fDTD;
bool fIsMixed;
ContentLeafNameTypeVector * fLeafNameTypeVector;
MemoryManager* fMemoryManager;
};
inline unsigned int
DFAContentModel::getNextState(unsigned int currentState,
XMLSize_t elementIndex) const {
if (currentState == XMLContentModel::gInvalidTrans) {
return XMLContentModel::gInvalidTrans;
}
if (currentState >= fTransTableSize || elementIndex >= fElemMapSize) {
ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Array_BadIndex, fMemoryManager);
}
return fTransTable[currentState][elementIndex];
}
inline
DFAContentModel::Occurence::Occurence(int minOcc, int maxOcc, int eltIndex)
{
minOccurs = minOcc;
maxOccurs = maxOcc;
elemIndex = eltIndex;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: Grammar.cpp 471747 2006-11-06 14:31:56Z amassari $
*/
#include <xercesc/validators/common/Grammar.hpp>
//since we need to dynamically created each and every derivatives
//during deserialization by XSerializeEngine>>Derivative, we got
//to include all hpp
#include <xercesc/validators/DTD/DTDGrammar.hpp>
#include <xercesc/validators/schema/SchemaGrammar.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
XERCES_CPP_NAMESPACE_BEGIN
/***
* Support for Serialization/De-serialization
***/
IMPL_XSERIALIZABLE_NOCREATE(Grammar)
void Grammar::serialize(XSerializeEngine&)
{
//no data
}
void Grammar::storeGrammar(XSerializeEngine& serEng
, Grammar* const grammar)
{
if (grammar)
{
serEng<<(int) grammar->getGrammarType();
serEng<<grammar;
}
else
{
serEng<<(int) UnKnown;
}
}
Grammar* Grammar::loadGrammar(XSerializeEngine& serEng)
{
int type;
serEng>>type;
switch((GrammarType)type)
{
case DTDGrammarType:
DTDGrammar* dtdGrammar;
serEng>>dtdGrammar;
return dtdGrammar;
case SchemaGrammarType:
SchemaGrammar* schemaGrammar;
serEng>>schemaGrammar;
return schemaGrammar;
case UnKnown:
return 0;
default: //we treat this same as UnKnown
return 0;
}
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,204 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: Grammar.hpp 676911 2008-07-15 13:27:32Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_GRAMMAR_HPP)
#define XERCESC_INCLUDE_GUARD_GRAMMAR_HPP
#include <limits.h>
#include <xercesc/framework/XMLElementDecl.hpp>
#include <xercesc/framework/XMLEntityDecl.hpp>
#include <xercesc/framework/XMLNotationDecl.hpp>
#include <xercesc/internal/XSerializable.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class XMLGrammarDescription;
//
// This abstract class specifies the interface for a Grammar
//
class VALIDATORS_EXPORT Grammar : public XSerializable, public XMemory
{
public:
// -----------------------------------------------------------------------
// Class Specific Types
//
// DTDGrammarType - Indicate this Grammar is built from a DTD.
// SchemaGrammarType - Indicate this Grammar is built from a Schema.
//
// TOP_LEVEL_SCOPE - outermost scope level (i.e. global) of a declaration.
// For DTD, all element decls and attribute decls always
// have TOP_LEVEL_SCOPE. For schema, it may vary if
// it is inside a complex type.
//
// UNKNOWN_SCOPE - unknown scope level. None of the decls should have this.
//
// -----------------------------------------------------------------------
enum GrammarType {
DTDGrammarType
, SchemaGrammarType
, UnKnown
};
enum {
// These are well-known values that must simply be larger
// than any reasonable scope
UNKNOWN_SCOPE = UINT_MAX - 0
, TOP_LEVEL_SCOPE = UINT_MAX - 1
};
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
virtual ~Grammar(){};
// -----------------------------------------------------------------------
// Virtual Getter methods
// -----------------------------------------------------------------------
virtual GrammarType getGrammarType() const =0;
virtual const XMLCh* getTargetNamespace() const =0;
virtual bool getValidated() const = 0;
// Element Decl
// this method should only be used while the grammar is being
// constructed, not while it is being used
// in a validation episode!
virtual XMLElementDecl* findOrAddElemDecl
(
const unsigned int uriId
, const XMLCh* const baseName
, const XMLCh* const prefixName
, const XMLCh* const qName
, unsigned int scope
, bool& wasAdded
) = 0;
virtual XMLSize_t getElemId
(
const unsigned int uriId
, const XMLCh* const baseName
, const XMLCh* const qName
, unsigned int scope
) const = 0;
virtual const XMLElementDecl* getElemDecl
(
const unsigned int uriId
, const XMLCh* const baseName
, const XMLCh* const qName
, unsigned int scope
) const = 0;
virtual XMLElementDecl* getElemDecl
(
const unsigned int uriId
, const XMLCh* const baseName
, const XMLCh* const qName
, unsigned int scope
) = 0;
virtual const XMLElementDecl* getElemDecl
(
const unsigned int elemId
) const = 0;
virtual XMLElementDecl* getElemDecl
(
const unsigned int elemId
) = 0;
// Notation
virtual const XMLNotationDecl* getNotationDecl
(
const XMLCh* const notName
) const=0;
virtual XMLNotationDecl* getNotationDecl
(
const XMLCh* const notName
)=0;
// -----------------------------------------------------------------------
// Virtual Setter methods
// -----------------------------------------------------------------------
virtual XMLElementDecl* putElemDecl
(
const unsigned int uriId
, const XMLCh* const baseName
, const XMLCh* const prefixName
, const XMLCh* const qName
, unsigned int scope
, const bool notDeclared = false
) = 0;
virtual XMLSize_t putElemDecl
(
XMLElementDecl* const elemDecl
, const bool notDeclared = false
) = 0;
virtual XMLSize_t putNotationDecl
(
XMLNotationDecl* const notationDecl
) const=0;
virtual void setValidated(const bool newState) = 0;
// -----------------------------------------------------------------------
// Virtual methods
// -----------------------------------------------------------------------
virtual void reset()=0;
virtual void setGrammarDescription( XMLGrammarDescription*) = 0;
virtual XMLGrammarDescription* getGrammarDescription() const = 0;
/***
* Support for Serialization/De-serialization
***/
DECL_XSERIALIZABLE(Grammar)
static void storeGrammar(XSerializeEngine& serEng
, Grammar* const grammar);
static Grammar* loadGrammar(XSerializeEngine& serEng);
protected :
// -----------------------------------------------------------------------
// Hidden constructors
// -----------------------------------------------------------------------
Grammar(){};
private:
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
Grammar(const Grammar&);
Grammar& operator=(const Grammar&);
};
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,445 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id $
*/
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/schema/SchemaGrammar.hpp>
#include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
#include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// GrammarResolver: Constructor and Destructor
// ---------------------------------------------------------------------------
GrammarResolver::GrammarResolver(XMLGrammarPool* const gramPool
, MemoryManager* const manager)
:fCacheGrammar(false)
,fUseCachedGrammar(false)
,fGrammarPoolFromExternalApplication(true)
,fStringPool(0)
,fGrammarBucket(0)
,fGrammarFromPool(0)
,fDataTypeReg(0)
,fMemoryManager(manager)
,fGrammarPool(gramPool)
,fXSModel(0)
,fGrammarPoolXSModel(0)
,fGrammarsToAddToXSModel(0)
{
fGrammarBucket = new (manager) RefHashTableOf<Grammar>(29, true, manager);
/***
* Grammars in this set are not owned
*/
fGrammarFromPool = new (manager) RefHashTableOf<Grammar>(29, false, manager);
if (!gramPool)
{
/***
* We need to instantiate a default grammar pool object so that
* all grammars and grammar components could be created through
* the Factory methods
*/
fGrammarPool = new (manager) XMLGrammarPoolImpl(manager);
fGrammarPoolFromExternalApplication=false;
}
fStringPool = fGrammarPool->getURIStringPool();
// REVISIT: size
fGrammarsToAddToXSModel = new (manager) ValueVectorOf<SchemaGrammar*> (29, manager);
}
GrammarResolver::~GrammarResolver()
{
delete fGrammarBucket;
delete fGrammarFromPool;
if (fDataTypeReg)
delete fDataTypeReg;
/***
* delete the grammar pool iff it is created by this resolver
*/
if (!fGrammarPoolFromExternalApplication)
delete fGrammarPool;
if (fXSModel)
delete fXSModel;
// don't delete fGrammarPoolXSModel! we don't own it!
delete fGrammarsToAddToXSModel;
}
// ---------------------------------------------------------------------------
// GrammarResolver: Getter methods
// ---------------------------------------------------------------------------
DatatypeValidator*
GrammarResolver::getDatatypeValidator(const XMLCh* const uriStr,
const XMLCh* const localPartStr) {
DatatypeValidator* dv = 0;
if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
if (!fDataTypeReg) {
fDataTypeReg = new (fMemoryManager) DatatypeValidatorFactory(fMemoryManager);
}
dv = fDataTypeReg->getDatatypeValidator(localPartStr);
}
else {
Grammar* grammar = getGrammar(uriStr);
if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) {
XMLBuffer nameBuf(128, fMemoryManager);
nameBuf.set(uriStr);
nameBuf.append(chComma);
nameBuf.append(localPartStr);
dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(nameBuf.getRawBuffer());
}
}
return dv;
}
Grammar* GrammarResolver::getGrammar( const XMLCh* const namespaceKey)
{
if (!namespaceKey)
return 0;
Grammar* grammar = fGrammarBucket->get(namespaceKey);
if (grammar)
return grammar;
if (fUseCachedGrammar)
{
grammar = fGrammarFromPool->get(namespaceKey);
if (grammar)
{
return grammar;
}
else
{
XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(namespaceKey);
Janitor<XMLGrammarDescription> janName(gramDesc);
grammar = fGrammarPool->retrieveGrammar(gramDesc);
if (grammar)
{
fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
}
return grammar;
}
}
return 0;
}
Grammar* GrammarResolver::getGrammar( XMLGrammarDescription* const gramDesc)
{
if (!gramDesc)
return 0;
Grammar* grammar = fGrammarBucket->get(gramDesc->getGrammarKey());
if (grammar)
return grammar;
if (fUseCachedGrammar)
{
grammar = fGrammarFromPool->get(gramDesc->getGrammarKey());
if (grammar)
{
return grammar;
}
else
{
grammar = fGrammarPool->retrieveGrammar(gramDesc);
if (grammar)
{
fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
}
return grammar;
}
}
return 0;
}
RefHashTableOfEnumerator<Grammar>
GrammarResolver::getGrammarEnumerator() const
{
return RefHashTableOfEnumerator<Grammar>(fGrammarBucket, false, fMemoryManager);
}
RefHashTableOfEnumerator<Grammar>
GrammarResolver::getReferencedGrammarEnumerator() const
{
return RefHashTableOfEnumerator<Grammar>(fGrammarFromPool, false, fMemoryManager);
}
RefHashTableOfEnumerator<Grammar>
GrammarResolver::getCachedGrammarEnumerator() const
{
return fGrammarPool->getGrammarEnumerator();
}
bool GrammarResolver::containsNameSpace( const XMLCh* const nameSpaceKey )
{
if (!nameSpaceKey)
return false;
if (fGrammarBucket->containsKey(nameSpaceKey))
return true;
if (fUseCachedGrammar)
{
if (fGrammarFromPool->containsKey(nameSpaceKey))
return true;
// Lastly, need to check in fGrammarPool
XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(nameSpaceKey);
Janitor<XMLGrammarDescription> janName(gramDesc);
Grammar* grammar = fGrammarPool->retrieveGrammar(gramDesc);
if (grammar)
return true;
}
return false;
}
void GrammarResolver::putGrammar(Grammar* const grammarToAdopt)
{
if (!grammarToAdopt)
return;
/***
* the grammar will be either in the grammarpool, or in the grammarbucket
*/
if (!fCacheGrammar || !fGrammarPool->cacheGrammar(grammarToAdopt))
{
// either we aren't caching or the grammar pool doesn't want it
// so we need to look after it
fGrammarBucket->put( (void*) grammarToAdopt->getGrammarDescription()->getGrammarKey(), grammarToAdopt );
if (grammarToAdopt->getGrammarType() == Grammar::SchemaGrammarType)
{
fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammarToAdopt);
}
}
}
// ---------------------------------------------------------------------------
// GrammarResolver: methods
// ---------------------------------------------------------------------------
void GrammarResolver::reset() {
fGrammarBucket->removeAll();
fGrammarsToAddToXSModel->removeAllElements();
delete fXSModel;
fXSModel = 0;
}
void GrammarResolver::resetCachedGrammar()
{
//REVISIT: if the pool is locked this will fail... should throw an exception?
fGrammarPool->clear();
// Even though fXSModel and fGrammarPoolXSModel will be invalid don't touch
// them here as getXSModel will handle this.
//to clear all other references to the grammars just deleted from fGrammarPool
fGrammarFromPool->removeAll();
}
void GrammarResolver::cacheGrammars()
{
RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
ValueVectorOf<XMLCh*> keys(8, fMemoryManager);
unsigned int keyCount = 0;
// Build key set
while (grammarEnum.hasMoreElements())
{
XMLCh* grammarKey = (XMLCh*) grammarEnum.nextElementKey();
keys.addElement(grammarKey);
keyCount++;
}
// PSVI: assume everything will be added, if caching fails add grammar back
// into vector
fGrammarsToAddToXSModel->removeAllElements();
// Cache
for (unsigned int i = 0; i < keyCount; i++)
{
XMLCh* grammarKey = keys.elementAt(i);
/***
* It is up to the GrammarPool implementation to handle duplicated grammar
*/
Grammar* grammar = fGrammarBucket->get(grammarKey);
if(fGrammarPool->cacheGrammar(grammar))
{
// only orphan grammar if grammar pool accepts caching of it
fGrammarBucket->orphanKey(grammarKey);
}
else if (grammar->getGrammarType() == Grammar::SchemaGrammarType)
{
// add it back to list of grammars not in grammar pool
fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammar);
}
}
}
// ---------------------------------------------------------------------------
// GrammarResolver: Setter methods
// ---------------------------------------------------------------------------
void GrammarResolver::cacheGrammarFromParse(const bool aValue)
{
reset();
fCacheGrammar = aValue;
}
Grammar* GrammarResolver::orphanGrammar(const XMLCh* const nameSpaceKey)
{
if (fCacheGrammar)
{
Grammar* grammar = fGrammarPool->orphanGrammar(nameSpaceKey);
if (grammar)
{
if (fGrammarFromPool->containsKey(nameSpaceKey))
fGrammarFromPool->removeKey(nameSpaceKey);
}
// Check to see if it's in fGrammarBucket, since
// we put it there if the grammar pool refused to
// cache it.
else if (fGrammarBucket->containsKey(nameSpaceKey))
{
grammar = fGrammarBucket->orphanKey(nameSpaceKey);
}
return grammar;
}
else
{
return fGrammarBucket->orphanKey(nameSpaceKey);
}
}
XSModel *GrammarResolver::getXSModel()
{
XSModel* xsModel;
if (fCacheGrammar || fUseCachedGrammar)
{
// We know if the grammarpool changed thru caching, orphaning and erasing
// but NOT by other mechanisms such as lockPool() or unlockPool() so it
// is safest to always get it. The grammarPool XSModel will only be
// regenerated if something changed.
bool XSModelWasChanged;
// The grammarpool will always return an xsmodel, even if it is just
// the schema for schema xsmodel...
xsModel = fGrammarPool->getXSModel(XSModelWasChanged);
if (XSModelWasChanged)
{
// we know the grammarpool XSModel has changed or this is the
// first call to getXSModel
if (!fGrammarPoolXSModel && (fGrammarsToAddToXSModel->size() == 0) &&
!fXSModel)
{
fGrammarPoolXSModel = xsModel;
return fGrammarPoolXSModel;
}
else
{
fGrammarPoolXSModel = xsModel;
// We had previously augmented the grammar pool XSModel
// with our our grammars or we would like to upate it now
// so we have to regenerate the XSModel
fGrammarsToAddToXSModel->removeAllElements();
RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
while (grammarEnum.hasMoreElements())
{
Grammar& grammar = (Grammar&) grammarEnum.nextElement();
if (grammar.getGrammarType() == Grammar::SchemaGrammarType)
fGrammarsToAddToXSModel->addElement((SchemaGrammar*)&grammar);
}
delete fXSModel;
if (fGrammarsToAddToXSModel->size())
{
fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
fGrammarsToAddToXSModel->removeAllElements();
return fXSModel;
}
fXSModel = 0;
return fGrammarPoolXSModel;
}
}
else {
// we know that the grammar pool XSModel is the same as before
if (fGrammarsToAddToXSModel->size())
{
// we need to update our fXSModel with the new grammars
if (fXSModel)
{
xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);
fXSModel = xsModel;
}
else
{
fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
}
fGrammarsToAddToXSModel->removeAllElements();
return fXSModel;
}
// Nothing has changed!
if (fXSModel)
{
return fXSModel;
}
else if (fGrammarPoolXSModel)
{
return fGrammarPoolXSModel;
}
fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);
return fXSModel;
}
}
// Not Caching...
if (fGrammarsToAddToXSModel->size())
{
xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);
fGrammarsToAddToXSModel->removeAllElements();
fXSModel = xsModel;
}
else if (!fXSModel)
{
// create a new model only if we didn't have one already
fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);
}
return fXSModel;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,271 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: GrammarResolver.hpp 932887 2010-04-11 13:04:59Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_GRAMMARRESOLVER_HPP)
#define XERCESC_INCLUDE_GUARD_GRAMMARRESOLVER_HPP
#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/util/RefHashTableOf.hpp>
#include <xercesc/util/StringPool.hpp>
#include <xercesc/validators/common/Grammar.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class DatatypeValidator;
class DatatypeValidatorFactory;
class XMLGrammarDescription;
/**
* This class embodies the representation of a Grammar pool Resolver.
* This class is called from the validator.
*
*/
class VALIDATORS_EXPORT GrammarResolver : public XMemory
{
public:
/** @name Constructor and Destructor */
//@{
/**
*
* Default Constructor
*/
GrammarResolver(
XMLGrammarPool* const gramPool
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
/**
* Destructor
*/
~GrammarResolver();
//@}
/** @name Getter methods */
//@{
/**
* Retrieve the DatatypeValidator
*
* @param uriStr the namespace URI
* @param typeName the type name
* @return the DatatypeValidator associated with namespace & type name
*/
DatatypeValidator* getDatatypeValidator(const XMLCh* const uriStr,
const XMLCh* const typeName);
/**
* Retrieve the DatatypeValidatorFactory used for built-in schema types
*
* @return the DatatypeValidator associated with namespace for XMLSchema
*/
DatatypeValidatorFactory* getBuiltinDatatypeValidatorFactory();
/**
* Retrieve the grammar that is associated with the specified namespace key
*
* @param gramDesc grammar description for the grammar
* @return Grammar abstraction associated with the grammar description
*/
Grammar* getGrammar( XMLGrammarDescription* const gramDesc ) ;
/**
* Retrieve the grammar that is associated with the specified namespace key
*
* @param namespaceKey Namespace key into Grammar pool
* @return Grammar abstraction associated with the NameSpace key.
*/
Grammar* getGrammar( const XMLCh* const namespaceKey ) ;
/**
* Get an enumeration of Grammar in the Grammar pool
*
* @return enumeration of Grammar in Grammar pool
*/
RefHashTableOfEnumerator<Grammar> getGrammarEnumerator() const;
/**
* Get an enumeration of the referenced Grammars
*
* @return enumeration of referenced Grammars
*/
RefHashTableOfEnumerator<Grammar> getReferencedGrammarEnumerator() const;
/**
* Get an enumeration of the cached Grammars in the Grammar pool
*
* @return enumeration of the cached Grammars in Grammar pool
*/
RefHashTableOfEnumerator<Grammar> getCachedGrammarEnumerator() const;
/**
* Get a string pool of schema grammar element/attribute names/prefixes
* (used by TraverseSchema)
*
* @return a string pool of schema grammar element/attribute names/prefixes
*/
XMLStringPool* getStringPool();
/**
* Is the specified Namespace key in Grammar pool?
*
* @param nameSpaceKey Namespace key
* @return True if Namespace key association is in the Grammar pool.
*/
bool containsNameSpace( const XMLCh* const nameSpaceKey );
inline XMLGrammarPool* getGrammarPool() const;
inline MemoryManager* getGrammarPoolMemoryManager() const;
//@}
/** @name Setter methods */
//@{
/**
* Set the 'Grammar caching' flag
*/
void cacheGrammarFromParse(const bool newState);
/**
* Set the 'Use cached grammar' flag
*/
void useCachedGrammarInParse(const bool newState);
//@}
/** @name GrammarResolver methods */
//@{
/**
* Add the Grammar with Namespace Key associated to the Grammar Pool.
* The Grammar will be owned by the Grammar Pool.
*
* @param grammarToAdopt Grammar abstraction used by validator.
*/
void putGrammar(Grammar* const grammarToAdopt );
/**
* Returns the Grammar with Namespace Key associated from the Grammar Pool
* The Key entry is removed from the table (grammar is not deleted if
* adopted - now owned by caller).
*
* @param nameSpaceKey Key to associate with Grammar abstraction
*/
Grammar* orphanGrammar(const XMLCh* const nameSpaceKey);
/**
* Cache the grammars in fGrammarBucket to fCachedGrammarRegistry.
* If a grammar with the same key is already cached, an exception is
* thrown and none of the grammars will be cached.
*/
void cacheGrammars();
/**
* Reset internal Namespace/Grammar registry.
*/
void reset();
void resetCachedGrammar();
/**
* Returns an XSModel, either from the GrammarPool or by creating one
*/
XSModel* getXSModel();
ValueVectorOf<SchemaGrammar*>* getGrammarsToAddToXSModel();
//@}
private:
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
GrammarResolver(const GrammarResolver&);
GrammarResolver& operator=(const GrammarResolver&);
// -----------------------------------------------------------------------
// Private data members
//
// fStringPool The string pool used by TraverseSchema to store
// element/attribute names and prefixes.
// Always owned by Grammar pool implementation
//
// fGrammarBucket The parsed Grammar Pool, if no caching option.
//
// fGrammarFromPool Referenced Grammar Set, not owned
//
// fGrammarPool The Grammar Set either plugged or created.
//
// fDataTypeReg DatatypeValidatorFactory registry
//
// fMemoryManager Pluggable memory manager for dynamic memory
// allocation/deallocation
// -----------------------------------------------------------------------
bool fCacheGrammar;
bool fUseCachedGrammar;
bool fGrammarPoolFromExternalApplication;
XMLStringPool* fStringPool;
RefHashTableOf<Grammar>* fGrammarBucket;
RefHashTableOf<Grammar>* fGrammarFromPool;
DatatypeValidatorFactory* fDataTypeReg;
MemoryManager* fMemoryManager;
XMLGrammarPool* fGrammarPool;
XSModel* fXSModel;
XSModel* fGrammarPoolXSModel;
ValueVectorOf<SchemaGrammar*>* fGrammarsToAddToXSModel;
};
inline XMLStringPool* GrammarResolver::getStringPool() {
return fStringPool;
}
inline void GrammarResolver::useCachedGrammarInParse(const bool aValue)
{
fUseCachedGrammar = aValue;
}
inline XMLGrammarPool* GrammarResolver::getGrammarPool() const
{
return fGrammarPool;
}
inline MemoryManager* GrammarResolver::getGrammarPoolMemoryManager() const
{
return fGrammarPool->getMemoryManager();
}
inline ValueVectorOf<SchemaGrammar*>* GrammarResolver::getGrammarsToAddToXSModel()
{
return fGrammarsToAddToXSModel;
}
inline DatatypeValidatorFactory* GrammarResolver::getBuiltinDatatypeValidatorFactory()
{
return fDataTypeReg;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,429 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: MixedContentModel.cpp 676911 2008-07-15 13:27:32Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <string.h>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/framework/XMLElementDecl.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/common/MixedContentModel.hpp>
#include <xercesc/validators/common/CMStateSet.hpp>
#include <xercesc/validators/common/Grammar.hpp>
#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// MixedContentModel: Constructors and Destructor
// ---------------------------------------------------------------------------
MixedContentModel::MixedContentModel(const bool dtd
, ContentSpecNode* const parentContentSpec
, const bool ordered
, MemoryManager* const manager) :
fCount(0)
, fChildren(0)
, fChildTypes(0)
, fOrdered(ordered)
, fDTD(dtd)
, fMemoryManager(manager)
{
//
// Create a vector of unsigned ints that will be filled in with the
// ids of the child nodes. It will be expanded as needed but we give
// it an initial capacity of 64 which should be more than enough for
// 99% of the scenarios.
//
ValueVectorOf<QName*> children(64, fMemoryManager);
ValueVectorOf<ContentSpecNode::NodeTypes> childTypes(64, fMemoryManager);
//
// Get the parent element's content spec. This is the head of the tree
// of nodes that describes the content model. We will iterate this
// tree.
//
ContentSpecNode* curNode = parentContentSpec;
if (!curNode)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoParentCSN, fMemoryManager);
// And now call the private recursive method that iterates the tree
buildChildList(curNode, children, childTypes);
//
// And now we know how many elements we need in our member list. So
// fill them in.
//
fCount = children.size();
fChildren = (QName**) fMemoryManager->allocate(fCount * sizeof(QName*)); //new QName*[fCount];
fChildTypes = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
(
fCount * sizeof(ContentSpecNode::NodeTypes)
); //new ContentSpecNode::NodeTypes[fCount];
for (XMLSize_t index = 0; index < fCount; index++) {
fChildren[index] = new (fMemoryManager) QName(*children.elementAt(index));
fChildTypes[index] = childTypes.elementAt(index);
}
}
MixedContentModel::~MixedContentModel()
{
for (XMLSize_t index = 0; index < fCount; index++) {
delete fChildren[index];
}
fMemoryManager->deallocate(fChildren); //delete [] fChildren;
fMemoryManager->deallocate(fChildTypes); //delete [] fChildTypes;
}
// ---------------------------------------------------------------------------
// MixedContentModel: Getter methods
// ---------------------------------------------------------------------------
bool MixedContentModel::hasDups() const
{
// Can't have dups if only one child
if (fCount == 1)
return false;
for (XMLSize_t index = 0; index < fCount; index++)
{
const QName* curVal = fChildren[index];
for (XMLSize_t iIndex = 0; iIndex < fCount; iIndex++)
{
if (iIndex == index)
continue;
if (fDTD) {
if (XMLString::equals(curVal->getRawName(), fChildren[iIndex]->getRawName())) {
return true;
}
}
else {
if ((curVal->getURI() == fChildren[iIndex]->getURI()) &&
(XMLString::equals(curVal->getLocalPart(), fChildren[iIndex]->getLocalPart()))) {
return true;
}
}
}
}
return false;
}
// ---------------------------------------------------------------------------
// MixedContentModel: Implementation of the ContentModel virtual interface
// ---------------------------------------------------------------------------
//
//Under the XML Schema mixed model,
//the order and number of child elements appearing in an instance
//must agree with
//the order and number of child elements specified in the model.
//
bool
MixedContentModel::validateContent( QName** const children
, XMLSize_t childCount
, unsigned int
, XMLSize_t* indexFailingChild
, MemoryManager* const) const
{
// must match order
if (fOrdered) {
unsigned int inIndex = 0;
for (unsigned int outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
const QName* curChild = children[outIndex];
// If its PCDATA, then we just accept that
if (curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
ContentSpecNode::NodeTypes type = fChildTypes[inIndex];
const QName* inChild = fChildren[inIndex];
if (type == ContentSpecNode::Leaf) {
if (fDTD) {
if (!XMLString::equals(inChild->getRawName(), curChild->getRawName())) {
*indexFailingChild=outIndex;
return false;
}
}
else {
if ((inChild->getURI() != curChild->getURI()) ||
(!XMLString::equals(inChild->getLocalPart(), curChild->getLocalPart()))) {
*indexFailingChild=outIndex;
return false;
}
}
}
else if (type == ContentSpecNode::Any) {
}
else if (type == ContentSpecNode::Any_NS) {
if (inChild->getURI() != curChild->getURI())
{
*indexFailingChild=outIndex;
return false;
}
}
else if (type == ContentSpecNode::Any_Other)
{
// Here we assume that empty string has id 1.
//
unsigned int uriId = curChild->getURI();
if (uriId == 1 || uriId == inChild->getURI())
{
*indexFailingChild=outIndex;
return false;
}
}
// advance index
inIndex++;
}
}
// can appear in any order
else {
for (unsigned int outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
const QName* curChild = children[outIndex];
// If its PCDATA, then we just accept that
if (curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
// And try to find it in our list
unsigned int inIndex = 0;
for (; inIndex < fCount; inIndex++)
{
ContentSpecNode::NodeTypes type = fChildTypes[inIndex];
const QName* inChild = fChildren[inIndex];
if (type == ContentSpecNode::Leaf) {
if (fDTD) {
if (XMLString::equals(inChild->getRawName(), curChild->getRawName())) {
break;
}
}
else {
if ((inChild->getURI() == curChild->getURI()) &&
(XMLString::equals(inChild->getLocalPart(), curChild->getLocalPart()))) {
break;
}
}
}
else if (type == ContentSpecNode::Any) {
break;
}
else if (type == ContentSpecNode::Any_NS) {
if (inChild->getURI() == curChild->getURI())
break;
}
else if (type == ContentSpecNode::Any_Other)
{
// Here we assume that empty string has id 1.
//
unsigned int uriId = curChild->getURI();
if (uriId != 1 && uriId != inChild->getURI())
break;
}
// REVISIT: What about checking for multiple ANY matches?
// The content model ambiguity *could* be checked
// by the caller before constructing the mixed
// content model.
}
// We did not find this one, so the validation failed
if (inIndex == fCount)
{
*indexFailingChild=outIndex;
return false;
}
}
}
// Everything seems to be in order, so return success
return true;
}
bool MixedContentModel::validateContentSpecial(QName** const children
, XMLSize_t childCount
, unsigned int
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const) const
{
SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
// must match order
if (fOrdered) {
unsigned int inIndex = 0;
for (unsigned int outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
QName* curChild = children[outIndex];
// If its PCDATA, then we just accept that
if (curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
ContentSpecNode::NodeTypes type = fChildTypes[inIndex];
QName* inChild = fChildren[inIndex];
if (type == ContentSpecNode::Leaf) {
if ( !comparator.isEquivalentTo(curChild, inChild))
{
*indexFailingChild=outIndex;
return false;
}
}
else if (type == ContentSpecNode::Any) {
}
else if (type == ContentSpecNode::Any_NS) {
if (inChild->getURI() != curChild->getURI())
{
*indexFailingChild=outIndex;
return false;
}
}
else if (type == ContentSpecNode::Any_Other)
{
// Here we assume that empty string has id 1.
//
unsigned int uriId = curChild->getURI();
if (uriId == 1 || uriId == inChild->getURI())
{
*indexFailingChild=outIndex;
return false;
}
}
// advance index
inIndex++;
}
}
// can appear in any order
else {
for (unsigned int outIndex = 0; outIndex < childCount; outIndex++) {
// Get the current child out of the source index
QName* curChild = children[outIndex];
// If its PCDATA, then we just accept that
if (curChild->getURI() == XMLElementDecl::fgPCDataElemId)
continue;
// And try to find it in our list
unsigned int inIndex = 0;
for (; inIndex < fCount; inIndex++)
{
ContentSpecNode::NodeTypes type = fChildTypes[inIndex];
QName* inChild = fChildren[inIndex];
if (type == ContentSpecNode::Leaf) {
if ( comparator.isEquivalentTo(curChild, inChild))
break;
}
else if (type == ContentSpecNode::Any) {
break;
}
else if (type == ContentSpecNode::Any_NS) {
if (inChild->getURI() == curChild->getURI())
break;
}
else if (type == ContentSpecNode::Any_Other)
{
// Here we assume that empty string has id 1.
//
unsigned int uriId = curChild->getURI();
if (uriId != 1 && uriId != inChild->getURI())
break;
}
// REVISIT: What about checking for multiple ANY matches?
// The content model ambiguity *could* be checked
// by the caller before constructing the mixed
// content model.
}
// We did not find this one, so the validation failed
if (inIndex == fCount)
{
*indexFailingChild=outIndex;
return false;
}
}
}
// Everything seems to be in order, so return success
return true;
}
// ---------------------------------------------------------------------------
// MixedContentModel: Private helper methods
// ---------------------------------------------------------------------------
void
MixedContentModel::buildChildList( ContentSpecNode* const curNode
, ValueVectorOf<QName*>& toFill
, ValueVectorOf<ContentSpecNode::NodeTypes>& toType)
{
// Get the type of spec node our current node is
const ContentSpecNode::NodeTypes curType = curNode->getType();
// If its a leaf, then store its id in the target list
if ((curType == ContentSpecNode::Leaf) ||
(curType == ContentSpecNode::Any) ||
(curType == ContentSpecNode::Any_Other) ||
(curType == ContentSpecNode::Any_NS) )
{
toFill.addElement(curNode->getElement());
toType.addElement(curType);
return;
}
// Get both the child node pointers
ContentSpecNode* leftNode = curNode->getFirst();
ContentSpecNode* rightNode = curNode->getSecond();
// And recurse according to the type of node
if (((curType & 0x0f) == ContentSpecNode::Choice)
|| ((curType & 0x0f) == ContentSpecNode::Sequence))
{
// Recurse on the left and right nodes
buildChildList(leftNode, toFill, toType);
// The last node of a choice or sequence has a null right
if (rightNode)
buildChildList(rightNode, toFill, toType);
}
else if ((curType == ContentSpecNode::OneOrMore)
|| (curType == ContentSpecNode::ZeroOrOne)
|| (curType == ContentSpecNode::ZeroOrMore))
{
// Just do the left node on this one
buildChildList(leftNode, toFill, toType);
}
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,212 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: MixedContentModel.hpp 901107 2010-01-20 08:45:02Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_MIXEDCONTENTMODEL_HPP)
#define XERCESC_INCLUDE_GUARD_MIXEDCONTENTMODEL_HPP
#include <xercesc/util/ValueVectorOf.hpp>
#include <xercesc/framework/XMLContentModel.hpp>
#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
XERCES_CPP_NAMESPACE_BEGIN
class ContentSpecNode;
//
// MixedContentModel is a derivative of the abstract content model base
// class that handles the special case of mixed model elements. If an element
// is mixed model, it has PCDATA as its first possible content, followed
// by an alternation of the possible children. The children cannot have any
// numeration or order, so it must look like this:
//
// <!ELEMENT Foo ((#PCDATA|a|b|c|)*)>
//
// So, all we have to do is to keep an array of the possible children and
// validate by just looking up each child being validated by looking it up
// in the list.
//
class MixedContentModel : public XMLContentModel
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
MixedContentModel
(
const bool dtd
, ContentSpecNode* const parentContentSpec
, const bool ordered = false
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~MixedContentModel();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
bool hasDups() const;
// -----------------------------------------------------------------------
// Implementation of the ContentModel virtual interface
// -----------------------------------------------------------------------
virtual bool validateContent
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual bool validateContentSpecial
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual ContentLeafNameTypeVector* getContentLeafNameTypeVector() const ;
virtual unsigned int getNextState(unsigned int currentState,
XMLSize_t elementIndex) const;
virtual bool handleRepetitions( const QName* const curElem,
unsigned int curState,
unsigned int currentLoop,
unsigned int& nextState,
unsigned int& nextLoop,
XMLSize_t elementIndex,
SubstitutionGroupComparator * comparator) const;
virtual void checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName = 0
) ;
private :
// -----------------------------------------------------------------------
// Private helper methods
// -----------------------------------------------------------------------
void buildChildList
(
ContentSpecNode* const curNode
, ValueVectorOf<QName*>& toFill
, ValueVectorOf<ContentSpecNode::NodeTypes>& toType
);
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
MixedContentModel();
MixedContentModel(const MixedContentModel&);
MixedContentModel& operator=(const MixedContentModel&);
// -----------------------------------------------------------------------
// Private data members
//
// fCount
// The count of possible children in the fChildren member.
//
// fChildren
// The list of possible children that we have to accept. This array
// is allocated as large as needed in the constructor.
//
// fChildTypes
// The type of the children to support ANY.
//
// fOrdered
// True if mixed content model is ordered. DTD mixed content models
// are <em>always</em> unordered.
//
// fDTD
// Boolean to allow DTDs to validate even with namespace support.
//
// -----------------------------------------------------------------------
XMLSize_t fCount;
QName** fChildren;
ContentSpecNode::NodeTypes* fChildTypes;
bool fOrdered;
bool fDTD;
MemoryManager* fMemoryManager;
};
inline ContentLeafNameTypeVector* MixedContentModel::getContentLeafNameTypeVector() const
{
return 0;
}
inline unsigned int
MixedContentModel::getNextState(unsigned int,
XMLSize_t) const {
return XMLContentModel::gInvalidTrans;
}
inline bool
MixedContentModel::handleRepetitions( const QName* const /*curElem*/,
unsigned int /*curState*/,
unsigned int /*currentLoop*/,
unsigned int& /*nextState*/,
unsigned int& /*nextLoop*/,
XMLSize_t /*elementIndex*/,
SubstitutionGroupComparator * /*comparator*/) const
{
return true;
}
inline void MixedContentModel::checkUniqueParticleAttribution
(
SchemaGrammar* const
, GrammarResolver* const
, XMLStringPool* const
, XMLValidator* const
, unsigned int* const pContentSpecOrgURI
, const XMLCh* /*pComplexTypeName*/ /*= 0*/
)
{
// rename back
unsigned int i = 0;
for (i = 0; i < fCount; i++) {
unsigned int orgURIIndex = fChildren[i]->getURI();
if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
(orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
(orgURIIndex != XMLElementDecl::fgPCDataElemId))
fChildren[i]->setURI(pContentSpecOrgURI[orgURIIndex]);
}
// for mixed content model, it's only a sequence
// UPA checking is not necessary
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,534 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: SimpleContentModel.cpp 799211 2009-07-30 09:06:43Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/validators/common/SimpleContentModel.hpp>
#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
#include <xercesc/validators/schema/XercesElementWildcard.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// SimpleContentModel: Implementation of the ContentModel virtual interface
// ---------------------------------------------------------------------------
//
// This method is called to validate our content. For this one, its just a
// pretty simple 'bull your way through it' test according to what kind of
// operation it is for.
//
bool
SimpleContentModel::validateContent(QName** const children
, XMLSize_t childCount
, unsigned int
, XMLSize_t* indexFailingChild
, MemoryManager* const) const
{
//
// According to the type of operation, we do the correct type of
// content check.
//
XMLSize_t index;
switch(fOp & 0x0f)
{
case ContentSpecNode::Leaf :
//
// There can only be one child and it has to be of the
// element type we stored.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
// If the 0th child is not the right kind, report an error at 0
if (fDTD) {
if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
*indexFailingChild=0;
return false;
}
}
else {
if ((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
*indexFailingChild=0;
return false;
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::ZeroOrOne :
//
// If the child count is greater than one, then obviously
// bad. Otherwise, if its one, then the one child must be
// of the type we stored.
//
if (childCount == 1) {
if (fDTD) {
if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
*indexFailingChild=0;
return false;
}
}
else {
if ((children[0]->getURI() != fFirstChild->getURI()) ||
(!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))) {
*indexFailingChild=0;
return false;
}
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::ZeroOrMore :
//
// If the child count is zero, that's fine. If its more than
// zero, then make sure that all children are of the element
// type that we stored.
//
if (childCount > 0)
{
if (fDTD) {
for (index = 0; index < childCount; index++) {
if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
*indexFailingChild=index;
return false;
}
}
}
else {
for (index = 0; index < childCount; index++) {
if ((children[index]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
*indexFailingChild=index;
return false;
}
}
}
}
break;
case ContentSpecNode::OneOrMore :
//
// If the child count is zero, that's an error. If its more
// than zero, then make sure that all children are of the
// element type that we stored.
//
if (childCount == 0)
{
*indexFailingChild=0;
return false;
}
if (fDTD) {
for (index = 0; index < childCount; index++) {
if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
*indexFailingChild=index;
return false;
}
}
}
else {
for (index = 0; index < childCount; index++) {
if ((children[index]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
*indexFailingChild=index;
return false;
}
}
}
break;
case ContentSpecNode::Choice :
//
// There can only be one child, and it must be one of the
// two types we stored.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
if (fDTD) {
if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName()) &&
!XMLString::equals(children[0]->getRawName(), fSecondChild->getRawName())) {
*indexFailingChild=0;
return false;
}
}
else {
if (((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
((children[0]->getURI() != fSecondChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart()))) {
*indexFailingChild=0;
return false;
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::Sequence :
//
// There must be two children and they must be the two values
// we stored, in the stored order. So first check the obvious
// problem of an empty content, which would never be valid
// in this content mode.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
// test first child
if (fDTD) {
if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
*indexFailingChild=0;
return false;
}
}
else {
if ((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
*indexFailingChild=0;
return false;
}
}
// test second child, if present
if( childCount == 1)
{
// missing second child
*indexFailingChild=1;
return false;
}
else
{
if (fDTD) {
if (!XMLString::equals(children[1]->getRawName(), fSecondChild->getRawName())) {
*indexFailingChild=1;
return false;
}
}
else {
if ((children[1]->getURI() != fSecondChild->getURI()) ||
!XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart())) {
*indexFailingChild=1;
return false;
}
}
if (childCount > 2) {
*indexFailingChild=2;
return false;
}
}
break;
default :
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
break;
}
return true;
}
bool SimpleContentModel::validateContentSpecial(QName** const children
, XMLSize_t childCount
, unsigned int
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const) const
{
SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
//
// According to the type of operation, we do the correct type of
// content check.
//
unsigned int index;
switch(fOp & 0x0f)
{
case ContentSpecNode::Leaf :
//
// There can only be one child and it has to be of the
// element type we stored.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
if ((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
{
if (!comparator.isEquivalentTo(children[0], fFirstChild))
{
*indexFailingChild=0;
return false;
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::ZeroOrOne :
//
// If the child count is greater than one, then obviously
// bad. Otherwise, if its one, then the one child must be
// of the type we stored.
//
if ((childCount == 1) &&
((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())))
{
if(!comparator.isEquivalentTo(children[0], fFirstChild))
{
*indexFailingChild=0;
return false;
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::ZeroOrMore :
//
// If the child count is zero, that's fine. If its more than
// zero, then make sure that all children are of the element
// type that we stored.
//
if (childCount > 0)
{
for (index = 0; index < childCount; index++)
{
if ((children[index]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
{
if (!comparator.isEquivalentTo(children[index], fFirstChild))
{
*indexFailingChild=index;
return false;
}
}
}
}
break;
case ContentSpecNode::OneOrMore :
//
// If the child count is zero, that's an error. If its more
// than zero, then make sure that all children are of the
// element type that we stored.
//
if (childCount == 0)
{
*indexFailingChild=0;
return false;
}
for (index = 0; index < childCount; index++)
{
if ((children[index]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
{
if (!comparator.isEquivalentTo(children[index], fFirstChild))
{
*indexFailingChild=index;
return false;
}
}
}
break;
case ContentSpecNode::Choice :
//
// There can only be one child, and it must be one of the
// two types we stored.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
if (((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
((children[0]->getURI() != fSecondChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart())))
{
if (!comparator.isEquivalentTo(children[0], fFirstChild) &&
!comparator.isEquivalentTo(children[0], fSecondChild) )
{
*indexFailingChild=0;
return false;
}
}
if (childCount > 1)
{
*indexFailingChild=1;
return false;
}
break;
case ContentSpecNode::Sequence :
//
// There must be two children and they must be the two values
// we stored, in the stored order. So first check the obvious
// problem of an empty content, which would never be valid
// in this content mode.
//
if (!childCount)
{
*indexFailingChild=0;
return false;
}
// test first child
if ((children[0]->getURI() != fFirstChild->getURI()) ||
!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
{
if(!comparator.isEquivalentTo(children[0], fFirstChild))
{
*indexFailingChild=0;
return false;
}
}
// test second child, if present
if( childCount == 1)
{
// missing second child
*indexFailingChild=1;
return false;
}
else
{
if ((children[1]->getURI() != fSecondChild->getURI()) ||
!XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart()))
{
if (!comparator.isEquivalentTo(children[1], fSecondChild))
{
*indexFailingChild=1;
return false;
}
}
if (childCount > 2) {
*indexFailingChild=2;
return false;
}
}
break;
default :
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
break;
}
return true;
}
ContentLeafNameTypeVector* SimpleContentModel::getContentLeafNameTypeVector() const
{
return 0;
}
void SimpleContentModel::checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName /*= 0*/
)
{
// rename back
unsigned int orgURIIndex = 0;
orgURIIndex = fFirstChild->getURI();
if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
(orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
(orgURIIndex != XMLElementDecl::fgPCDataElemId))
fFirstChild->setURI(pContentSpecOrgURI[orgURIIndex]);
orgURIIndex = fSecondChild->getURI();
if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
(orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
(orgURIIndex != XMLElementDecl::fgPCDataElemId))
fSecondChild->setURI(pContentSpecOrgURI[orgURIIndex]);
// only possible violation is when it's a choice
if ((fOp & 0x0f) == ContentSpecNode::Choice) {
SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
if (XercesElementWildcard::conflict(pGrammar,
ContentSpecNode::Leaf,
fFirstChild,
ContentSpecNode::Leaf,
fSecondChild,
&comparator))
pValidator->emitError(XMLValid::UniqueParticleAttributionFail,
pComplexTypeName,
fFirstChild->getRawName(),
fSecondChild->getRawName());
}
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,212 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: SimpleContentModel.hpp 901107 2010-01-20 08:45:02Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_SIMPLECONTENTMODEL_HPP)
#define XERCESC_INCLUDE_GUARD_SIMPLECONTENTMODEL_HPP
#include <xercesc/framework/XMLContentModel.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// SimpleContentModel is a derivative of the abstract content model base
// class that handles a small set of simple content models that are just
// way overkill to give the DFA treatment.
//
// DESCRIPTION:
//
// This guy handles the following scenarios:
//
// a
// a?
// a*
// a+
// a,b
// a|b
//
// These all involve a unary operation with one element type, or a binary
// operation with two elements. These are very simple and can be checked
// in a simple way without a DFA and without the overhead of setting up a
// DFA for such a simple check.
//
// NOTE: Pass the XMLElementDecl::fgPCDataElemId value to represent a
// PCData node. Pass XMLElementDecl::fgInvalidElemId for unused element
//
class SimpleContentModel : public XMLContentModel
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
SimpleContentModel
(
const bool dtd
, QName* const firstChild
, QName* const secondChild
, const ContentSpecNode::NodeTypes cmOp
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
);
~SimpleContentModel();
// -----------------------------------------------------------------------
// Implementation of the ContentModel virtual interface
// -----------------------------------------------------------------------
virtual bool validateContent
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual bool validateContentSpecial
(
QName** const children
, XMLSize_t childCount
, unsigned int emptyNamespaceId
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLSize_t* indexFailingChild
, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
) const;
virtual ContentLeafNameTypeVector *getContentLeafNameTypeVector() const;
virtual unsigned int getNextState(unsigned int currentState,
XMLSize_t elementIndex) const;
virtual bool handleRepetitions( const QName* const curElem,
unsigned int curState,
unsigned int currentLoop,
unsigned int& nextState,
unsigned int& nextLoop,
XMLSize_t elementIndex,
SubstitutionGroupComparator * comparator) const;
virtual void checkUniqueParticleAttribution
(
SchemaGrammar* const pGrammar
, GrammarResolver* const pGrammarResolver
, XMLStringPool* const pStringPool
, XMLValidator* const pValidator
, unsigned int* const pContentSpecOrgURI
, const XMLCh* pComplexTypeName = 0
) ;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
SimpleContentModel();
SimpleContentModel(const SimpleContentModel&);
SimpleContentModel& operator=(const SimpleContentModel&);
// -----------------------------------------------------------------------
// Private data members
//
// fFirstChild
// fSecondChild
// The first (and optional second) child node. The
// operation code tells us whether the second child is used or not.
//
// fOp
// The operation that this object represents. Since this class only
// does simple contents, there is only ever a single operation
// involved (i.e. the children of the operation are always one or
// two leafs.)
//
// fDTD
// Boolean to allow DTDs to validate even with namespace support. */
//
// -----------------------------------------------------------------------
QName* fFirstChild;
QName* fSecondChild;
ContentSpecNode::NodeTypes fOp;
bool fDTD;
MemoryManager* const fMemoryManager;
};
// ---------------------------------------------------------------------------
// SimpleContentModel: Constructors and Destructor
// ---------------------------------------------------------------------------
inline SimpleContentModel::SimpleContentModel
(
const bool dtd
, QName* const firstChild
, QName* const secondChild
, const ContentSpecNode::NodeTypes cmOp
, MemoryManager* const manager
)
: fFirstChild(0)
, fSecondChild(0)
, fOp(cmOp)
, fDTD(dtd)
, fMemoryManager(manager)
{
if (firstChild)
fFirstChild = new (manager) QName(*firstChild);
else
fFirstChild = new (manager) QName(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, XMLElementDecl::fgInvalidElemId, manager);
if (secondChild)
fSecondChild = new (manager) QName(*secondChild);
else
fSecondChild = new (manager) QName(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, XMLElementDecl::fgInvalidElemId, manager);
}
inline SimpleContentModel::~SimpleContentModel()
{
delete fFirstChild;
delete fSecondChild;
}
// ---------------------------------------------------------------------------
// SimpleContentModel: Virtual methods
// ---------------------------------------------------------------------------
inline unsigned int
SimpleContentModel::getNextState(unsigned int,
XMLSize_t) const {
return XMLContentModel::gInvalidTrans;
}
inline bool
SimpleContentModel::handleRepetitions( const QName* const /*curElem*/,
unsigned int /*curState*/,
unsigned int /*currentLoop*/,
unsigned int& /*nextState*/,
unsigned int& /*nextLoop*/,
XMLSize_t /*elementIndex*/,
SubstitutionGroupComparator * /*comparator*/) const
{
return true;
}
XERCES_CPP_NAMESPACE_END
#endif